精华内容
下载资源
问答
  • watershed算法

    2011-11-20 00:02:53
    watershed的代码,是学习的好资料啊,经典的代码的啊,要的话赶紧下啊
  • Watershed算法

    2017-06-01 20:19:25
    先找一些资料,然后再分析和实现 参考资料: http://cmm.ensmp.fr/~beucher/wtshed....https://cn.mathworks.com/company/newsletters/articles/the-watershed-transform-strategies-for-image-segmentation.html
    展开全文
  • 图像分割学习opencv是为了工程应用,只学习不应用,等于白学习。下面分析一个图像分割的例子,以加强学习。目标 学习使用cv::filter2D执行一些...学习使用cv::watershed从背景中隔离物体 代码#include <opencv2/

    图像分割

    学习opencv是为了工程应用,只学习不应用,等于白学习。下面分析一个图像分割的例子,以加强学习。

    目标

    • 学习使用cv::filter2D执行一些laplacian滤波来锐化图像
    • 学习使用cv::distanceTransform来获得二进制图像的导出表示,其中每个像素的值被替换为最近的背景像素的距离
    • 学习使用cv::watershed从背景中隔离物体

    代码

    #include <opencv2/opencv.hpp>
    #include <iostream>
    using namespace std;
    using namespace cv;
    int main(int, char** argv)
    {
        // Load the image
        Mat src = imread(argv[1]);
        // Check if everything was fine
        if (!src.data)
            return -1;
        // Show source image
        imshow("Source Image", src);
        // Change the background from white to black, since that will help later to extract
        // better results during the use of Distance Transform
        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;
              }
            }
        }
        // Show output image
        imshow("Black Background Image", src);
        // Create a kernel that we will use for accuting/sharpening our image
        Mat kernel = (Mat_<float>(3,3) <<
                1,  1, 1,
                1, -8, 1,
                1,  1, 1); // an approximation of second derivative, a quite strong kernel
        // do the laplacian filtering as it is
        // well, we need to convert everything in something more deeper then CV_8U
        // because the kernel has some negative values,
        // and we can expect in general to have a Laplacian image with negative values
        // BUT a 8bits unsigned int (the one we are working with) can contain values from 0 to 255
        // so the possible negative number will be truncated
        Mat imgLaplacian;
        Mat sharp = src; // copy source image to another temporary one
        filter2D(sharp, imgLaplacian, CV_32F, kernel);
        src.convertTo(sharp, CV_32F);
        Mat imgResult = sharp - imgLaplacian;
        // convert back to 8bits gray scale
        imgResult.convertTo(imgResult, CV_8UC3);
        imgLaplacian.convertTo(imgLaplacian, CV_8UC3);
        // imshow( "Laplace Filtered Image", imgLaplacian );
        imshow( "New Sharped Image", imgResult );
        src = imgResult; // copy back
        // Create binary image from source image
        Mat bw;
        cvtColor(src, bw, CV_BGR2GRAY);
        threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
        imshow("Binary Image", bw);
        // Perform the distance transform algorithm
        Mat dist;
        distanceTransform(bw, dist, CV_DIST_L2, 3);
        // Normalize the distance image for range = {0.0, 1.0}
        // so we can visualize and threshold it
        normalize(dist, dist, 0, 1., NORM_MINMAX);
        imshow("Distance Transform Image", dist);
        // Threshold to obtain the peaks
        // This will be the markers for the foreground objects
        threshold(dist, dist, .4, 1., CV_THRESH_BINARY);
        // Dilate a bit the dist image
        Mat kernel1 = Mat::ones(3, 3, CV_8UC1);
        dilate(dist, dist, kernel1);
        imshow("Peaks", dist);
        // Create the CV_8U version of the distance image
        // It is needed for findContours()
        Mat dist_8u;
        dist.convertTo(dist_8u, CV_8U);
        // Find total markers
        vector<vector<Point> > contours;
        findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
        // Create the marker image for the watershed algorithm
        Mat markers = Mat::zeros(dist.size(), CV_32SC1);
        // Draw the foreground markers
        for (size_t i = 0; i < contours.size(); i++)
            drawContours(markers, contours, static_cast<int>(i), Scalar::all(static_cast<int>(i)+1), -1);
        // Draw the background marker
        circle(markers, Point(5,5), 3, CV_RGB(255,255,255), -1);
        imshow("Markers", markers*10000);
        // Perform the watershed algorithm
        watershed(src, markers);
        Mat mark = Mat::zeros(markers.size(), CV_8UC1);
        markers.convertTo(mark, CV_8UC1);
        bitwise_not(mark, mark);
    //    imshow("Markers_v2", mark); // uncomment this if you want to see how the mark
                                      // image looks like at that point
        // Generate random colors
        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));
        }
        // Create the result image
        Mat dst = Mat::zeros(markers.size(), CV_8UC3);
        // Fill labeled objects with random colors
        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);
            }
        }
        // Visualize the final image
        imshow("Final Result", dst);
        waitKey(0);
        return 0;

    代码说明

    1. 通过文件加载图像,并检查显示。
        // Load the image
        Mat src = imread(argv[1]);
        // Check if everything was fine
        if (!src.data)
            return -1;
        // Show source image
        imshow("Source Image", src);

    2.如果图像背景是白色的,最好转化成黑色的,在距离变换时这将有助于前景区分对象。(这个操作很生硬,因为很多时候图像都不是纯色)

        // Change the background from white to black, since that will help later to extract
        // better results during the use of Distance Transform
        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;
              }
            }
        }
        // Show output image
        imshow("Black Background Image", src);

    3.接下来锐化图像来强化前景物体的边缘。通过使用laplacian滤波。

        // Create a kernel that we will use for accuting/sharpening our image
        Mat kernel = (Mat_<float>(3,3) <<
                1,  1, 1,
                1, -8, 1,
                1,  1, 1); // an approximation of second derivative, a quite strong kernel
        // do the laplacian filtering as it is
        // well, we need to convert everything in something more deeper then CV_8U
        // because the kernel has some negative values,
        // and we can expect in general to have a Laplacian image with negative values
        // BUT a 8bits unsigned int (the one we are working with) can contain values from 0 to 255
        // so the possible negative number will be truncated
        Mat imgLaplacian;
        Mat sharp = src; // copy source image to another temporary one
        filter2D(sharp, imgLaplacian, CV_32F, kernel);
        src.convertTo(sharp, CV_32F);
        Mat imgResult = sharp - imgLaplacian;
        // convert back to 8bits gray scale
        imgResult.convertTo(imgResult, CV_8UC3);
        imgLaplacian.convertTo(imgLaplacian, CV_8UC3);
        // imshow( "Laplace Filtered Image", imgLaplacian );
        imshow( "New Sharped Image", imgResult );

    4.转成灰度图像和二值化。

        // Create binary image from source image
        Mat bw;
        cvtColor(src, bw, CV_BGR2GRAY);
        threshold(bw, bw, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
        imshow("Binary Image", bw);

    5.应用Distance Tranform于二值化的图像。另外,我们通过normalize处理图像。

        // Perform the distance transform algorithm
        Mat dist;
        distanceTransform(bw, dist, CV_DIST_L2, 3);
        // Normalize the distance image for range = {0.0, 1.0}
        // so we can visualize and threshold it
        normalize(dist, dist, 0, 1., NORM_MINMAX);
        imshow("Distance Transform Image", dist);

    6.二值化图像然后执行腐蚀操作。

        // Threshold to obtain the peaks
        // This will be the markers for the foreground objects
        threshold(dist, dist, .4, 1., CV_THRESH_BINARY);
        // Dilate a bit the dist image
        Mat kernel1 = Mat::ones(3, 3, CV_8UC1);
        dilate(dist, dist, kernel1);
        imshow("Peaks", dist);

    7.从每一个小块上创建标记给watershed 算法

        // Create the CV_8U version of the distance image
        // It is needed for findContours()
        Mat dist_8u;
        dist.convertTo(dist_8u, CV_8U);
        // Find total markers
        vector<vector<Point> > contours;
        findContours(dist_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
        // Create the marker image for the watershed algorithm
        Mat markers = Mat::zeros(dist.size(), CV_32SC1);
        // Draw the foreground markers
        for (size_t i = 0; i < contours.size(); i++)
            drawContours(markers, contours, static_cast<int>(i), Scalar::all(static_cast<int>(i)+1), -1);
        // Draw the background marker
        circle(markers, Point(5,5), 3, CV_RGB(255,255,255), -1);
        imshow("Markers", markers*10000);

    8.最后,我们使用watershed算法,并且可视化它。

        // Perform the watershed algorithm
        watershed(src, markers);
        Mat mark = Mat::zeros(markers.size(), CV_8UC1);
        markers.convertTo(mark, CV_8UC1);
        bitwise_not(mark, mark);
    //    imshow("Markers_v2", mark); // uncomment this if you want to see how the mark
                                      // image looks like at that point
        // Generate random colors
        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));
        }
        // Create the result image
        Mat dst = Mat::zeros(markers.size(), CV_8UC3);
        // Fill labeled objects with random colors
        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);
            }
        }
        // Visualize the final image
        imshow("Final Result", dst);
    
    展开全文
  • 我们将学习使用分水岭算法实现基于标记的图像分割 我们将看到:cv.watershed() 理论 任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷...

    目标

    在本章中,

    • 我们将学习使用分水岭算法实现基于标记的图像分割
    • 我们将看到:cv.watershed()

    理论

    任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水位的上升,根据附近的山峰(坡度),来自不同山谷的水明显会开始合并,颜色也不同。为了避免这种情况,你要在水融合的地方建造屏障。你继续填满水,建造障碍,直到所有的山峰都在水下。然后你创建的屏障将返回你的分割结果。这就是Watershed背后的“思想”。你可以访问Watershed的CMM网页,了解它与一些动画的帮助。

    但是这种方法会由于图像中的噪声或其他不规则性而产生过度分割的结果。因此OpenCV实现了一个基于标记的分水岭算法,你可以指定哪些是要合并的山谷点,哪些不是。这是一个交互式的图像分割。我们所做的是给我们知道的对象赋予不同的标签。用一种颜色(或强度)标记我们确定为前景或对象的区域,用另一种颜色标记我们确定为背景或非对象的区域,最后用0标记我们不确定的区域。这是我们的标记。然后应用分水岭算法。然后我们的标记将使用我们给出的标签进行更新,对象的边界值将为-1

    代码

    下面我们将看到一个有关如何使用距离变换和分水岭来分割相互接触的对象的示例。

    考虑下面的硬币图像,硬币彼此接触。即使你设置阈值,它也会彼此接触。

    我们先从寻找硬币的近似估计开始。因此,我们可以使用Otsu的二值化。

    import numpy as np
    import cv2 as cv
    from matplotlib import pyplot as plt
    img = cv.imread('coins.png')
    gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV cv.THRESH_OTSU)

    现在我们需要去除图像中的任何白点噪声。为此,我们可以使用形态学扩张。要去除对象中的任何小孔,我们可以使用形态学侵蚀。因此,现在我们可以确定,靠近对象中心的区域是前景,而离对象中心很远的区域是背景。我们不确定的唯一区域是硬币的边界区域。

    因此,我们需要提取我们可确定为硬币的区域。侵蚀会去除边界像素。因此,无论剩余多少,我们都可以肯定它是硬币。如果物体彼此不接触,那将起作用。但是,由于它们彼此接触,因此另一个好选择是找到距离变换并应用适当的阈值。接下来,我们需要找到我们确定它们不是硬币的区域。为此,我们扩张了结果。膨胀将对象边界增加到背景。这样,由于边界区域已删除,因此我们可以确保结果中背景中的任何区域实际上都是背景。参见下图。

    剩下的区域是我们不知道的区域,无论是硬币还是背景。分水岭算法应该找到它。这些区域通常位于前景和背景相遇(甚至两个不同的硬币相遇)的硬币边界附近。我们称之为边界。可以通过从sure_bg区域中减去sure_fg区域来获得。

    # 噪声去除
    kernel = np.ones((3,3),np.uint8)
    opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)
    # 确定背景区域
    sure_bg = cv.dilate(opening,kernel,iterations=3)
    # 寻找前景区域
    dist_transform = cv.distanceTransform(opening,cv.DIST_L2,5)
    ret, sure_fg = cv.threshold(dist_transform,0.7*dist_transform.max(),255,0)
    # 找到未知区域
    sure_fg = np.uint8(sure_fg)
    unknown = cv.subtract(sure_bg,sure_fg)

    查看结果。在阈值图像中,我们得到了一些硬币区域,我们确定它们是硬币,并且现在已分离它们。(在某些情况下,你可能只对前景分割感兴趣,而不对分离相互接触的对象感兴趣。在那种情况下,你无需使用距离变换,只需侵蚀就足够了。侵蚀只是提取确定前景区域的另一种方法。)

    现在我们可以确定哪些是硬币的区域,哪些是背景。因此,我们创建了标记(它的大小与原始图像的大小相同,但具有int32数据类型),并标记其中的区域。我们肯定知道的区域(无论是前景还是背景)都标有任何正整数,但是带有不同的整数,而我们不确定的区域则保留为零。为此,我们使用cv.connectedComponents()。它用0标记图像的背景,然后其他对象用从1开始的整数标记。

    但是我们知道,如果背景标记为0,则分水岭会将其视为未知区域。所以我们想用不同的整数来标记它。相反,我们将未知定义的未知区域标记为0。

    # 类别标记
    ret, markers = cv.connectedComponents(sure_fg)
    # 为所有的标记加1,保证背景是0而不是1
    markers = markers 1
    # 现在让所有的未知区域为0
    markers[unknown==255] = 0

    参见JET colormap中显示的结果。深蓝色区域显示未知区域。当然,硬币的颜色不同。剩下,肯定为背景的区域显示在较浅的蓝色,跟未知区域相比。

    现在我们的标记已准备就绪。现在是最后一步的时候了,使用分水岭算法。然后标记图像将被修改。边界区域将标记为-1。

    markers = cv.watershed(img,markers) 
    img[markers == -1] = [255,0,0]

    请参阅下面的结果。对某些硬币,它们接触的区域被正确地分割,而对于某些硬币,却不是。

    附加资源

    1. CMM page on Watershed Transformation

    练习

    1. OpenCV samples has an interactive sample on watershed segmentation, watershed.py. Run it, Enjoy it, then learn it.

    欢迎关注磐创博客资源汇总站:http://docs.panchuang.net/

    欢迎关注PyTorch官方中文教程站:http://pytorch.panchuang.net/

    OpenCV中文官方文档:http://woshicver.com/

    展开全文
  • 目标在本章中,我们将学习使用分水岭算法实现基于标记的图像分割我们将看到:cv.watershed()理论任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。你开始用不同颜色的水(标签)填充每个...

    目标

    在本章中,

    • 我们将学习使用分水岭算法实现基于标记的图像分割
    • 我们将看到:cv.watershed()

    理论

    任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水位的上升,根据附近的山峰(坡度),来自不同山谷的水明显会开始合并,颜色也不同。为了避免这种情况,你要在水融合的地方建造屏障。你继续填满水,建造障碍,直到所有的山峰都在水下。然后你创建的屏障将返回你的分割结果。这就是Watershed背后的“思想”。你可以访问Watershed的CMM网页,了解它与一些动画的帮助。

    但是这种方法会由于图像中的噪声或其他不规则性而产生过度分割的结果。因此OpenCV实现了一个基于标记的分水岭算法,你可以指定哪些是要合并的山谷点,哪些不是。这是一个交互式的图像分割。我们所做的是给我们知道的对象赋予不同的标签。用一种颜色(或强度)标记我们确定为前景或对象的区域,用另一种颜色标记我们确定为背景或非对象的区域,最后用0标记我们不确定的区域。这是我们的标记。然后应用分水岭算法。然后我们的标记将使用我们给出的标签进行更新,对象的边界值将为-1。

    代码

    下面我们将看到一个有关如何使用距离变换和分水岭来分割相互接触的对象的示例。

    考虑下面的硬币图像,硬币彼此接触。即使你设置阈值,它也会彼此接触。

    024277ce3359d5afdfbeb5b7a75bfa54.png

    我们先从寻找硬币的近似估计开始。因此,我们可以使用Otsu的二值化。

    import numpy as npimport cv2 as cvfrom matplotlib import pyplot as pltimg = cv.imread('coins.png')gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)
    aa1a7b9590c41c786a147367d1fba3a7.png

    现在我们需要去除图像中的任何白点噪声。为此,我们可以使用形态学扩张。要去除对象中的任何小孔,我们可以使用形态学侵蚀。因此,现在我们可以确定,靠近对象中心的区域是前景,而离对象中心很远的区域是背景。我们不确定的唯一区域是硬币的边界区域。

    因此,我们需要提取我们可确定为硬币的区域。侵蚀会去除边界像素。因此,无论剩余多少,我们都可以肯定它是硬币。如果物体彼此不接触,那将起作用。但是,由于它们彼此接触,因此另一个好选择是找到距离变换并应用适当的阈值。接下来,我们需要找到我们确定它们不是硬币的区域。为此,我们扩张了结果。膨胀将对象边界增加到背景。这样,由于边界区域已删除,因此我们可以确保结果中背景中的任何区域实际上都是背景。参见下图。

    92ab995f8b7fd200849a1f12b2dda3cf.png

    剩下的区域是我们不知道的区域,无论是硬币还是背景。分水岭算法应该找到它。这些区域通常位于前景和背景相遇(甚至两个不同的硬币相遇)的硬币边界附近。我们称之为边界。可以通过从sure_bg区域中减去sure_fg区域来获得。

    # 噪声去除kernel = np.ones((3,3),np.uint8)opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)# 确定背景区域sure_bg = cv.dilate(opening,kernel,iterations=3)# 寻找前景区域dist_transform = cv.distanceTransform(opening,cv.DIST_L2,5)ret, sure_fg = cv.threshold(dist_transform,0.7*dist_transform.max(),255,0)# 找到未知区域sure_fg = np.uint8(sure_fg)unknown = cv.subtract(sure_bg,sure_fg)

    查看结果。在阈值图像中,我们得到了一些硬币区域,我们确定它们是硬币,并且现在已分离它们。(在某些情况下,你可能只对前景分割感兴趣,而不对分离相互接触的对象感兴趣。在那种情况下,你无需使用距离变换,只需侵蚀就足够了。侵蚀只是提取确定前景区域的另一种方法。)

    85680416c762b2a64c3d99a6293097fe.png

    现在我们可以确定哪些是硬币的区域,哪些是背景。因此,我们创建了标记(它的大小与原始图像的大小相同,但具有int32数据类型),并标记其中的区域。我们肯定知道的区域(无论是前景还是背景)都标有任何正整数,但是带有不同的整数,而我们不确定的区域则保留为零。为此,我们使用cv.connectedComponents()。它用0标记图像的背景,然后其他对象用从1开始的整数标记。

    但是我们知道,如果背景标记为0,则分水岭会将其视为未知区域。所以我们想用不同的整数来标记它。相反,我们将未知定义的未知区域标记为0。

    # 类别标记ret, markers = cv.connectedComponents(sure_fg)# 为所有的标记加1,保证背景是0而不是1markers = markers+1# 现在让所有的未知区域为0markers[unknown==255] = 0

    参见JET colormap中显示的结果。深蓝色区域显示未知区域。当然,硬币的颜色不同。剩下,肯定为背景的区域显示在较浅的蓝色,跟未知区域相比。

    17ae06ade64dfc5513f9178defd8178a.png

    现在我们的标记已准备就绪。现在是最后一步的时候了,使用分水岭算法。然后标记图像将被修改。边界区域将标记为-1。

    markers = cv.watershed(img,markers) img[markers == -1] = [255,0,0]

    请参阅下面的结果。对某些硬币,它们接触的区域被正确地分割,而对于某些硬币,却不是。

    5fb9f137a99762d40d59080c0a99ec3c.png

    附加资源

    1. CMM page on http://cmm.ensmp.fr/~beucher/wtshed.html

    练习

    1. OpenCV samples has an interactive sample on watershed segmentation, watershed.py. Run it, Enjoy it, then learn it.
    展开全文
  • marke) cv.waitKey(0) markers = cv.watershed(img,markers) #Watershed算法 第一个参数是图像,第二个参数是标记图 #会根据markers传入的轮廓作为种子(也就是所谓的注水点), #对图像上其他的像素点根据分水岭...
  • 目标在本章中,我们将学习使用分水岭算法实现基于标记的图像分割我们将看到:cv.watershed()理论任何灰度图像都可以看作是一个地形表面,其中高强度...
  • 我们将学习使用分水岭算法实现基于标记的图像分割 - 我们将看到:cv.watershed() 理论 任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷...
  • 目前有很多图像分割方法,其中分水岭算法是一种基于区域的图像分割算法,分水岭算法因实现方便,已经在医疗图像,模式识别等领域得到了广泛的应用。 传统分水岭算法基本原理 分水岭比较经典的计算方法是L.Vincent于...
  • watershed分水岭算法

    2017-09-19 16:17:46
    所谓分水岭算法有好多种实现算法,拓扑学,形态学,浸水模拟和降水模拟等方式。要搞懂就不容易了。Watershed Algorithm(分水岭算法),顾名思义,就是根据分水岭的构成来考虑图像的分割。
  • watershed分水岭算法的源代码

    热门讨论 2009-11-15 11:52:32
    watershed分水岭算法的源代码,一个很实用的用于图像分割的算法
  • Watershed分水岭分割算法,学习一下吧哈哈哈
  • 1. watershed  void watershed( InputArray image, InputOutputArray markers ); 第一个参数 image,必须是一个8bit 3通道彩色图像矩阵序列,第一个参数没什么要说的。 关键是第二个参数 markers:在执行分水岭...
  • 最近需要做一个图像分割的程序,查了opencv的源代码,发现opencv里实现的图像分割一共有两个方法,watershed和mean-shift算法。这两个算法的具体实现都在segmentation.cpp文件内。 watershed(分水岭算法)方法是一...
  • 根据官方文档The function implements one of the variants of watershed, non-parametric marker-based segmentation algorithm, described in [161] .[161] Fernand Meyer. Color image segmentation. In Image ...
  • opencv watershed demo: http://download.csdn.net/detail/keen_zuxwang/9852585 分水岭算法 1、一种基于拓扑理论的数学形态学的图像分割方法。分水岭算法容易导致图像的过度分割。opencv中,使用预定义的一组...
  • watershed分水岭算法的matlab例子详解

    万次阅读 2014-11-24 21:45:14
    今天本来想试试mser算法的,结果没看懂。就先看看类似的fen'shui'l
  • matlab之watershed分水岭分割算法

    千次阅读 2017-02-22 14:34:04
    Separating touching objects in an image is one of the more difficult image processing operations. The watershed transform is often applied to this problem. The watershed transform finds "catchment bas

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 282
精华内容 112
关键字:

watershed算法