OpenCV使用分水岭算法实现图像分割

一、概述

  案例:使用分水岭算法实现图像的分割实现

  API:介绍参考上一遍

  实现步骤:

    1.输入图像

    2.灰度化

    3.二值化

    4.执行距离变换

    5.归一化

    6.二值化

    7.生成marker:通过findContours+drawContours来创建一个marker

    8.将7生成的marker放入分水岭函数:watershed

    9.给marker着色

    10.输出着色后的图像

  ps:此算法关键点在于生成marker。生成marker之后其实已经完成了算法,后面的着色只是为了让输出更加好看。

 

 

二、代码样例

 Mat src = imread(filePath);//输入原图
    if(src.empty()){
        //
        qDebug()<<"图像为空";
        return;
    }
    //图像灰度化
    Mat gray;
    cvtColor(src,gray,COLOR_BGR2GRAY);
    //图像二值化
    Mat binary;
    threshold(gray,binary,0,255,THRESH_BINARY|cv::THRESH_OTSU);
    imshow("binary",binary);
    qDebug()<<"binary....";
    //执行距离变换
    Mat dist;
    distanceTransform(binary,dist,DistanceTypes::DIST_L2,3,CV_32F);
    qDebug()<<"distanceTransform....";
    normalize(dist,dist,0.0,1.0,NORM_MINMAX);//归一化0~1之间
    qDebug()<<"normalize....";
    //重新二值化预值
    threshold(dist,dist,0.1,1.0,THRESH_BINARY);
    qDebug()<<"threshold....";
    normalize(dist,dist,0,255,NORM_MINMAX);
    qDebug()<<"normalize....";
    dist.convertTo(dist,CV_8UC1);//
    qDebug()<<"convertTo....";

    //开始生成marker并绘制出来
    vector<vector<Point>> contours;
    vector<Vec4i> heri;
    findContours(dist,contours,RETR_CCOMP,CHAIN_APPROX_SIMPLE);
    qDebug()<<"findContours....";

    Mat marker = Mat::zeros(dist.size(),CV_32S);
    for(size_t i = 0;i<contours.size();i++){
        drawContours(marker,contours,i,Scalar(i+1),-1, 8, heri, INT_MAX);
    }
    qDebug()<<"drawContours...."<<contours.size();
    circle(marker, Point(5, 5), 3, Scalar(255), -1);
    watershed(src,marker);
    qDebug()<<"watershed....";
//    marker.convertTo(marker,CV_8UC1);//ps:此处需要注意(到这里实际上已经完成了算法)。一旦不转换就不能用imshow,一旦转换了后面的marker着色就会出现异常
//    imshow("marker",marker);
    qDebug()<<"imshow(marker,marker);....";
    //生成颜色数组
    vector<Vec3b> colors;
    for (size_t i = 0; i < contours.size(); i++) {
        int r = theRNG().uniform(0, 255);
        int g = theRNG().uniform(0, 255);
        int b = theRNG().uniform(0, 255);
        colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
    }

    //给marker着色
    Mat finalResult = Mat::zeros(dist.size(),CV_8UC3);//三通道彩色图像
    int index = 0;
    for(int row = 0;row<marker.rows;row++){
        for(int col = 0;col<marker.cols;col++){
            index = marker.at<int>(row,col);
            if(index>0&&index<=contours.size()){
                finalResult.at<Vec3b>(row,col)  = colors[index-1];
            }else{
                finalResult.at<Vec3b>(row,col) = Vec3b(255,255,255);
            }
        }
    }
    imshow("finalResult",finalResult);

 

三、图片演示

案例1:分割蚕茧

 

案例二:分割任意图像

 

 

posted on 2022-04-12 21:51  飘杨......  阅读(59)  评论(0编辑  收藏  举报