zoukankan      html  css  js  c++  java
  • opencv::分水岭图像分割

    分水岭分割方法原理 (3种)
        - 基于浸泡理论的分水岭分割方法 (距离)
        - 基于连通图的方法 
        - 基于距离变换的方法
    
    
    图像形态学操作:
        - 腐蚀与膨胀 
        - 开闭操作 
        
        
    分水岭算法运用
        - 分割粘连对象,实现形态学操作与对象计数 
        - 图像分割

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main(int argc, char** argv) {
        Mat src = imread("D:/images/coins_001.jpg");
        if (src.empty()) {
            printf("could not load image...
    ");
            return -1;
        }
        namedWindow("input image", CV_WINDOW_AUTOSIZE);
        imshow("input image", src);
    
        Mat gray, binary, shifted;
        pyrMeanShiftFiltering(src, shifted, 21, 51);
        //imshow("shifted", shifted);
    
        //灰度
        cvtColor(shifted, gray, COLOR_BGR2GRAY);
        threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
        //imshow("binary", binary);
    
        // 距离变换
        Mat dist;
        distanceTransform(binary, dist, DistanceTypes::DIST_L2, 3, CV_32F);
        normalize(dist, dist, 0, 1, NORM_MINMAX);
        //imshow("distance result", dist);
    
        // 二值化
        threshold(dist, dist, 0.4, 1, THRESH_BINARY);
        //imshow("distance binary", dist);
    
        // markers
        Mat dist_m;
        dist.convertTo(dist_m, CV_8U);
        vector<vector<Point>> contours;
        findContours(dist_m, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
    
        // create markers
        Mat markers = Mat::zeros(src.size(), CV_32SC1);
        for (size_t t = 0; t < contours.size(); t++) {
            drawContours(markers, contours, static_cast<int>(t), Scalar::all(static_cast<int>(t) + 1), -1);
        }
        circle(markers, Point(5, 5), 3, Scalar(255), -1);
        //imshow("markers", markers*10000);
    
        // 形态学操作 - 彩色图像,目的是去掉干扰,让结果更好
        Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
        morphologyEx(src, src, MORPH_ERODE, k);
    
        // 完成分水岭变换
        watershed(src, markers);
        Mat mark = Mat::zeros(markers.size(), CV_8UC1);
        markers.convertTo(mark, CV_8UC1);
        bitwise_not(mark, mark, Mat());
        //imshow("watershed result", mark);
    
        // generate random color
        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));
        }
    
        // 颜色填充与最终显示
        Mat dst = Mat::zeros(markers.size(), CV_8UC3);
        int index = 0;
        for (int row = 0; row < markers.rows; row++) {
            for (int col = 0; col < markers.cols; col++) {
                index = markers.at<int>(row, col);
                if (index > 0 && index <= contours.size()) {
                    dst.at<Vec3b>(row, col) = colors[index - 1];
                }
                else {
                    dst.at<Vec3b>(row, col) = Vec3b(0, 0, 0);
                }
            }
        }
    
        imshow("Final Result", dst);
        printf("number of objects : %d
    ", contours.size());
    
        waitKey(0);
        return 0;
    }

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    Mat watershedCluster(Mat &image, int &numSegments);
    void createDisplaySegments(Mat &segments, int numSegments, Mat &image);
    int main(int argc, char** argv) {
        Mat src = imread("D:/images/cvtest.png");
        if (src.empty()) {
            printf("could not load image...
    ");
            return -1;
        }
        namedWindow("input image", CV_WINDOW_AUTOSIZE);
        imshow("input image", src);
    
        int numSegments;
        Mat markers = watershedCluster(src, numSegments);
        createDisplaySegments(markers, numSegments, src);
        waitKey(0);
        return 0;
    }
    
    Mat watershedCluster(Mat &image, int &numComp) {
        // 二值化
        Mat gray, binary;
        cvtColor(image, gray, COLOR_BGR2GRAY);
        //阈值
        threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
        // 形态学与距离变换
        Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
        morphologyEx(binary, binary, MORPH_OPEN, k, Point(-1, -1));
        Mat dist;
        distanceTransform(binary, dist, DistanceTypes::DIST_L2, 3, CV_32F);
        normalize(dist, dist, 0.0, 1.0, NORM_MINMAX);
    
        // 开始生成标记
        threshold(dist, dist, 0.1, 1.0, THRESH_BINARY);
        normalize(dist, dist, 0, 255, NORM_MINMAX);
        dist.convertTo(dist, CV_8UC1);
    
        // 标记开始
        vector<vector<Point>> contours;
        vector<Vec4i> hireachy;
        findContours(dist, contours, hireachy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
        if (contours.empty()) {
            return Mat();
        }
    
        Mat markers(dist.size(), CV_32S);
        markers = Scalar::all(0);
        for (int i = 0; i < contours.size(); i++) {
            drawContours(markers, contours, i, Scalar(i + 1), -1, 8, hireachy, INT_MAX);
        }
        //填充
        circle(markers, Point(5, 5), 3, Scalar(255), -1);
    
        // 分水岭变换
        watershed(image, markers);
        numComp = contours.size();
        return markers;
    }
    
    void createDisplaySegments(Mat &markers, int numSegments, Mat &image) {
        // generate random color
        vector<Vec3b> colors;
        for (size_t i = 0; i < numSegments; 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));
        }
    
        // 颜色填充与最终显示
        Mat dst = Mat::zeros(markers.size(), CV_8UC3);
        int index = 0;
        for (int row = 0; row < markers.rows; row++) {
            for (int col = 0; col < markers.cols; col++) {
                index = markers.at<int>(row, col);
                if (index > 0 && index <= numSegments) {
                    dst.at<Vec3b>(row, col) = colors[index - 1];
                }
                else {
                    dst.at<Vec3b>(row, col) = Vec3b(255, 255, 255);
                }
            }
        }
        imshow("分水岭图像分割-演示", dst);
        return;
    }
  • 相关阅读:
    Java核心API需要掌握的程度
    JAVA开发者最常去的20个英文网站
    Java .class files decompile tools
    让aptget到网络上查找源,避免经常插入光盘
    Google Job : Research Engineer Beijing
    教你亚健康该如何饮食
    tcpdump w 和 r 的使用
    黑客发布iOS 4.1永久越狱程序 狼人:
    微软将迎来迄今最大补丁日 一次修补49个漏洞 狼人:
    百度瞄准客户端 迅雷、360、腾讯皆是目标 狼人:
  • 原文地址:https://www.cnblogs.com/osbreak/p/11738140.html
Copyright © 2011-2022 走看看