opencv學習筆記(二十)——形態學濾波
阿新 • • 發佈:2019-01-11
開運算
處理過程:先腐蝕後膨脹。
功能:用於消除小物體,在纖細點處分離物體,並且在平滑較大物體的邊界的同時不明顯改變其面積,同時抑制比結構元小的亮細節。
使用例項:
#include<opencv2/opencv.hpp>
void main()
{
cv::Mat image = cv::imread("腐蝕膨脹練習1.jpg");
cv::namedWindow("SourceImage");
cv::namedWindow("OutputImage");
cv::imshow("SourceImage", image);
//開運算(MORPH_OPEN)
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
cv::morphologyEx(image, image, cv::MORPH_CLOSE, element);
cv::imshow("OutputImage", image);
cv::waitKey(0);
}
效果圖如下:
閉運算
處理過程:先膨脹後腐蝕
功能:用來填充物體內細小空洞、連線鄰近物體、平滑其邊界的同時並不明顯改變其面積,同時抑制比結構元小的暗細節。
使用例項:
#include <opencv2/opencv.hpp>
void main()
{
cv::Mat image = cv::imread("result.BMP");
cv::namedWindow("SourceImage");
cv::namedWindow("OutputImage");
cv::imshow("SourceImage", image);
//閉運算(MORPH_CLOSE)
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
cv::morphologyEx (image, image, cv::MORPH_CLOSE, element);
cv::imshow("OutputImage", image);
cv::waitKey(0);
}
效果:
形態學梯度
處理過程:膨脹圖和腐蝕圖相減
功能:對二值化影象進行這一操作可以將邊緣突出來,可以使用形態學梯度來保留物體的邊緣輪廓
使用例項:
#include<opencv2/opencv.hpp>
void main()
{
cv::Mat image = cv::imread("result.BMP");
cv::namedWindow("SourceImage");
cv::namedWindow("OutputImage");
cv::imshow("SourceImage", image);
//形態學梯度(MORPH_GRADIENT)
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2, 2));
cv::morphologyEx(image, image, cv::MORPH_GRADIENT, element);
cv::imshow("OutputImage", image);
cv::waitKey(0);
}
效果:
頂帽變換和低帽變換
頂帽(白頂帽變換):
處理過程:原影象減去開運算的過程。
功能:頂帽變換用於校正不均勻關照的影響(補充:均勻光照在從背景中提取目標的處理中扮演核心的角色)。
使用例項:
#include<opencv2/opencv.hpp>
void main()
{
cv::Mat image = cv::imread("Fig0926(a)(rice).tif");
cv::namedWindow("SourceImage");
cv::namedWindow("OutputImage");
cv::imshow("SourceImage", image);
//形態學梯度(MORPH_GRADIENT)
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15));
cv::morphologyEx(image, image, cv::MORPH_TOPHAT, element);
cv::imshow("OutputImage", image);
cv::waitKey(0);
}
效果展示:
低帽(黑底帽變換):
處理過程:閉運算減去原影象的過程。
功能:突出比原圖輪廓周圍更暗的區域。
使用例項:
#include<opencv2/opencv.hpp>
void main()
{
cv::Mat image = cv::imread("Fig0926(a)(rice).tif");
cv::namedWindow("SourceImage");
cv::namedWindow("OutputImage");
cv::imshow("SourceImage", image);
//形態學梯度(MORPH_GRADIENT)
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(10, 10));
cv::morphologyEx(image, image, cv::MORPH_BLACKHAT, element);
cv::imshow("OutputImage", image);
cv::waitKey(0);
}
效果圖:
核心函式morphologyEx()介紹:
原始碼解析:
檢視一下morphologyEx原始碼:
void cv::gpu::morphologyEx(const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, GpuMat& buf1, GpuMat& buf2, Point anchor, int iterations, Stream& stream)
{
switch( op )
{
case MORPH_ERODE: erode(src, dst, kernel, buf1, anchor, iterations, stream); break;
case MORPH_DILATE: dilate(src, dst, kernel, buf1, anchor, iterations, stream); break;
case MORPH_OPEN:
erode(src, buf2, kernel, buf1, anchor, iterations, stream);
dilate(buf2, dst, kernel, buf1, anchor, iterations, stream);
break;
case CV_MOP_CLOSE:
dilate(src, buf2, kernel, buf1, anchor, iterations, stream);
erode(buf2, dst, kernel, buf1, anchor, iterations, stream);
break;
case CV_MOP_GRADIENT:
erode(src, buf2, kernel, buf1, anchor, iterations, stream);
dilate(src, dst, kernel, buf1, anchor, iterations, stream);
subtract(dst, buf2, dst, GpuMat(), -1, stream);
break;
case CV_MOP_TOPHAT:
erode(src, dst, kernel, buf1, anchor, iterations, stream);
dilate(dst, buf2, kernel, buf1, anchor, iterations, stream);
subtract(src, buf2, dst, GpuMat(), -1, stream);
break;
case CV_MOP_BLACKHAT:
dilate(src, dst, kernel, buf1, anchor, iterations, stream);
erode(dst, buf2, kernel, buf1, anchor, iterations, stream);
subtract(buf2, src, dst, GpuMat(), -1, stream);
break;
default:
CV_Error(CV_StsBadArg, "unknown morphological operation");
}
}
可以發現,這個函式使用了一個大的switch實現了多種形態學濾波的呼叫。
函式API介紹:
C++: void morphologyEx(
InputArray src,
OutputArray dst,
int op,
InputArraykernel,
Pointanchor=Point(-1,-1),
intiterations=1,
intborderType=BORDER_CONSTANT,
constScalar& borderValue=morphologyDefaultBorderValue() );
- 第一個引數,InputArray型別的src,輸入影象,即源影象,填Mat類的物件即可。影象位深應該為以下五種之一:CV_8U,
CV_16U,CV_16S, CV_32F 或CV_64F。 - 第二個引數,OutputArray型別的dst,即目標影象,函式的輸出引數,需要和源圖片有一樣的尺寸和型別。
- 第三個引數,int型別的op,表示形態學運算的型別,可以是如下之一的識別符號:
MORPH_OPEN – 開運算(Opening operation)
MORPH_CLOSE – 閉運算(Closing operation)
MORPH_GRADIENT -形態學梯度(Morphological gradient)
MORPH_TOPHAT - “頂帽”(“Top hat”)
MORPH_BLACKHAT - “黑帽”(“Black hat“)
另有CV版本的識別符號也可選擇,如CV_MOP_CLOSE,CV_MOP_GRADIENT,CV_MOP_TOPHAT,CV_MOP_BLACKHAT,這應該是OpenCV1.0系列版本遺留下來的識別符號,和上面的“MORPH_OPEN”一樣的效果。
- 第四個引數,InputArray型別的kernel,形態學運算的核心。若為NULL時,表示的是使用參考點位於中心3x3的核。我們一般使用函式getStructuringElement配合這個引數的使用。getStructuringElement函式會返回指定形狀和尺寸的結構元素(核心矩陣)。
- 第五個引數,Point型別的anchor,錨的位置,其有預設值(-1,-1),表示錨位於中心。
- 第六個引數,int型別的iterations,迭代使用函式的次數,預設值為1。
- 第七個引數,int型別的borderType,用於推斷影象外部畫素的某種邊界模式。注意它有預設值BORDER_ CONSTANT。
- 第八個引數,const
Scalar&型別的borderValue,當邊界為常數時的邊界值,有預設值morphologyDefaultBorderValue(),一般我們不用去管他。需要用到它時,可以看官方文件中的createMorphologyFilter()函式得到更詳細的解釋。