前言
安装
需要安装两个依赖:
- OpenCvSharp4
- OpenCvSharp4.runtime.win
添加引用
1 | using OpenCvSharp; |
依赖扩展
- OpenCvSharp4.Extensions
其中
OpenCvSharp4.Extensions 主要是一些辅助的工具 比如Mat和Bitmap的互转。
操作步骤
常用操作
Mat和Bitmap互转
1 | //Bitmap转Mat |
读取图片
1 | private void readImg() |
保存
1 | Mat img1 = new Mat("D:\\Pic\\0.jpg", ImreadModes.Color); |
查看效果
方式1
本地保存图片
1 | Cv2.ImWrite("D:\\Pic\\3.jpg", img3); |
方式2
窗口打开图片
1 | private void showImg(Mat img) |
图片模式转换
1 | Mat img10 = new Mat(); |
复制
1 | Mat img2 = new Mat(); |
图片拼接
type表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数),由type()返回,但是返回值是int型,不是OpenCV预定义的宏(CV_8UC1, CV_64FC1…),也就是说你用type函数得到的只是一个int型的数值,比如CV_8UC1返回的值是0,而不是CV_8UC1。
数据类型
U(unsigned integer)表示的是无符号整数,
S(signed integer)是有符号整数,
F(float)是浮点数
方式1
1 | /// <summary> |
调用
1 | List<Mat> mats = new List<Mat>(); |
注意
不同色彩模式的图片不能正常合并,和目标图片的色彩模式也要保持一致,这里使用
matList[0].Type()
设置目标图的模式。默认背景是纯黑色,这里
new Scalar(255, 255, 255)
使图片默认为纯白色。
方式2(不推荐)
使用VConcat()
或HConcat()
拼接则要求待拼接图像有相同的宽度或高度
1 | /// <summary> |
调用方式
1 | List<Mat> mats = new List<Mat>(); |
灰度
1 | /// <summary> |
二值化
1 | /// <summary> |
腐蚀与膨胀
腐蚀与膨胀都是针对白色区域的
- 腐蚀 白色变少 黑色变多
- 膨胀 白色变多 黑色减少
示例
1 | /// <summary> |
高斯模糊
1 | /// <summary> |
缩放
1 | /// <summary> |
旋转
其中方式1和方式2都一样,都只能旋转90的倍数。
方式3可以旋转任意角度,但是如果是长方形就会部分无法显示。
所以
- 旋转
90的倍数
推荐方式1
。 - 旋转
其他角度
推荐方式3
。
方式1
1 | public static Mat rotate90Counter(Mat source) |
其中方向
1 | public enum RotateFlags |
方式2
逆时针90
1 | /// <summary> |
顺时针90
1 | /// <summary> |
旋转180
1 | /// <summary> |
总结一下:
- 需逆时针90°旋转时
Transpose(src,tmp) + Flip(tmp,dst,0)
需顺时针90°旋转时
Transpose(src,tmp) + Flip(tmp,dst,1)
需180°旋转时
Flip(src,dst,-1)
Transpose()简单来说,就相当于数学中的转置,在矩阵中,转置就是把行与列相互调换位置;
相当于将图像逆时针旋转90度,然后再关于x轴对称
枚举
1 | public enum FlipMode |
方式3
旋转任意角度
这种方式如果是长方向旋转90度会导致黑边和遮挡。
1 | /// <summary> |
透视变形
获取黑块顶点
1 | using OpenCvSharp; |
透视变形
1 | using OpenCvSharp; |
调用
1 | //透视变形 |
剪裁
1 | // 截取左上角四分之一区域 |
文件名
1 | public class ZPathUtil |
是否涂卡
1 | /// <summary> |
注意传入的原图一定要二值化。
绘制边框
1 | Mat img10 = new Mat(); |
注意
黑白图片转为彩色
查找轮廓
实现框选用户选择的选项
1 | /// <summary> |
调用方式
1 | int rows = mat4.Rows; |
获取面积
1 | //获取涂写区域 |
其中Cv2.CountNonZero(matTemp)
是获取非0的像素点个素数,所以在二值化的图片中,用户涂的区域都是0,我们只需要获取涂的百分比就能判断用户是否涂卡。
获取答题卡涂的选项
其中每个选项的坐标区域是在制作答题卡的时候,后台要保存的。
1 | int[][][] ques_select = new int[][][] { |
页码识别
页面我们可以转换为二进制然后进行黑块渲染,识别的时候后在转成数字即可。这里是页码从1开始,所以要减1。
1 | /// <summary> |
工具类
基本操作
CvCommonUtils
1 | using OpenCvSharp; |
获取边界
CvContoursUtils
1 | using OpenCvSharp; |
透视变形
CvPerspectiveUtils
1 | using OpenCvSharp; |
查看代码执行时间
1 | using System.Diagnostics; |
计时实例可以使用多次
1 | System.Diagnostics.Stopwatch oTime = new System.Diagnostics.Stopwatch(); |