1. 程式人生 > >opencv學習筆記(二十)——形態學濾波

opencv學習筆記(二十)——形態學濾波

開運算

處理過程:先腐蝕後膨脹。
功能:用於消除小物體,在纖細點處分離物體,並且在平滑較大物體的邊界的同時不明顯改變其面積,同時抑制比結構元小的亮細節。
使用例項:

#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()函式得到更詳細的解釋。