卷积的意义:加权叠加。更详细的图像卷积和数学理论等,见知乎:https://www.zhihu.com/question/22298352。
数学形态学(Mathematical morphology):包含腐蚀(erode)、膨胀(dilate)、击中击不中、开运算和闭运算等。
腐蚀和膨胀是对白色部分(高亮部分)而言。膨胀是图中高亮部分进行膨胀。腐蚀是高亮部分被腐蚀缩小。拿腐蚀来理解:个人理解,可能有误:就是一个大图A,一个3X3d的图B,称为核(kernel)。如果图A的某个点P,放一个图B那么大的都能放下,那么中间那个点P就是有效的。否则是无效的点。这样到最后就变小了。
方法:
一、首先获得结构元素。包括结构元素的大小和形状。(GetStructuringElement)。保存在Mat类型的变量里,这个变量,定义为Kernel。例如:
var kernal = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(4, 4), new Point(1, 1));
第一个变量:type类型:有rect、cross、ellipse。就是矩形、十字形和椭圆。
第二个变量:内核尺寸。一般有3X3啊之类的
第三个变量:锚点位置。默认-1,-1。 位于中心。十字形内核依赖锚点位置,其他情况下,只影响结果的偏移。
二、进行腐蚀操作。例如
CvInvoke.Erode(gray, gray, kernal, new Point(0, 2), 1, BorderType.Default, new MCvScalar());
第一个变量:Mat对象即可。图像通道数量可以是任意的,但图像深度应为CV_8U、CV_16U、 CV_16S、 CV_32F、 CV_64F其中之一。
第二个变量:需要与源目标一样尺寸和类型。(这里和源是同一个)
第三个变量:null为3X3,参考点在中心。否则定义个kernal。
第四个变量:默认(-1,-1),位于element中心?
第五个变量:迭代使用erode()次数。默认为1.
第六个变量:不用管。new MCvScalar()即可。
opencv参数只需要填三个。其余四个都是默认。Emgucv要填。Emgucv的这两个函数只是增加了CVInvoke前缀而已。
接下来,找轮廓和画出来。
findContours发现轮廓。简单几步就可以监测出物体的轮廓。
先二值化~
CvInvoke.FindContours(gray, contours, hierarchy, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);
然后第一个变量:单通道图像矩阵,可以是灰度图,但更常用的是二值图。一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值化图像。
第二个变量:是一个向量。new一个就行。并且是一个双重向量。最后会保存在这里。里面有什么东西呢?向量内每个元素保存了一组由连续point点构成的集合的向量。每一组point点集就是一个轮廓。有多少轮廓,向量contours就有多少元素。
第三个变量:hierarchy。StackOverFlow上说直接new Mat()即可。对的。本来定义:向量内每一个元素包含4个int变量的向量。保存了i个轮廓的后一个轮廓,前一个轮廓,父轮廓,内嵌轮廓的索引编号。
第四个变量:是int型。四个。
external只监测最外围轮廓。
list监测所有轮廓,但不存在父轮廓、内嵌轮廓。彼此独立。
ccomp监测所有轮廓,建立2个等级关系。
tree监测所有,建立等级树结构。
第五个变量:none是保存边界上所有连续的轮廓到contours向量内。simple是仅保存轮廓的拐点信息,存入contours。
然后画出来。
for (int i = 0; i < contours.Size; i++) { //contours[i]可以变换成矩形。得到这个连通区域的外接矩形 var rect = CvInvoke.BoundingRectangle(contours[i]); //如果高度不足,或者长宽比太小,认为是无效数据,否则把矩形画到原图上 if (rect.Height > 10 && (rect.Width * 1.0 / rect.Height) > 0.2) { rects.Add(rect); //CvInvoke.DrawContours(resuImage, contours, i, color);//画轮廓 CvInvoke.Rectangle(img, rect, color);//画矩形框 } }
补充阅读(opencv):https://blog.csdn.net/dcrmg/article/details/51987348