OpenCV實現膨脹與腐蝕
形態學(morphlogy)就是基於形狀的一系列圖像處理操作,而膨脹與腐蝕是兩種最基礎的形態學操作。開運算、閉運算、形態學梯度、頂帽、黑帽都是基於膨脹與腐蝕來實現的。
膨脹與腐蝕主要可以用來
1.消除噪音
2.分割出獨立的圖像元素,在圖像中連接相鄰的元素
3.找出圖像中的明顯極大值區域或者極小值區域
4.找出圖像的梯度
原理說明:二者均對於高亮地區而言(以二值圖像爲例)
膨脹(dilate):求局部最大值
核與圖像卷積,即計算核覆蓋的區域的像素的最大值,並把這個最大值賦給參考點的指定像素。
原理圖:
數學公式:
函數調用:
void cv::dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor, int iterations,
int borderType, const Scalar& borderValue )
{
morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue );
}
腐蝕(erode):求局部最小值
核與圖像卷積,即計算核覆蓋的區域的像素的最小值,並把這個最小值賦給參考點的指定像素。
原理圖:
數學公式:
函數調用:
void cv::erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor, int iterations,
int borderType, const Scalar& borderValue )
{
morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue );
}
函數調用:在這裏,只實現膨脹,腐蝕原理類似。
代碼:
void method_one(InputArray src, OutputArray dst, int d)
{
int radius = d / 2;
d = radius * 2 + 1;
int row = src.rows();
int col = src.cols();
dst.create(row, col, src.type());
src.copyTo(dst);//拷貝
Mat _src = src.getMat();
Mat _dst = dst.getMat();
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < col;++j)
{
if (_src.data[i*col+ j] == 255)//如果當前的像素是255,那麼在r*r的範圍內都應輸出255
{//要考慮邊界的情況
int position_start_x = 0 > j - radius ? 0 : j - radius;
int position_start_y = 0 > i - radius ? 0 : i - radius;
int position_end_x = col-1 < j + radius ? col - 1: j + radius;
int position_end_y = row-1 < i + radius ? row - 1: i + radius;
for (int m = position_start_y; m <= position_end_y; ++m)
{
for (int n = position_start_x; n <= position_end_x; ++n)
{
_dst.data[m*col + n] = 255;
}
}
}
}
}
}
int main()
{
Mat srcimage = imread("C:\\Users\\l\\Desktop\\2.jpg");
Mat gray;
gray.create(srcimage.rows, srcimage.cols, CV_8UC1);
cvtColor(srcimage,gray,CV_BGR2GRAY);
Mat binary;
binary.create(srcimage.rows, srcimage.cols, CV_8UC1);
for (int i = 0; i < gray.cols*gray.rows*gray.channels();i++)
{
if (gray.data[i] < 128)
binary.data[i] = 0;
else
binary.data[i] = 255;
}
imshow("原始圖", binary);
Mat dilateimage(binary.cols,binary.rows,CV_8UC1);//存儲膨脹後的圖像
Mat element;
element = getStructuringElement(MORPH_RECT, Size(3, 3));
double time = static_cast<double>(getTickCount());
dilate(binary,dilateimage,element,cv::Point(-1,-1),1);
time = ((double)getTickCount() - time) / getTickFrequency();
cout << "Opencv自帶函數所用時間" << time <<"秒"<< endl;
imshow("結果圖", dilateimage);
Mat result1;
double time1 = static_cast<double>(getTickCount());
method_one(binary, result1, 3);
time = ((double)getTickCount() - time) / getTickFrequency();
cout << "方法一所用時間" << time << "秒" << endl;
imshow("方法一的結果圖", result1);
waitKey(0);
return 0;
}
結果圖:
其他形態學濾波的應用:
開運算(Opening Operation):先腐蝕後膨脹
dst = open(src,element)=dilate(erode(src,element));
閉運算(Closing Operation):先膨脹後腐蝕
dst = close(src,element) = erode(dilate(src,element));
形態學梯度(Morphological Grodient):膨脹圖與腐蝕圖只差
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;
參考鏈接:
http://www.cnblogs.com/hrlnw/p/5044402.html
http://www.cnblogs.com/slysky/archive/2011/10/16/2214015.html