opencv 图像分割,分水岭算法,漂移均值滤波

本章内容

* 基于分水岭的图像分割算法
     *1.均值漂移滤波,
     * 2.二值化
     * 3.距离变换
     * 4.查找轮廓,获取标记
     * 5.分水岭
     * 6.标记颜色

opencv 图像分割,分水岭算法,漂移均值滤波

opencv 图像分割,分水岭算法,漂移均值滤波

输出结果:

opencv 图像分割,分水岭算法,漂移均值滤波

源码:

#include<opencv2/opencv.hpp>
#include<iostream>


int main(int argc, char** argv) {
    /* 本章内容
     * 基于分水岭的图像分割算法
     *1.均值漂移滤波,
     * 2.二值化
     * 3.距离变换
     * 4.查找轮廓,获取标记
     * 5.分水岭
     * 6.标记颜色
    */
    cv::String fileName = "/home/wang/dev/Image/coins_001.jpg";
    cv::Mat src = cv::imread(fileName);
    if(src.data == NULL ){
        std::cout << "文件读入失败" << std::endl;
        return -1;
    }
    cv::imshow("src", src);
    // 1.均值漂移滤波,
    cv::Mat shifted;
    cv::pyrMeanShiftFiltering(src,shifted,21,15);
    cv::imshow("shifted",shifted);
    // 2.二值化
    cv::Mat gray;
    cv::cvtColor(shifted,gray,cv::COLOR_BGR2GRAY);
    cv::Mat binary;
    cv::threshold(gray,binary,0,255,cv::THRESH_BINARY|cv::THRESH_OTSU);
    cv::imshow("binary",binary);
    cv::Mat k = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1));
    cv::morphologyEx(binary,binary,cv::MORPH_OPEN,k,cv::Point(-1,-1),5);
    cv::imshow("binary MORPH_OPEN",binary);

    //3.距离变换
    cv::Mat dist;
    cv::distanceTransform(binary,dist,cv::DistanceTypes::DIST_L2,3);
    cv::normalize(dist,dist,1,0,cv::NORM_MINMAX);
    cv::imshow("dist", dist);
    cv::threshold(dist,dist,0.2,1,cv::THRESH_BINARY); //
    cv::imshow("dist bynary", dist);

    // 4.查找轮廓,获取标记
    std::vector<std::vector<cv::Point>> contours;
    cv::Mat distU8;
    dist.convertTo(distU8,CV_8U);
    cv::findContours(distU8,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE,cv::Point(0,0));
    cv::Mat marker = cv::Mat::zeros(src.size(),CV_32F);
    for(int i=0; i < contours.size();i++){
        cv::drawContours(marker,contours,i, cv::Scalar(i + 1),-1); // -1表示填充
    }
    cv::imshow("marker",marker);
    // 原图像腐蚀
    cv::morphologyEx(src,src,cv::MORPH_ERODE,k);
    cv::imshow("src1",src);

    // 5.分水岭
    std::cout << "src.type()" << src.type() << std::endl;
    marker.convertTo(marker,CV_32SC1);
    cv::watershed(src,marker);
    cv::Mat makU8;
    marker.convertTo(makU8,CV_8UC1);
    cv::imshow("makU8",makU8*20);

    // 6.标记颜色
    std::vector<cv::Vec3b> colors;
    for(int i=0; i < contours.size(); i++){
            int b = cv::theRNG().uniform(0,255);
            int g = cv::theRNG().uniform(0,255);
            int r = cv::theRNG().uniform(0,255);
            colors.push_back(cv::Vec3b(b,g,r));
    }

    cv::Mat dst = cv::Mat::zeros(marker.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()) {
                    dst.at<cv::Vec3b>(row, col) = colors[index - 1];
                } else {
                    dst.at<cv::Vec3b>(row, col) = cv::Vec3b(0, 0, 0);
                }
            }
        }
     imshow("Final Result", dst);

    cv::waitKey(0);
    return 0;
}