卷积就是循环对图像跟一个核逐个元素相乘再求和得到另外一副图像的操作,比如结果图中第一个元素5是怎么算的呢?原图中3×3的区域与3×3的核逐个元素相乘再相加:
5=1×1+2×0+1×0+0×0+1×0+1×0+3×0+0×0+2×2
算完之后,整个框再往右移一步继续计算,横向计算完后,再往下移一步继续计算。
简而言之,卷积是一个对应位置像素值相乘后再相加的操作。
转载此文
最基本的形态学操作有二:腐蚀与膨胀(Erosion 与 Dilation)。 他们的运用广泛:
消除噪声
分割(isolate)独立的图像元素,以及连接(join)相邻的元素。
寻找图像中的明显的极大值区域或极小值区域。
此操作将图像 A 与任意形状的内核 (B),通常为正方形或圆形,进行卷积。
内核 B 有一个可定义的 锚点, 通常定义为内核中心点。
进行膨胀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” (因此有了术语膨胀 dilation )。对上图采用膨胀操作我们得到:
原图
膨胀
背景(白色)膨胀,而黑色字母缩小了
Mat element = getStructuringElement( erosion_type, //设定卷积核的形状
Size( 2*erosion_size + 1, 2*erosion_size+1 ),//设定卷积核的大小
Point( erosion_size, erosion_size ) );//表示描点的位置,一般 c = 1,表示描点位于中心
// 腐蚀操作
erode( src, erosion_dst, element );
它提取的是内核覆盖下的相素最小值。
进行腐蚀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最小相素值提取,并代替锚点位置的相素。
从下面的结果图我们看到亮区(背景)变细,而黑色区域(字母)则变大了。
原图
腐蚀
Mat element = getStructuringElement( erosion_type, //设定卷积核的形状
Size( 2*erosion_size + 1, 2*erosion_size+1 ), //设定卷积核的大小
Point( erosion_size, erosion_size ) ); //表示描点的位置,一般 c = 1,表示描点位于中心
//膨胀操作
dilate( src, dilation_dst, element );
开运算是通过先对图像腐蚀再膨胀实现的,开运算断开前景连接,抑制亮细节。
dst = open( src, element) = dilate( erode( src, element ) )
能够排除小团块物体(假设物体较背景明亮)。
请看下面,左图是原图像,右图是采用开运算转换之后的结果图。 观察发现字母拐弯处的白色空间消失。
闭运算是通过先对图像膨胀再腐蚀实现的,闭运算闭合前景连接,抑制暗细节。
dst = close( src, element ) = erode( dilate( src, element ) )
能够排除小型黑洞(黑色区域)。
膨胀图与腐蚀图之差
dst = morph_{grad}( src, element ) = dilate( src, element ) - erode( src, element )
能够保留物体的边缘轮廓,如下所示:
原图像与开运算结果图之差,将突出比原轮廓亮的部分。
dst = tophat( src, element ) = src - open( src, element )
闭运算结果图与原图像之差,将突出比原轮廓暗的部分。
dst = blackhat( src, element ) = close( src, element ) - src
Mat element = getStructuringElement( morph_elem, //设定卷积核的形状
Size( 2*morph_size + 1, 2*morph_size+1 ), //设定卷积核的大小
Point( morph_size,morph_size ) ); //表示描点的位置,一般 c = 1,表示描点位于中心
// 运行指定形态学操作
morphologyEx( src, dst, operation, element );
/*operation: 需要运行的形态学操作。 我们有5个选项:
Opening: MORPH_OPEN : 2
Closing: MORPH_CLOSE: 3
Gradient: MORPH_GRADIENT: 4
Top Hat: MORPH_TOPHAT: 5
Black Hat: MORPH_BLACKHAT: 6
*/
imshow( window_name, dst );
官方原文链接
void extract_line_Demo(Mat& image) {
int height = image.rows;
int width = image.cols;
Mat gray_img, binary_img;
Mat horiz_img, vert_img;
imshow("image", image);
cvtColor(image, gray_img, COLOR_BGR2GRAY);//原图转灰度图
bitwise_not(gray_img, gray_img);//图像非操作,~1=0,~0=1(将二进制图片的效果反转既黑色变白色,白色变黑色)
GaussianBlur(gray_img, gray_img, Size(3, 3), 10);//高斯模糊
adaptiveThreshold(gray_img, binary_img, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 15, -2);//自适应阈值操作,凸显目标的轮廓
int horiz_size = (int)(width / 15); // horiz_size值越大,检测出长线条,筛选掉段线条
int vert_size = (int)(height / 15); // 同上
Mat horiz = getStructuringElement(MORPH_RECT, Size(horiz_size, 1), Point(-1, -1));//设置水平线内核
erode(binary_img, horiz_img, horiz);
dilate(horiz_img, horiz_img, horiz);
imshow("horiz_img", horiz_img);
Mat vert = getStructuringElement(MORPH_RECT, Size(1, vert_size), Point(-1, -1));
morphologyEx(binary_img, vert_img, MORPH_OPEN, vert, Point(-1, -1)); //开操作=腐蚀+膨胀
imshow("vert_img", vert_img);
Mat net_img,mask_img;
bitwise_or(horiz_img, vert_img, mask_img);
imshow("mask_img", mask_img); //图像或操作,1|1=1,1|0=0,0|1=0,0|0=0
}