自学了一段时间的opencvsharp了,目前基本上将库内的基本函数都已经在winform上实现一遍,现在就将我在学习过程中碰到的问题以及想法分享给大家。
首先是配置环境 : vs2019 , .Net Framework4.8 , Opencvsharp4 4.5.5.20211231,
直接在Nuget包管理器内下载这几个就行。
我的软件界面
大概基本将opencvsharp库中的对图像的操作函数基本都已经实现过了。中间也遇到过许多的问题。
以下是我在学习过程中碰到的问题和注意事项。
1、 我们在winform上常用的图像是 Bitmap 和 Image 类型的 ,opencvsharp中的图像为 mat 类型
在使用过程中就需要用到 OpenCvSharp.Extensions.BitmapConverter.ToBitmap() 和 OpenCvSharp.Extensions.BitmapConverter.ToMat()这两个方法来进行格式转换。
![](/qrcode.jpg)
2、 我们常见的彩色图像为 RGB 类型 ,而在OpenCvSharp中对应的是 BGR 类型 ,注意对应通道。
3、调用库内函数时,用一部分对输入图像格式用要求 , 需要使用Mat.ConvertTo()方法来改变图像的格式。
4、BGRA格式图像的应用 ,将BGR图像转换成BGRA图像 可以使用 Mat.ConvertTo() 也能使用
Cv2.CvtColor(), 当然也能自己将BGR图像拆分通道,新建一个通道,在组合成一个新的四通道图像。这样可以自己设置新通道的数值 即 BGRA的alpha值可以改变图像的透明度,注意保存图像的格式要选择支持BGRA图像的格式保存,如.png。下面是我用BGRA图像实现 两个同级picturebox的透明化。
两个picturebox叠放一起, 里面的为BGRA的图像 png格式 ,将里面的picturebox的parent设置为外面的picturebox,调整相应位置,再将里面的picturebox的 BackColor 设置为 Color.Transparent,就能实现下面的结果了。
5、mat图像像素的读写 可以采用 mat.At<>,但我在使用时有时会报错 “赋值左边必须为变量 属性或者索引器”,不知道其原因,我就采用了 mat.Get<>和mat.Set<> 来进行像素的读写。
6、在循环或者线程中定义的mat对象需要及时 释放掉 Mat.Release(); 特别占内存,尤其是在调用摄像头时,要实时获取摄像头的某一帧画面,如果不及时释放掉,经常跑着跑着就内存不足,然后程序就崩了。
7、 Cv2.Rectangle()和Cv2.Line(),这是用来在图像上画矩形和直线的两个方法。但是我在使用时碰到一个问题。就是,当我使用的 mat 是由 new mat(path) 实例化来的时候,画出来的都是正常的,而,当我用的 mat 是由 picturebox的 image 转成 bitmap 再调用 OpenCvSharp.Extensions.BitmapConverter.ToMat() 转换成的mat时,颜色就不一样的。
下面是结果和相应的代码 我不知道其中有什么问题
private void button1_Click(object sender, EventArgs e)
{
string path = @"E:\myPictures\LenaSource\lena_JPG.jpg";
pictureBox1.Image = new Bitmap(path);
pictureBox2.Image = new Bitmap(path);
Mat mm = new Mat(path);
Bitmap bitmap = new Bitmap(pictureBox2.Image);
Mat mm2 = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
OpenCvSharp.Rect rect = new Rect(50, 50, 100, 100);
Cv2.Rectangle(mm, rect, Scalar.Red, 1, LineTypes.AntiAlias);
Cv2.Rectangle(mm2, rect, Scalar.Red, 1, LineTypes.AntiAlias);
//Cv2.Line(mm, 50, 50, 150, 50, Scalar.Red);
//Cv2.Line(mm, 50, 50, 50, 150, Scalar.Red);
//Cv2.Line(mm, 150, 50, 150, 150, Scalar.Red);
//Cv2.Line(mm, 150, 150, 50, 150, Scalar.Red);
//Cv2.Line(mm2, 50, 50, 150, 50, Scalar.Red);
//Cv2.Line(mm2, 50, 50, 50, 150, Scalar.Red);
//Cv2.Line(mm2, 150, 50, 150, 150, Scalar.Red);
//Cv2.Line(mm2, 150, 150, 50, 150, Scalar.Red);
pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mm);
pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mm2);
}
8、调用 Cv2.InvertAffineTransform() 进行反射变换时图像大小为 2*3。
9、调用 Cv2.PyrDown() 和 Cv2.PyrUp() 对图像进行 金字塔采样时, 向上每采样一次 ,图像大小变为原来的4倍 ,向下每采样一次 ,图像大小变为原来的1/4,所以采样次数不宜过多,向上采样次数太大的话,图像没法保存的。
10、在使用picturebox时,一般将picturebox的SizeMode设置为StretchImage,图像自己缩放。 在picturebox的鼠标事件中对图像进行操作时,如用鼠标绘制ROI, 获取到的鼠标位置是相对于picturebox 要转化成相对于图像的,一般等比例转化一下就行,由于取整的问题,可能会有一点偏差,但使用起来效果还行。
11、Cv2.RandShuffle(),随机打乱图像顺序。这个方法我在调用时一直报错 System.AccessViolationException:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
自己这样设置图像也不行,更改次数也不行,
Mat src = new Mat(2, 3, MatType.CV_8UC1);
src.Set<byte>(0, 0, 1);
src.Set<byte>(0, 1, 2);
src.Set<byte>(0, 2, 3);
src.Set<byte>(1, 0, 5);
src.Set<byte>(1, 1, 8);
src.Set<byte>(1, 2, 10);
Cv2.RandShuffle(src, 1);
有知道是什么怎么回事的或者使用成功的欢迎指导。
12、 Cv2.PutText() ,向图像中写入文字,字体不支持中文 可以用 Graphics .DrawString。
13、使用 OCRTesseract 进行文字识别。我之前使用的opencvsharp3,在使用OCRTesseract.Create()进行创建对象时,就会报错"外部组件异常"。我不知道是本地的配置文件有问题还是opencvsharp3不行,后面我换成opencvsharp4之后就能够正常运行了,程序框架需要 .Net Framework 4 .8。
14、使用 FaceRecognizer 人脸识别器时,注意训练集和用来测试的图片大小需要一样的。
15、图像马赛克的原理:将选择马赛克的点的周围部分像素点的像素值都设置成选择点的像素。opencvsharp没有图像的马赛克,但只要知道其原理就能自己实现。
以上就是我在学习opencvsharp过程中总结出来的部分问题以及注意事项,有知道其中问题答案的或者是有其他问题的欢迎一起探讨,共同进步,谢谢。