N年没有写博客了2333,大三以后基本上都在开发一些项目,项目本身又不好写博客TT,所以好久好久没动过了,现在在做一个机器视觉方向的实习,刚好可以研究倒腾一下,然后给自己开个小坑,八月份看看能不能倒腾一下badusb。

图片格式转换以及彩色转黑白模块

Halcon开发

首先我们要在halcon上把整个处理逻辑跑通,halcon是一个工业领域的机器视觉软件库,他提供很多有关图像处理的算子来帮助处理图像,算子就类似于封装好的函数,可以在编写程序的时候提高效率,要实现图片彩色转黑白,我们首先第一步是读入图片并且获得到一些基本信息,包括图片展示,宽高。

read_image (Image, 'background/6355071687f84cfcb2cb002f9073f5a4.jpg')
get_image_size (Image, Width, Height)
originalWidth:=Width
originalHeight:=Height
if(Width>800 or Height>800) //预览图片时将图片等比缩小,避免图片太大占满窗口
Scale:=1.0
if(Width>Height)
Scale:=800.0/Width
else
Scale:=800.0/Height
endif
Width:=Width*Scale
Height:=Height*Scale

endif
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
zoom_image_size(Image, ResizedImage, Width, Height, 'constant') //ResizedImage就是重置大小后的图片
dev_display (ResizedImage)

stop ()

halcon中可以使用函数stop()来打断点,方便调试,运行结果如下

然后就是简单的调用转换模块

rgb1_to_gray(Image,GrayImage)  //转换
//预览
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_display (GrayImage)

stop()
//写出图片,也就是修改格式
write_image(GrayImage,'png',0,'background/6355071687f84cfcb2cb002f9073f5a4(gray).png')
write_image(GrayImage,'jpg',0,'background/6355071687f84cfcb2cb002f9073f5a4(gray).jpg')

最后一步就是导出为C#文件,依次点击文件———->导出

至此halcon开发环节结束,我们得到了一个C#文件,接下来就是联合开发中的C#部分

C#开发

在导出C#文件之后,我们需要在visual studio里面新建工程,这里说个题外话,vscode我发现还是有不少坑,搞不定比如添加引用就很麻烦,因此选了visual studio。visual studio新建项目,选择Windows窗体应用就可以得到一个新的工程

在新建完工程之后,需要引入halcon动态dll库,呃有点像java的导包,需要在解决方案资源管理器里右键引用

使用预览找到halcondotnet.dll,这个文件没有以外的话应该是在你的halcon文件夹下的bin目录里,引入成功后就去工具箱右键选择项添加halcon对应的组件,引用的文件跟上面是一样的,也是halcondotnet.dll。引入的组件就是两个。

最后进行简单的拖拽把窗体布局放好,大概放个样子就行

左边的黑窗可以像halcon一样展示图片,button按钮逻辑可以自行编写,比如点击按钮,图片转换开始。另外我们从halcon导出的代码比较长,我们只要找到action函数并将它复制到button按钮的逻辑里就行,当然不是说100%复制就行,还得阅读一下理解一下。

C#完善

在简单把导出的代码复制粘贴过来之后还需要写一些东西让他变得更“智能”,比如很多变量不能直接写死,在把主要功能粘贴成功后我们点运行就能得到一个窗口了:

接下来就是一些完善工作了,比如按钮的更人性化的操作等等

Opencv的初步探索

因为halcon的库要钱( ,所以如果要做一个工具箱,最好呢还是用免费的库,which is opencv 😋,这里我第一次使用opencv,所以还得从最开始的配置环境做起,我尝试了分别从两种项目引入opencv,一种是最普通原始的c++项目引入,另一种就是前面做的C#窗体项目中引入opencv

原始C++引入

看着傻瓜教程一步一步配就好,注意你下载的opencv的版本和链接器里的版本保持一致就行,不然找不到

比如我这里是4.10.0版本就写opencv_world4100.lib。配置好之后跑一个小例子能跑通说明引入成功了。哦好像opencv需要添加一下环境变量,添加成功后应该是在终端输入“opencv_version”能看到版本号。到这就算是引入成功了,不过我也没打算在C++项目上用opencv,所以就点到为止了,重点在后面的C#窗体项目。

C#窗体项目引入

C#窗体项目就有点抽象了,踩了一点坑。首先要找到nuget包管理器,在包管理器里面操作

找到opencv,勾上项目,安装

当时这里就撞上了一个很逆天的坑,安装不了,每一次点安装,vs弹出来一个许可证书,点击接受之后,又弹回去了,压根安装不上,还没有报错信息,错误列表全空,根本不知道哪里有问题… 后来看错误列表旁边的输出,发现是.net框架版本不对,右键项目————->属性,修改框架版本

目标框架原本是用的4.5,安装不上,改成4.7,能安装了,这个坑搞得有点蛋疼,因为他没有报错信息,每次尝试安装就自动回滚,需要自己去找原因。至此C#窗体应用成功引入opencv,在对应的cs文件下使用命令 using OpenCvSharp 即可使用opencv。

opencv库函数探索

这里就是对opencv瞎玩儿,看看基本的功能,首先是读入展示图片,新建个Mat对象来保存图片,直接用ImShow函数展示图片

Mat src = Cv2.ImRead("C:/testImg01.jpg", ImreadModes.Color);
Cv2.ImShow("dst", src);

模板匹配

上传一个模板图片,一个目标图片,目标是找到图片中的模板,

Cv2.MatchTemplate(target, template, result, TemplateMatchModes.CCoeffNormed);
// 找到最佳匹配位置
Cv2.MinMaxLoc(result, out double minVal, out double maxVal, out OpenCvSharp.Point minLoc, out OpenCvSharp.Point maxLoc);
OpenCvSharp.Point matchLoc = maxLoc;
// 在目标图像上用绿色矩形框标记匹配的位置
Cv2.Rectangle(target, matchLoc, new OpenCvSharp.Point(matchLoc.X + template.Cols, matchLoc.Y + template.Rows), Scalar.Blue, 2);

target是目标图片,template是模板图片,模板匹配得到的result是一个结果矩阵,我们要找到这个矩阵里的最大值,maxval就是最大值,maxloc就是这个矩阵的位置,根据位置可以得到matchloc,这是最佳匹配图像的左上角的点,因此就可以绘制出一个把模板框在里面的框框了。

这是一个理想的情况,找到符合条件的模板,然后就是翻车的情况

这个是匹配的时候多匹配了一个部分,但是这部分照理来说是要排除的,然后还有一种情况是分不清模板的,这个结果太抽象了,我也不知道应该怎么做233333

-————————————————————————————————————————-(手动分割线)——————————————————————

2333我又可以了笑死,把模板差值提高0.1,确定在0.6的时候他就能够分清不同模板了

double threshold= 0.6;
if (maxVal >= threshold)
{
// 绘制矩形框标记出最佳匹配位置
OpenCvSharp.Point matchLoc = maxLoc;
Cv2.Rectangle(target, matchLoc, new OpenCvSharp.Point(matchLoc.X + template.Cols, matchLoc.Y + template.Rows), Scalar.Green, 2);
}

嘻嘻,这样就可以了,要注意的是如果模板本身是不对称的或者不规则的,需要不断旋转模板来跟图片比对,每旋转一次比对一次,还是有那么一点麻烦的。