1. 程式人生 > >opencv分水嶺演算法分割硬幣

opencv分水嶺演算法分割硬幣

網上有Python寫的,但是沒有C++寫的,所以自己搞了個,東拼西湊的結果,畢竟我也不是大神,湊活著看吧。傾情奉獻,歡迎指教

#include <opencv2/opencv.hpp>
#include <stack>
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <stdio.h>
using namespace std;
using namespace cv;




void icvprCcaBySeedFill(const cv::Mat& _binImg, cv::Mat& _lableImg)     //連通域標記,分水嶺演算法會用到,網上找的程式
{
    // connected component analysis (4-component)
    // use seed filling algorithm
    // 1. begin with a foreground pixel and push its foreground neighbors into a stack;
    // 2. pop the top pixel on the stack and label it with the same label until the stack is empty
    //
    // foreground pixel: _binImg(x,y) = 1
    // background pixel: _binImg(x,y) = 0




    if (_binImg.empty() ||
        _binImg.type() != CV_8UC1)
    {
        return ;
    }


    _lableImg.release() ;
    _binImg.convertTo(_lableImg, CV_32SC1) ;


    int label = 1 ;  // start by 2


    int rows = _binImg.rows - 1 ;
    int cols = _binImg.cols - 1 ;
    for (int i = 1; i < rows-1; i++)
    {
        int* data= _lableImg.ptr<int>(i) ;
        for (int j = 1; j < cols-1; j++)
        {
            if (data[j] == 1)
            {
                std::stack<std::pair<int,int> > neighborPixels ;
                neighborPixels.push(std::pair<int,int>(i,j)) ;     // pixel position: <i,j>
                ++label ;  // begin with a new label
                while (!neighborPixels.empty())
                {
                    // get the top pixel on the stack and label it with the same label
                    std::pair<int,int> curPixel = neighborPixels.top() ;
                    int curX = curPixel.first ;
                    int curY = curPixel.second ;
                    _lableImg.at<int>(curX, curY) = label ;


                    // pop the top pixel
                    neighborPixels.pop() ;




                    if (curY != 1 && _lableImg.at<int>(curX, curY-1) == 1) //左值
                    neighborPixels.push(std::pair<int,int>(curX, curY-1)) ;
                    if ( curY != rows && _lableImg.at<int>(curX, curY+1) == 1)// 右值
                    neighborPixels.push(std::pair<int,int>(curX, curY+1)) ;
                    if (curX != 0 && _lableImg.at<int>(curX-1, curY) == 1)// 上值
                    neighborPixels.push(std::pair<int,int>(curX-1, curY)) ;
                    if (curX != cols && _lableImg.at<int>(curX+1, curY) == 1)//下值
                    neighborPixels.push(std::pair<int,int>(curX+1, curY)) ;


                }
            }
        }
    }
}


int main(int argc,char *argv[])
{
     Mat image=imread("......圖片的地址.........",1);
   Mat imageGray;
    cvtColor(image,imageGray,CV_BGR2GRAY);
      GaussianBlur(imageGray,imageGray,Size(5,5),2); //濾波
    
threshold(imageGray,imageGray,200,255,CV_THRESH_OTSU|CV_THRESH_BINARY_INV);
 imshow("binary",imageGray);
    Mat imageThin(imageGray.size(),CV_32FC1); //定義儲存距離變換結果的Mat矩陣


 distanceTransform(imageGray,imageThin,CV_DIST_L2,3);  //距離變換
    Mat distShow;
    imageThin.convertTo(distShow,CV_8UC1);


    normalize(distShow,distShow,0,255,CV_MINMAX); //為了顯示清晰,做了0~255歸一化
   
    imshow("Source Image",image);
    imshow("Thin Image",distShow);
    Mat fg,bg,mark0;
    Mat element = getStructuringElement(MORPH_RECT, Size(25, 25));
       erode(distShow,fg, element);
       threshold(fg,fg,200,255,CV_THRESH_OTSU|CV_THRESH_BINARY);
        imshow("front Image",fg);
     

Mat element2 = getStructuringElement(MORPH_RECT, Size(5, 5));
dilate(distShow,bg,element2);
  threshold(bg,bg,20,125,CV_THRESH_BINARY_INV);
imshow("bg",bg);
mark0=bg+fg;
imshow("mark0",mark0);

cv::Mat labelImg ;
cv::threshold(mark0, mark0, 130, 1, CV_THRESH_BINARY) ;
  icvprCcaBySeedFill(mark0, labelImg) ;


   // show result
   cv::Mat grayImg ;
   labelImg *= 10 ;
   labelImg.convertTo(grayImg, CV_8UC1) ;
  grayImg=grayImg+bg;
   cv::imshow("marker", grayImg) ;


cvtColor(imageGray,imageGray,CV_GRAY2BGR);
Mat marker;
 grayImg.convertTo(marker,CV_32SC1);
 watershed(imageGray,marker);
Mat afterWatershed;
convertScaleAbs(marker,afterWatershed);
imshow("After Watershed",afterWatershed);

   waitKey();
    return 0;
}