OpenCV——分水嶺算法


分水嶺算法,是一種基於拓撲理論的數學形態學的分割方法,其基本思想是把圖像看作是測地學上的拓撲地貌,圖像中每一點像素的灰度值表示該點的海拔高度,每一個局部極小值及其影響區域稱為集水盆,而集水盆的邊界則形成分水嶺。

一般的分水嶺算法會對微弱邊緣,圖像中的噪聲,物體表面細微的灰度變化造成過度的分割。

以下為分水嶺算法的示例程序。

watershedSegmenter.h

#if !defined WATERSHS
#define WATERSHS

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

class WatershedSegmenter {

  private:
      Mat markers;

  public:
       //設置標記圖
      void setMarkers(const Mat& markerImage) {

        //watershed()的輸入參數必須為一個32位有符號的標記,所以要先進行轉換 
        markerImage.convertTo(markers,CV_32S);
      }
      //執行watershed()
      Mat process(const Mat &image) {

        // Apply watershed
        watershed(image,markers);

        return markers;
      }

      // 以圖像形式返回結果
      Mat getSegmentation() {

        Mat tmp;
    // 從32S到8U(0-255)會進行飽和運算,所以像素高於255的一律復制為255
        markers.convertTo(tmp,CV_8U);

        return tmp;
      }

      // 以圖像形式返回分水嶺
     Mat getWatersheds() {

       Mat tmp;
        //在設置標記圖像,即執行setMarkers()后,邊緣的像素會被賦值為-1,其他的用正整數表示
        //下面的這個轉換可以讓邊緣像素變為-1*255+255=0,即黑色,其余的溢出,賦值為255,即白色。
        markers.convertTo(tmp,CV_8U,255,255);
        return tmp;
      }
};


#endif

main.cpp

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include "watershedSegmenter.h"

using namespace std;
using namespace cv;
int main()
{
    //設置視頻讀入,括號里面的數字是攝像頭的選擇,一般自帶的是0
    VideoCapture capture(0);

    if (!capture.isOpened())
    {
        cout << "can not open the video" << endl;
        return -1;
    }

    Mat frame;
    Mat binImage;

    bool stop = false;
    while (!stop)
    {
        //讀入視頻幀,轉換顏色空間,並分割通道
        capture >> frame;
        cvtColor(frame, binImage, CV_BGR2GRAY);

        threshold(binImage, binImage, 120, 255, THRESH_BINARY);


        //膨脹圖像
        dilate(binImage, binImage, Mat());

        /*分水嶺算法*/
        //*************************************************************
        Mat fg;
        //腐蝕圖像6次
        erode(binImage, fg, Mat(), Point(-1, -1), 6);
        // Identify image pixels without objects
        Mat bg;

        //膨脹圖像6次
        dilate(binImage, bg, Mat(), Point(-1, -1), 6);

        imshow("bg", bg);
        //進行固定閾值操作 
        threshold(bg, bg, 1, 128, THRESH_BINARY_INV);


        // Show markers image
        Mat markers(binImage.size(), CV_8U, Scalar(0));
        markers = fg + bg;
        imshow("markers image", markers);
        WatershedSegmenter segmenter;
        segmenter.setMarkers(markers);
        segmenter.process(frame);

        imshow("segmentation", segmenter.getSegmentation());
        imshow("Watersheds", segmenter.getWatersheds());
    }
    waitKey(0);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM