标签:
图像的腐蚀与膨胀
一、原理:
⑴ 图像形态学处理的概念
定义结构元素B为:
1 | 1 |
1 | 0 |
(i-1,j+1) | (i,j+1) |
(i-1,j) | 所求此点(i,j) |
腐蚀处理的结果是使原来的二值图像减小一圈。
二、我再加一个轮廓提取,非常简单的方法:用的是9X9的模板;
(i-1,j+1) | (i,j+1) | (i+1,j+1) |
(i-1,j) | 所求此点(i,j) | (i+1,j) |
(i-1,j-1) | (i,j-1) | (i+1,j_1) |
#include<opencv2/opencv.hpp> #include<iostream> using namespace cv; using namespace std; Mat srcImage, grayImage, binarygray, erosion, dilation, outline; static void g_erosion(int, void*); static void g_dilation(int, void*); static void g_outline(int, void*); static void ShowHelpText(); int main() { system("color 3f"); ShowHelpText(); srcImage = imread("D://vvoo//cell.jpg"); cvtColor(srcImage, grayImage, CV_RGB2GRAY); int threshold; cout << "input threshold: " << endl; cin >> threshold; //二值化 binarygray = Mat::zeros(grayImage.rows, grayImage.cols, grayImage.type()); { for (int i = 0; i <grayImage.rows; i++) { for (int j = 0; j < grayImage.cols; j++) { if (grayImage.data[i*grayImage.step + j] > threshold) { binarygray.data[i*binarygray.step + j] = 255; } else { binarygray.data[i*binarygray.step + j] = 0; } } } } //腐蚀 g_erosion(0, 0); //膨胀 g_dilation(0, 0); //轮廓提取 g_outline(0, 0); imshow("原图", srcImage); imshow("binarygray", binarygray); waitKey(0); return 0; } static void g_erosion(int, void*) { erosion = Mat::zeros(binarygray.rows, binarygray.cols, binarygray.type()); { for (int i = 1; i < binarygray.rows; i++) { for (int j = 1; j < binarygray.cols; j++) { if (binarygray.data[(i - 1)*binarygray.step + j] + binarygray.data[(i - 1)*binarygray.step + j + 1] + binarygray.data[i*binarygray.step + j + 1] == 0) { erosion.data[i*erosion.step + j] = 0; } else { erosion.data[i*erosion.step + j] = 255; } } } } imshow("erosion_1", erosion); } static void g_dilation(int, void*) { dilation = Mat::zeros(binarygray.rows, binarygray.cols, binarygray.type()); for (int i = 1; i < binarygray.rows; i++) { for (int j = 1; j < binarygray.cols; j++) { if (binarygray.data[(i - 1)*binarygray.step + j] == 0 || binarygray.data[(i - 1)*binarygray.step + j - 1] == 0 || binarygray.data[i*binarygray.step + j + 1] == 0) { dilation.data[i*dilation.step + j] = 0; } else { dilation.data[i*dilation.step + j] = 255; } } } imshow("dilation_1", dilation); } static void g_outline(int, void*) { outline = Mat::zeros(binarygray.rows, binarygray.cols, binarygray.type()); for (int i = 1; i < binarygray.rows; i++) { for (int j = 1; j < binarygray.cols; j++) { if (binarygray.data[i*binarygray.step + j + 1] + binarygray.data[(i - 1)*binarygray.step + j] + binarygray.data[i*binarygray.step + j - 1] + binarygray.data[(i - 1)*binarygray.step + j - 1] + binarygray.data[(i + 1)*binarygray.step + j - 1] + binarygray.data[(i + 1)*binarygray.step + j] + binarygray.data[(i - 1)*binarygray.step + j + 1] + binarygray.data[(i + 1)*binarygray.step + j + 1] == 2040) { outline.data[i*erosion.step + j] = 255; } if (binarygray.data[i*binarygray.step + j + 1] + binarygray.data[(i - 1)*binarygray.step + j] + binarygray.data[i*binarygray.step + j - 1] + binarygray.data[(i - 1)*binarygray.step + j - 1] + binarygray.data[(i + 1)*binarygray.step + j - 1] + binarygray.data[(i + 1)*binarygray.step + j] + binarygray.data[(i - 1)*binarygray.step + j + 1] + binarygray.data[(i + 1)*binarygray.step + j + 1] == 0) { outline.data[i*erosion.step + j] = 255; } } } imshow("outline", outline); } static void ShowHelpText() { cout << "\n\n本程序涉及到:"<<"腐蚀(erosion)、膨胀(dilation)、轮廓提取(outline)。\n\n" << endl; }四、运行结果
五、调用Opencv的erode()函数和dilate()函数实现腐蚀和膨胀功能
1)erode函数,使用像素邻域内的局部极小运算符来腐蚀一张图片,从src输入,由dst输出。支持就地(in-place)操作。
看一下函数原型:
void erode( InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() );
同样的,使用erode函数,一般我们只需要填前面的三个参数,后面的四个参数都有默认值。而且往往结合getStructuringElement一起使用。
2)dilate函数原型
函数原型:
C++: void dilate( InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() );
参数详解:
我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵。其中,getStructuringElement函数的第一个参数表示内核的形状,我们可以选择如下三种形状之一:
矩形: MORPH_RECT
而getStructuringElement函数的第二和第三个参数分别是内核的尺寸以及锚点的位置。
3)代码实现
#include<opencv2/opencv.hpp> #include<iostream> using namespace cv; using namespace std; #define WINDOWN_NAME_1 "原图" #define WINDOWN_NAME_2 "腐蚀图" #define WINDOWN_NAME_3 "膨胀图" int main() { Mat srcImage = imread("D://vvoo//cell.jpg"); //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); Mat out_erosion, out_dilate; //进行膨胀操作 erode(srcImage, out_erosion, element); dilate(srcImage, out_dilate, element); imshow(WINDOWN_NAME_1, srcImage); imshow(WINDOWN_NAME_2, out_erosion); imshow(WINDOWN_NAME_3, out_dilate); waitKey(0); return 0; }
4)运行结果
和自己写的比较下比较一下,差别比较大,主要是因为结构元素大小的关系,我的是2*2,Opencv是15*15的。
我也是初学者,欢迎纠正!
六、参考资料
1.system("color 3f");//输出窗口和字体颜色可变化,3代表窗口颜色(绿色),f代表窗口里字体颜色(白色)
全部颜色为:
标签:
原文地址:http://blog.csdn.net/qq_29540745/article/details/51931770