目录
1 任务与目的
2 方案总体设计
3 C#界面设计
4 OpenCVSharp功能实现
5 打包与运行
6 总结
本次任务是设计一个能够实现OpenCV部分功能的图像处理软件。目的在于方便图像处理人员在具体编写OpenCV程序前,提前能够对图像进行简单处理,进而帮助开发人员分析该如何对图像进行处理。
使用C#对界面和逻辑进行开发。界面开发的工具有很多,例如使用C++与QT进行开发。OpenCV针对C++有专用的库,与QT也有良好的支持,但是开发时间与C#比较长,并且生成的应用程序安装包较大。不光是OpenCV相关的库文件需要打包进应用程序安装包,还有QT界面相关的库文件也需要添加。过大的应用程序相当于简单的功能,两者并不协调,所以使用C#进行界面逻辑的开发更为快捷方便。
使用OpenCVSharp实现图像处理功能。在目前针对C#的计算机视觉库主要有两种,EmguCV和OpenCVSharp。EmguCV的优势在于不仅仅提供了计算机视觉函数接口并且提供了一系列界面控件接口,但目前只支持OpenCV1的书写风格。但是是通过把C++封装成动态链接库在C#中调用,这样在修改算法的过程中就会非常的不方便,封装DLL的时候也比较麻烦。对于OpenCVSharp的工具,从名字就可以看出其是OpenCV提供给C#的接口。OpenCVSharp是OpenCV的.NET wrapper,它比EmguCV更接近于原始的OpenCV。网上常见的免费版EmguCV则是GUN协议,任何发表都需要至少公布你的源代码,相比之下OpenCVSharp则是相对温和多的LGUN协议,对商业应用友好(基本上相当于BSD)。OpenCVSharp提供了OpenCV和OpenCV2两种书写风格。因此设计使用OpenCVSharp进行图像处理的功能实现。
以下是方案对比表:
表1-1 不同方案对比表
开发方案对比 |
C# |
C++&QT |
原始OpenCV |
\ |
界面开发速度较快 库文件调用方便 安装包大 商业友好 |
EmguCV |
界面开发速度快 库文件调用不方便 安装包较大 商业不友好 |
\ |
OpenCVSharp |
界面开发速度快 库文件调用方便 安装包较小 商业友好 |
\ |
因此选用C#与OpenCVSharp搭配在VS2017下进行图像处理软件的开发。
设计的应用程序用于进行简单的图像处理功能,因此考虑包含以下功能:
表2-1 设计功能表
功能 |
基本方法 |
打开图片 |
C#中OpenFileDialog控件 |
保存图片 |
C#中SaveFileDialog控件 |
开\关摄像头 |
OpenCVSharp的VideoCapture方法 |
图像处理功能选择 |
C#中ListBox控件 |
图像处理 |
OpenCVSharp的各类图像处理方法 |
图像显示 |
C#中PictureBox控件 |
图像处理步骤队列 |
C#中ListBox控件 |
消息通知 |
C#中TextBox控件 |
图像处理功能参数调整 |
C#中NumericUpDown控件 |
要实现以上各项功能,除了使用表中第二列所示的基本方法外,还需要将C#控件与OpenCVSharp中的各类图像处理方法紧密联系。
设计将图像处理功能选择ListBox与OpenCVSharp的各类图像处理方法一一对应,而方法的各项参数统一存放在一个多维数组里,C#中NumericUpDown控件在执行图像处理功能参数调整的时候通过调取这个多维数组,来实现修改参数的功能。用户通过点击选择图像处理功能,对图像处理步骤队列ListBox中的元素进行添加,程序内部通过判断这些元素及其排列,选择对应的OpenCVSharp图像处理方法对图像进行处理。
这些步骤的简化示意图如下:
图2-1 设计相关示意图
以下将详细介绍C#界面的设计和OpenCVSharp功能实现。
在一个C#窗体中添加需要的控件,主要包括:按键(Button)、列表(ListBox)、图像显示窗(PictureBox)、文字显示窗(TextBox)等。对各控件属性进行设置,例如按键名称、功能选择列表元素等。
程序由个人独立开发,设计一个独特的图标和应用程序名称,由本人命名为“sa蛋OpenCV试验器”。
显示效果如图所示:
图3-1 主C#窗体控件布局效果
布局与界面效果设计完成后,对各个控件进行逻辑编程。
打开图片功能与摄像头功能同时开启并不方便图像显示,因此当摄像头开启时,点击“打开图片”按键不弹出文件选择界面,同时在“通知消息显示”中通知应先关闭摄像头再打开图片。打开文件功能由C#的OpenFileDialog类实现,相关程序如下图所示:
图3-2 打开图片功能部分程序图
选择要打开的文件后,OpenFileDialog类的FileName变量会返回文件地址。
保存图片功能实现与打开图片步骤类似。
点击“打开摄像头”按钮后,会触发此按钮的点击事件,从而执行如下程序:
private void button3_Click(object sender, EventArgs e)
{
camera = new VideoCapture(0);
cameraopen = true;
VideoCapture为OpenCVSharp所提供的摄像头类,可以方便快捷地开启摄像头;cameraopen为自定义的bool型标识符,由于表示摄像头是否已开启。
关闭摄像头代码如下:
private void button4_Click(object sender, EventArgs e)
{
if(cameraopen == true)
{
camera.Dispose();
cameraopen = false;
使用VideoCapture类的Dispose()方法即可关闭摄像头。
点击“使用说明”按钮弹出一个消息显示窗体,此窗体由C#的MessageBox类实现,程序如下:
private void button7_Click(object sender, EventArgs e)
{
MessageBox.Show("此为传感器理论与研究方法……", "使用说明", MessageBoxButtons.OK);
}
MessageBox类的Show()方法的第一个参数为显示消息内容,第二个参数为窗体标题,第三个参数为窗体添加的按键,此窗体添加一个确定按钮。
显示效果如图:
图3-3 使用说明功能
点击“刷新图像”后,执行以下程序:
image1 = new Mat(my_imagesource);
image2 = new Mat();
image2 = myOPENCV_run(image1, image2);//运行
主要通过myOPENCV_run()方法将打开的图像进行处理,此方法为自定义方法,用于执行OpenCVSharp图像处理功能,在第四节详细说明。
点击“图像显示”后,执行以下程序:
pictureBox1.Image = image2.ToBitmap();
MAT类的ToBitmap()方法,作用是将一个MAT图转换为正常可以显示的图片,传给PictureBox进行显示。
通知消息使用TextBox控件,通知消息需要能够翻阅,即每次通知消息都是接着已有的通知信息进行添加。程序如下:
textBox1.AppendText("\r\n图片刷新完成!");
textBox1.SelectionStart = this.textBox1.TextLength;
textBox1.ScrollToCaret();
TextBox类的AppendText()方法用于添加文字信息,SelectionStart用来将光标移至最后,使用ScrollToCaret()方法使TextBox始终保持显示最新一行的文字。
点击左侧列表进行功能选择,首先弹出对应功能的参数设置界面,设计第二个窗体用于设置参数。如下图所示:
图3-4 设置参数界面
每项功能都对应有四个参数,定义一个数组用于存放这些参数,数组的行下标就是对应的枚举过的参数名。数组定义如下:
public static int[,] myOPENCV_value = new int[60 , 4]; //用于存放各方法中的参数
当点击确定时,数组的参数被修改为设定值,同时此窗体,将选择的元素添加进图像处理列表。
图像处理需要按使用者选择的功能顺序进行执行,是一个有序的操作。重新定义一个数组专门用来存放使用者选择出来的功能参数,与功能列表定义的数组不同的是,前者要多一列用来存放功能对应的序号,其他均相同。这样的作用是,可以对数组存放序号的列进行依次检索,从而能够按使用者选择的顺序进行执行图像处理功能。此数组定义如下:
public int[,] myOPENCV_runlist = new int[20, 5];//运行步骤列表,与myOPENCV_value不同的是,运行步骤限定为20步,列的第一个元素存放运行功能序号
点击图像处理步骤列表的元素,同样弹出参数设置窗口。这时将窗体的删除按钮等显现,实现对已经选择功能的删除功能。删除或中间插入其他功能都需要对列表元素进行添加或删除,与此同时也要对数组的行元素进行删除或插入。使用循环即可完成上述步骤。
至此已大致介绍完实现此软件界面使用的逻辑和方法,下面介绍录入应用程序的部分OpenCVSharp图像处理功能实现。
初始设想能够实现60种以上的基本图像处理功能,由于设计开发的时间有限,个人的能力水平也有待提高,因此只添加了较为基础的27种功能。
功能名称与OpenCVSharp中对应方法如下表:
表4-1 录入的OpenCVSharp功能名称表
功能 |
OpenCVSharp中对应方法(函数)名称 |
颜色空间转换 |
CvtColor |
方框滤波 |
BoxFilter |
均值滤波 |
Blur |
高斯滤波 |
GaussianBlur |
中值滤波 |
MedianBlur |
双边滤波 |
BilateralFilter |
膨胀 |
Dilate |
腐蚀 |
Erode |
高级形态学变换 |
MorphologyEx |
漫水填充 |
FloodFill |
尺寸放大 |
PyrUp |
尺寸缩小 |
PyrDown |
尺寸调整 |
Resize |
固定阈值化 |
Threshold |
边缘检测CANNY |
Canny |
边缘检测SOBEL |
Sobel |
边缘检测LAPLACIAN |
Laplacian |
边缘检测SCHARR |
Scharr |
图像快速增强 |
ConvertScaleAbs |
图像融合 |
AddWeighted |
霍夫标准变换 |
HoughLines |
霍夫累计概率变换 |
HoughLinesP |
霍夫圆变换 |
HoughCircles |
重映射 |
Remap |
仿射变换 |
WarpAffine |
直方图均衡化 |
EqualizeHist |
人脸识别 |
DetectFace |
上表功能均单独进行了实现,通过检索图像处理步骤数组myOPENCV_runlist时,依次判断其每一行的第一个元素,其中存放的为对应功能的序号(序号为已经枚举化的功能名称)。通过依次识别出的序号,一步一步执行对应的图像处理功能,这一步骤由一个for循环加一个大型的switch-case实现,部分代码如下:
for (int i = 0 ; i< listBox2.Items.Count ; i++)
{
switch((myOPENCV)myOPENCV_runlist[i,0])
{
case myOPENCV.cvt_color: // myOPENCV为一个自定义枚举类型
执行对应图像处理方法时,将数组保存的参数带入,即可实现功能的参数使用。
在VS2017中使用Microsoft Visual Studio Installer Project生成一个安装包工程,在工程中对使用到的库文件、图片、数据等进行添加。如下图所示:
图5-1 安装包工程
在项目属性中设置安装文件名称、快捷方式、文件夹等。进行完上述步骤后即可生成一个安装包文件。由于添加了使用到的所有库文件,因此其他Windows用户安装完后,大部分也可以正常使用。
安装后虽然能够正常使用,但并不符合“小巧便捷”的最初设想。因此使用Enigma Virtual Box打包软件将安装后的程序目录进行再次打包,生成一个可以直接执行无需安装的exe文件。如下图所示:
图5-2 可直接执行的exe文件
至此设计基本完成,下面对软件进行简单测试:
效果图如下:
图5-3 测试人脸识别
需要注意的是,部分功能对输入的图像有严格要求,例如“直方图均衡化”需要输入一个单通道的图像,这时需要先进行“颜色空间转换”,将图像转换为灰度图后再进行下一步操作。若不按要求添加功能,多数会导致程序出错。
至此project已经暂时完成,其实还有很多的设想都没来得及实现,比如如何在程序出错时不会崩溃、如何优化参数设置界面、如何添加更多更有用的图像处理功能。