相关概念:
腐蚀:删除对象边界某些像素。
结构元素
设有两幅图象B,X。若X是被处理的对象,而B是用来处理X的,则称B为结构元素(structure element),又被形象地称做刷子。结构元素通常都是一些比较小的图象。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
腐蚀过程介绍:
对二值图腐蚀过程:
在图6.10中,左边是被处理的图象X(二值图象,我们针对的是黑点),中间是结构元素B,那个标有origin的点是中心点,即当前处理元素的位置。腐蚀的方法是,拿B的中心点和X上的点一个一个地对比,如果B上的所有点(指的是所有黑点)都在X的范围内(即X图上处理元素所在的位置以及它上,左两个点都是黑色),则该点保留,否则将该点去掉(变为白点);右边是腐蚀后的结果。可以看出,它仍在原来X的范围内,且比X包含的点要少,就像X被腐蚀掉了一层。
对灰度图像的腐蚀:
如下图,左边是要处理图像,中间是结构元素,右边是与对应每个像素的灰度值。
处理过程就是:与上面的B一样,中间是要处理的元素所在的位置,三个1所在的位置对应三个灰度值,然后将中间这个1对应的灰度值改成这三个最小的,如源图像第一个灰度值1,它上左都没有灰度值,所以最小就是它本身,所以输出也是1,再比如处理灰度值为22那个点的时候,上面是7左边是44,所以22应改为7。
腐蚀的作用
1,边缘检测。
2,噪声滤除。
3,形态骨架提取。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
腐蚀例程:
1:从灰度值层面介绍腐蚀
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
int main()
{
//创建源图像
IplImage* src = cvCreateImage(cvSize(11, 10), 8, 1);
//创建图像 用来保存输出后的图像
IplImage* dat = cvCreateImage(cvSize(11,10), 8, 1);
//图像清零
cvSetZero(dat);
cvSetZero(src);
//将源图像赋初值
int x, y;
//(1,6)-->(1,9)
//(2,6)-->(2,9)
//(3,6)-->(3,9)
for (y = 1; y < 4; y++)
{
for (x = 6; x < 10; x++)
{
cvSetReal2D(src, y, x, 255);
}
}
//(4,4)-->(4,7)
//(5,4)-->(4,7)
for (y = 4; y < 6; y++)
{
for (x = 4; x < 8; x++)
{
cvSetReal2D(src, y, x, 255);
}
}
//(6,1)-->(6,7)
for (x = 1; x < 8; x++)
{
cvSetReal2D(src, 6, x, 255);
}
//(7,1)-->(7,4)
//(8,1)-->(8,4)
for (y = 7; y < 9; y++)
{
for (x = 1; x < 5; x++)
{
cvSetReal2D(src, y, x, 255);
}
}
//输出源图像
printf("src is :\n");
for (y = 0; y < src->height; y++)
{
for (x = 0; x < src->width; x++)
{
float value = cvGetReal2D(src, y, x);
printf("%5d", (int)(value));
}
printf("\n");
}
//创建结构元素变量,并且对其取值
IplConvKernel* element = 0;
//结构元素的取值情况
int value[16] = {
0, 0, 0, 0,
0, 0, 1, 0,
0, 1, 1, 0,
0, 0, 0, 0
};
//声明结构元素的列数 行数 锚点坐标
int clos = 4, rows = 4, anchor_x = 2, anchor_y = 2;
element = cvCreateStructuringElementEx(clos, rows, anchor_x, anchor_y, CV_SHAPE_CUSTOM, value);
//使用自定义结构元素 对图像进行腐蚀
cvErode(src, dat, element, 1);
//输出腐蚀后的结果
printf("dat is: \n");
for (y = 0; y < dat->height; y++)
{
for (x = 0; x < dat->width; x++)
{
float value = cvGetReal2D(dat, y, x);
printf("%5d", (int)value);
}
printf("\n");
}
}
效果:
腐蚀前:
腐蚀后:
2,从图像层面介绍腐蚀:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{
Mat srcImage = imread("楪析.jpg");
imshow("【原图】腐蚀操作", srcImage);
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat dstImage;
erode(srcImage, dstImage, element);
imshow("【效果图】腐蚀操作", dstImage);
waitKey(0);
return 0;
}
腐蚀前:
腐蚀后:
图像膨胀
图像的膨胀就是图像腐蚀的相反操作,例如: 对灰度图的处理过程就是:与上面的B一样,中间是要处理的元素所在的位置,三个1所在的位置对应三个灰度值,然后将中间这个1对应的灰度值改成这三个最大的,如第一个灰度值1,它上左都没有灰度值,所以最大就是它本身,所以输出也是1,再比如处理灰度值为22那个点的时候,上面是7左边是44,所以22应改为44。
例程:
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
void main11()
{
/*创建两个单通道图像*/
IplImage *src, *dst;
src = cvCreateImage(cvSize(10, 10), 8, 1);
dst = cvCreateImage(cvGetSize(src), 8, 1);
/*图像的取值*/
unsigned char data[100] = {
1, 2, 5, 1, 78, 68, 7, 3, 5, 6,
5, 66, 7, 6, 3, 44, 22, 44, 0, 2,
9, 77, 3, 5, 6, 2, 4, 57, 9, 4,
54, 27, 59, 23, 58, 13, 36, 31, 38, 57,
35, 26, 24, 24, 31, 54, 22, 48, 48, 49,
27, 14, 26, 33, 68, 87, 57, 61, 19, 72,
46, 58, 46, 64, 54, 43, 97, 92, 20, 53,
84, 35, 35, 75, 12, 57, 37, 57, 4, 48,
57, 14, 67, 97, 56, 33, 37, 46, 58, 59,
36, 57, 89, 65, 47, 75, 11, 27, 41, 54
};
for (int y = 0; y < src->height; y++)
{
unsigned char* imageData = (unsigned char *)(src->imageData + y*src->widthStep);
for (int x = 0; x < src->width; x++)
{
imageData[x] = data[y*src->width + x];
}
}
printf("src is \n");
for (int y = 0; y < src->height; y++)
{
for (int x = 0; x < src->width; x++)
{
float value = cvGetReal2D(src, x, y);
printf("%3d ", (int)(value));
}
printf("\n");
}
/*声明结构元素变量*/
IplConvKernel* element = 0;
int values[16] = {
0,0,0,0,
0,0,1,0,
0,1,1,0,
0,0,0,0
};
/*结构体元素参数*/
int clos = 4, rows = 4, anchor_x = 2, anchor_y = 2;
/*创建结构元素*/
element = cvCreateStructuringElementEx(clos, rows, anchor_x, anchor_y, CV_SHAPE_CUSTOM, values);
/*膨胀后的结果*/
cvDilate(src, dst, element, 1);
printf("dst is \n");
for (int y = 0; y < src->height; y++)
{
for (int x = 0; x < src->width; x++)
{
float value = cvGetReal2D(dst, x, y);
printf("%3d ", (int)(value));
}
printf("\n");
}
/*释放图像内存*/
src = NULL;
dst = NULL;
system("pause");
}
效果如图: