AI图像标注软件:WPF-LabelImg
AI图像标注软件:WPF-LabelImg
WPF-ROI控件设计
一 AI图像标注软件:WPF-LabelImg使用教程
项目方案



WPF-LabelImg 项目掌握教程
一、项目概述
WPF-LabelImg 是一个基于 WPF(Windows Presentation Foundation) 开发的图像标签标记工具,主要用于机器学习训练数据的标注工作。该项目提供了直观的图形界面,支持绘制矩形标注框、导入/导出 YOLO 格式标签文件等功能。
二、项目结构解析
2.1 整体架构
WPF-LabelImg-发布/
├── Solution/ # 解决方案文件
│ └── WPF-LabelImg.sln # Visual Studio 解决方案
├── Source/ # 源代码目录
│ ├── Apps/ # 应用程序层
│ │ └── H.App.LabelImg/ # 主应用(核心业务)
│ ├── Controls/ # 自定义控件
│ │ └── H.LabelImg.ShapeBox/ # 形状绘制控件
│ └── WPF-Control/ # 通用WPF控件库(基础框架)
└── Document/ # 文档资源
2.2 核心模块说明
| 模块 | 职责 | 关键文件 |
|---|---|---|
| H.App.LabelImg | 主应用程序,包含业务逻辑和界面 | MainWindow.xaml, App.xaml.cs |
| H.LabelImg.ShapeBox | 形状绘制控件,处理标注框的渲染和交互 | ShapeBox.xaml.cs, RectShape.cs |
| WPF-Control | 通用控件库,提供基础 UI 组件 | 各种 Controls 和 Modules |
三、快速上手:运行项目
3.1 环境要求
- IDE: Visual Studio 2022 或更高版本
- 框架: .NET 8.0 (Windows)
- 数据库: SQLite(嵌入式,无需额外安装)
3.2 运行步骤
-
打开解决方案
双击 Solution/WPF-LabelImg.sln -
设置启动项目
- 在解决方案资源管理器中右键点击
H.App.LabelImg - 选择 设为启动项目
- 在解决方案资源管理器中右键点击
-
编译运行
- 按
F5或点击工具栏的 开始调试 按钮 - 首次运行会自动创建 SQLite 数据库文件
- 按
3.3 验证运行
成功启动后,你将看到如下界面:
- 左侧:项目管理、收藏夹、过滤器面板
- 中间:图像预览和标注区域
- 右侧:详情、编辑、标签列表面板
四、核心组件深度剖析
4.1 主窗口架构(MainWindow.xaml)
主窗口采用 OutlookBar 布局模式,分为三个主要区域:
<!-- 左侧面板:项目管理和过滤器 -->
<h:OutlookBar DockPanel.Dock="Left">
<h:OutlookSection Header="项目管理">...</h:OutlookSection>
<h:OutlookSection Header="收藏夹">...</h:OutlookSection>
<h:OutlookSection Header="过滤器">...</h:OutlookSection>
<h:OutlookSection Header="排序器">...</h:OutlookSection>
</h:OutlookBar>
<!-- 中间区域:图像展示和标注 -->
<ContentPresenter Content="{Binding}" />
<!-- 右侧面板:详情和编辑 -->
<h:OutlookBar DockPanel.Dock="Right">
<h:OutlookSection Header="详情">...</h:OutlookSection>
<h:OutlookSection Header="标签列表">...</h:OutlookSection>
</h:OutlookBar>
关键绑定说明:
DataContext="{Binding Source={x:Static h:IocProject.Instance}, Path=Current.File}"- 使用静态 IOC 容器获取当前项目的文件数据
ItemsSource="{Binding Collection}"- 绑定文件集合到列表控件
4.2 形状绘制控件(ShapeBox)
ShapeBox 是项目的核心标注控件,负责图像渲染和形状绘制:
public class ShapeBox : FrameworkElement, IShapeView
{
// 视觉层:图像层 + 形状层
private ImageDrawingVisual _imageDrawingVisual;
private ShapeDrawingVisual _shapeDrawingVisual;
// 依赖属性
public ImageSource ImageSource { get; set; } // 绑定图像源
public ObservableCollection<IShape> Shapes { get; set; } // 形状集合
// 绘制方法
public void DrawShapes()
{
using var drawingContext = _shapeDrawingVisual.RenderOpen();
foreach (var shape in shapes)
{
shape.Draw(this, drawingContext, Stroke, strokeThickness, Fill);
}
}
}
设计亮点:
- 使用 VisualCollection 实现分层渲染(图像层在底层,形状层在顶层)
- 支持缩放自适应(
ToViewThickness方法处理缩放时的边框粗细)
4.3 矩形形状(RectShape)
RectShape 实现了标注框的核心逻辑:
public class RectShape : TitleShapeBase, IRectShape, IBoundingBoxable, IThumbShape
{
public Rect Rect { get; set; } // 标注框的矩形区域
public override void Drawing(IView view, DrawingContext dc, Pen pen, Brush fill)
{
if (this.Rect.IsZoreOrEmpty()) return;
// 绘制矩形
dc.DrawRectangle(fill, pen, Rect);
// 绘制标题(标签名称)
DrawTitle(view, dc, Rect.TopLeft, pen.Brush, 10 / view.Scale, 10 / view.Scale);
// 可选:绘制交线和尺寸
if (UseCross) { ... }
if (UseText) { ... }
}
// 创建控制点(用于拖拽调整)
protected override IEnumerable<IHandle> CreateHandles()
{
yield return new ActionHandle(x => this.Rect = new Rect(x, this.Rect.BottomRight),
this.Rect.TopLeft, this);
yield return new ActionHandle(x => this.Rect = new Rect(this.Rect.TopLeft, x),
this.Rect.BottomRight, this);
}
}
4.4 项目管理(FileProjectItem)
项目数据管理采用 Repository 模式:
public class FileProjectItem : ProjectItemBase
{
public string BaseFolder { get; set; } // 图像文件目录
public ObservableCollection<LabelItem> Labels { get; set; } // 标签类别
// 数据库绑定的文件仓储
public IRepositoryBindable<fm_dd_image> File { get; set; }
public override bool Load(out string message)
{
// 配置数据库连接
DbIoc.ConfigureServices(dx =>
{
dx.AddDbContext<DataContext>(x =>
{
string con = $"Data Source={this.GetFilePath()}";
x.UseLazyLoadingProxies().UseSqlite(con);
});
});
// 迁移数据库并加载数据
DataContext context = DbIoc.Services.GetService<DataContext>();
context.Database.Migrate();
this.File = DbIoc.GetService<IRepositoryBindable<fm_dd_image>>();
this.File.RefreshData();
return true;
}
}
4.5 YOLO 格式解析器(YoloTxtParser)
支持导入/导出 YOLO 格式的标签文件:
public class YoloTxtParser
{
public List<fm_dd_label> ParseYoloFile(fm_dd_image imageInfo, Dictionary<int, string> classMapping)
{
string txtFilePath = Path.ChangeExtension(imageInfo.Url, ".txt");
if (!File.Exists(txtFilePath)) return new List<fm_dd_label>();
string[] lines = File.ReadAllLines(txtFilePath);
foreach (string line in lines)
{
// YOLO格式: <class_id> <center_x> <center_y> <width> <height>
var label = ParseYoloLine(line, imageInfo, classMapping);
labels.Add(label);
}
return labels;
}
// 转换归一化坐标到像素坐标
private Rect ConvertToPixelBoundingBox(double centerX, double centerY,
double width, double height,
int imageWidth, int imageHeight)
{
double x = centerX * imageWidth - (width * imageWidth / 2);
double y = centerY * imageHeight - (height * imageHeight / 2);
return new Rect(x, y, width * imageWidth, height * imageHeight);
}
}
五、数据模型设计
5.1 数据库模型
项目使用 Entity Framework Core + SQLite 存储数据:
| 表名 | 说明 | 关键字段 |
|---|---|---|
fm_dd_images |
图像文件信息 | Url, PixelWidth, PixelHeight |
fm_dd_labels |
标签标注信息 | LabelName, BoundingBox, LabelColor |
5.2 实体类结构
// 图像实体
public class fm_dd_image : ObservableObject
{
public int Id { get; set; }
public string Url { get; set; } // 文件路径
public int PixelWidth { get; set; } // 像素宽度
public int PixelHeight { get; set; } // 像素高度
public string Tags { get; set; } // 分类标签(JSON)
public int Score { get; set; } // 评分
public bool IsFavorite { get; set; } // 是否收藏
}
// 标签实体
public class fm_dd_label : ObservableObject
{
public int Id { get; set; }
public string LabelName { get; set; } // 标签名称
public Rect BoundingBox { get; set; } // 边界框
public Color LabelColor { get; set; } // 标签颜色
public int ImageId { get; set; } // 关联图像ID
}
六、核心业务流程
6.1 创建新项目
用户点击"新建项目" → FileProjectService.Create() → 创建项目目录和数据库 → 加载空项目
关键代码(App.xaml.cs):
services.AddProject<FileProjectService>();
6.2 标注工作流
打开项目 → 选择图像 → 绘制标注框 → 设置标签名称 → 保存到数据库
6.3 导出 YOLO 格式
选择导出 → 遍历所有图像 → 生成 .txt 文件(归一化坐标)→ 生成 classes.txt
七、扩展开发指南
7.1 添加新的标注形状
- 实现 IShape 接口:
public class CircleShape : ShapeBase, IShape
{
public Point Center { get; set; }
public double Radius { get; set; }
public override void Draw(IView view, DrawingContext dc, Brush stroke,
double strokeThickness, Brush fill)
{
dc.DrawEllipse(fill, new Pen(stroke, strokeThickness), Center, Radius, Radius);
}
}
- 注册到 ShapeBox:
在ShapeBox.DrawShapes()方法中添加新形状的绘制逻辑。
7.2 添加新的过滤器
- 继承 FileFilter 基类:
public class CustomFileFilter : FileFilter
{
public override bool Filter(fm_dd_image item)
{
// 自定义过滤逻辑
return item.Score >= 8;
}
}
- 在 UI 中注册:
<local:CustomFileFilter Name="高分图像" Value="True" />
7.3 添加新的排序器
public class FileOrderByCreateTime : OrderBase<fm_dd_image>
{
public override string Name => "按创建时间排序";
public override IOrderedEnumerable<fm_dd_image> Order(IEnumerable<fm_dd_image> source)
{
return source.OrderBy(x => x.CreateTime);
}
}
八、调试技巧
8.1 查看数据库内容
数据库文件路径:项目目录/项目名称.db
使用工具:
- DB Browser for SQLite(免费开源)
- Visual Studio SQLite 扩展
8.2 调试形状绘制
在 ShapeBox.DrawShapes() 方法中添加断点,观察 Shapes 集合的内容。
8.3 日志查看
项目使用 Log4net 记录日志,日志文件位于:
%AppData%\H.App.LabelImg\Logs\
九、常见问题
Q1:如何导入已有标签?
A:使用菜单"编辑" → “导入YOLO TXT文件”,确保 .txt 文件与图像文件同名且在同一目录。
Q2:如何批量处理图像?
A:在项目设置中配置 BaseFolder,系统会自动扫描该目录下的所有图像文件。
Q3:标签颜色如何自定义?
A:在右侧"标签列表"面板中,点击标签项可以修改颜色属性。
Q4:如何导出标注数据?
A:使用菜单"编辑" → “导出YOLO TXT文件”,会在图像目录生成对应的 .txt 文件。
十、学习路径建议
第1周:熟悉项目结构和基本操作
└─ 运行项目,体验标注流程
└─ 阅读 MainWindow.xaml 和 App.xaml.cs
第2周:深入核心控件
└─ 学习 ShapeBox 的渲染机制
└─ 理解 RectShape 的交互逻辑
第3周:掌握数据层
└─ 学习 DataContext 和实体模型
└─ 理解 Repository 模式的应用
第4周:扩展开发
└─ 尝试添加自定义过滤器或排序器
└─ 实现新的标注形状
第5周:高级主题
└─ 学习 IOC 容器的配置
└─ 理解模块系统(Modules)的设计
十一、资源推荐
- 官方文档: https://hebiangu.github.io/WPF-Control-Docs
- WPF 学习: https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/
- Entity Framework Core: https://learn.microsoft.com/zh-cn/ef/core/
通过以上内容,你应该已经对 WPF-LabelImg 项目有了全面的了解。建议从运行项目开始,逐步深入各个模块的源码,结合调试工具理解其工作机制。如果遇到具体问题,可以随时进一步探讨!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)