opencv分水岭算法分割硬币

来源:互联网 发布:韩顺平php视频下载 编辑:程序博客网 时间:2024/05/30 20:09

网上有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;
}

原创粉丝点击