预备知识(卷积)
卷积就是循环对图像跟一个核逐个元素相乘再求和得到另外一副图像的操作,比如结果图中第一个元素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)相邻的元素。 寻找图像中的明显的极大值区域或极小值区域。
膨胀 dilate ()
此操作将图像 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 );
腐蚀 erode ()
它提取的是内核覆盖下的相素最小值。 进行腐蚀操作时,将内核 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 );
开运算 (Opening)
开运算是通过先对图像腐蚀再膨胀实现的。 dst = open( src, element) = dilate( erode( src, element ) ) 能够排除小团块物体(假设物体较背景明亮) 请看下面,左图是原图像,右图是采用开运算转换之后的结果图。 观察发现字母拐弯处的白色空间消失。
闭运算(Closing)
闭运算是通过先对图像膨胀再腐蚀实现的。 dst = close( src, element ) = erode( dilate( src, element ) ) 能够排除小型黑洞(黑色区域)。
形态梯度(Morphological Gradient)
膨胀图与腐蚀图之差 dst = morph_{grad}( src, element ) = dilate( src, element ) - erode( src, element ) 能够保留物体的边缘轮廓,如下所示:
顶帽(Top Hat)
原图像与开运算结果图之差 dst = tophat( src, element ) = src - open( src, element )
黑帽(Black Hat)
闭运算结果图与原图像之差 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
}
|