【OpenCV】图像分割

来源:互联网 发布:java 关键字 编辑:程序博客网 时间:2024/05/16 15:42

距离变换和分水岭算法的图像分割

#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;int main(){    Mat src = imread("../data/cards.jpg");    if (src.empty()) { return -1; }                                 for (int x = 0; x < src.rows; x++)        for (int y = 0; y < src.cols; y++)            if (src.at<Vec3b>(x, y) == Vec3b(255, 255, 255))    // 将背景的白色转换成黑色            {                                                                   src.at<Vec3b>(x, y)[0] = 0;                src.at<Vec3b>(x, y)[1] = 0;                src.at<Vec3b>(x, y)[2] = 0;            }    imshow("Black Background Image", src);                      Mat kernel = (Mat_<float>(3, 3) <<                          // 二阶导数,拉普拉斯        1, 1, 1,        1, -8, 1,        1, 1, 1);    Mat imgLaplacian;    Mat sharp = src;    filter2D(sharp, imgLaplacian, CV_32F, kernel);              // 拉普拉斯滤波    src.convertTo(sharp, CV_32F);    Mat imgResult = sharp - imgLaplacian;                       // 减去后者的白色边缘,得到图像黑色边缘加深    imgResult.convertTo(imgResult, CV_8UC3);                    // 处理目的是截断拉普拉斯运算后的负值    imgLaplacian.convertTo(imgLaplacian, CV_8UC3);    imshow("Laplacian Image", imgLaplacian);    imshow("Sharped Image", imgResult);    Mat bw;    src = imgResult;    cvtColor(src, bw, CV_BGR2GRAY);    threshold(bw,bw,40,255,CV_THRESH_BINARY | CV_THRESH_OTSU);  // 二值化图像    imshow("Binary Image", bw);    Mat dist;    distanceTransform(bw, dist, CV_DIST_L2, 3);                 // 距离变换    normalize(dist, dist, 0, 1, NORM_MINMAX);                   // 归一化    imshow("Distance Transform", dist);    threshold(dist, dist, .4, 1, CV_THRESH_BINARY);             // 阈值分割    Mat kernel1 = Mat::ones(3, 3, CV_8UC1);    dilate(dist, dist, kernel1);                                // 膨胀处理    imshow("Dilate", dist);    Mat dist_8u;    dist.convertTo(dist_8u, CV_8U);    vector<vector<Point>> contours;                             // 轮廓检测    findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);    Mat markers = Mat::zeros(dist.size(), CV_32SC1);    for (size_t i = 0; i < contours.size(); i++)                // 绘制轮廓        drawContours(markers, contours, static_cast<int>(i), Scalar::all(static_cast<int>(i) + 1));    circle(markers, Point(5, 5), 3, CV_RGB(255, 255, 255), -1);    imshow("Markers", markers * 100000);    watershed(src, markers);                                    // 分水岭    imshow("watershed", markers * 100000);    Mat mark = Mat::zeros(markers.size(), CV_8UC1);    markers.convertTo(mark, CV_8UC1);    bitwise_not(mark, mark);                                    // 图像反转    imshow("Markers_v2", mark);    vector<Vec3b> colors;    for (size_t i = 0; i < contours.size(); i++)                // 随机数    {        int b = theRNG().uniform(0, 255);        int g = theRNG().uniform(0, 255);        int r = theRNG().uniform(0, 255);        colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));    }    Mat dst = Mat::zeros(markers.size(), CV_8UC3);    for (int i = 0; i < markers.rows; i++)        for (int j = 0; j < markers.cols; j++)        {            int index = markers.at<int>(i, j);            if (index > 0 && index <= static_cast<int>(contours.size()))                dst.at<Vec3b>(i, j) = colors[index - 1];            else                dst.at<Vec3b>(i, j) = Vec3b(0, 0, 0);        }    imshow("Final Result", dst);    waitKey(0);    return 0;}


运行结果




原创粉丝点击