opencv學習筆記(十)-影象腐蝕與腐蝕
相關概念:
腐蝕:刪除物件邊界某些畫素。
結構元素
設有兩幅圖象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");
}
效果如圖: