分水岭分割算法(watershed segmentation)的C++实现

运行环境:ubuntu16.04+Qt+opencv2.4.13

参考链接:http://blog.csdn.net/u010741471/article/details/45193521

watershedsegmenter.h

#ifndef WATERSHEDSEGMENTER
#define WATERSHEDSEGMENTER

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

class WatershedSegmenter {

  private:
      //用来表示标记(图)
      cv::Mat markers;

  public:
       //设置标记图
      void setMarkers(const cv::Mat& markerImage) {

        //watershed()的输入参数必须为一个32位有符号的标记,所以要先进行转换
        markerImage.convertTo(markers,CV_32S);
      }
      //执行watershed()
      cv::Mat process(const cv::Mat &image) {

        // Apply watershed
        cv::watershed(image,markers);

        return markers;
      }

      // 以图像形式返回结果
      cv::Mat getSegmentation() {

        cv::Mat tmp;
    // 从32S到8U(0-255)会进行饱和运算,所以像素高于255的一律复制为255
        markers.convertTo(tmp,CV_8U);//

        return tmp;
      }

      // 以图像形式返回分水岭(我理解的是分割线)
      cv::Mat getWatersheds() {

        cv::Mat tmp;
        //在设置标记图像,即执行setMarkers()后,边缘的像素会被赋值为-1,其他的用正整数表示
        //下面的这个转换可以让边缘像素变为-1*255+255=0,即黑色,其余的溢出,赋值为255,即白色。
        markers.convertTo(tmp,CV_8U,255,255);
        return tmp;
      }
};

#endif // WATERSHEDSEGMENTER

main.cpp

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "watershedsegmenter.h"

using namespace std;
using namespace cv;

int main()
{
    // Read input image 原图
    Mat image= imread("/home/osksh/skin_c/dulani_anuradha4.jpg");
    if (!image.data)
        return 0;

    // Display the image
    namedWindow("Original Image");
    imshow("Original Image",image);

    Mat binary,fg,bg;
    cvtColor(image,binary,CV_RGBA2GRAY);

    //Display the binary image
    namedWindow("Binary Image");
    imshow("Binary Image",binary);

    // 由二值图像获得前景。腐蚀。移除噪点与微小物体

    erode(binary,fg,cv::Mat(),cv::Point(-1,-1),6);

    // Display the foreground image
    namedWindow("Foreground Image");
    imshow("Foreground Image",fg);

    //膨胀二值图来获取背景(只有草地,没有树林)
    dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),6);
    threshold(bg,bg,150,128,cv::THRESH_BINARY_INV);
    //最后一个参数的表示 ifsrc>1,dst=0,else dst=128。这样就使背景全为灰色(128)
    // Display the background image
    namedWindow("Background Image");
    imshow("Background Image",bg);

    // Show markers image
    Mat markers(binary.size(),CV_8U,cv::Scalar(0));
    markers= fg+bg;//使用重载操作符+
    namedWindow("Markers");
    imshow("Markers",markers);

    // Create watershed segmentation object
    WatershedSegmenter segmenter;

    // Set markers and process
    segmenter.setMarkers(markers);
    segmenter.process(image);

    // Display segmentation result
    namedWindow("Segmentation");
    imshow("Segmentation",segmenter.getSegmentation());

    // Display watersheds
    namedWindow("Watersheds");
    imshow("Watersheds",segmenter.getWatersheds());

    waitKey(0);
    return 0;
}
时间: 2024-10-14 23:11:20

分水岭分割算法(watershed segmentation)的C++实现的相关文章

基于Matlab的标记分水岭分割算法

转自:http://blog.sina.com.cn/lyqmath 1 综述 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 basins"(

Matlab的标记分水岭分割算法

1 综述 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 basins"(集水盆) and "watershed ridge line

分水岭分割算法

建立不同目标间的分水岭(涨水法). 分水岭计算步骤: 1.设待分割图象为f(x,y),其梯度图象为g(x,y) 2.用M1, M2, -, MR表示g(x, y)中各局部极小值的象素,位置,C(Mi)为与Mi对应的区域中的象素坐标集合 3.用n表示当前灰度阈值,T[n]代表记为(u,v)的象素集合,g(u,v)<n, 4.对Mi所在的区域,其中满足条件的坐标集合Cn(Mi)可看作一幅二值图象 令 S 代表T[n]中的连通组元集合,对每个连通组元 ,s∈S[n],有3种可能性: (1) S ∩ C

stl_algorithm算法之分割算法

分割算法: 7.49.template <class InputIterator, class UnaryPredicate> bool is_partitioned (InputIterator first, InputIterator last, UnaryPredicate pred) { while (first!=last && pred(*first)) { //第一个while找到左边所有连续的符合pred函数的元素 ++first; } while (first

MP4文件格式的解析,以及MP4文件的分割算法

mp4应该算是一种比较复杂的媒体格式了,起源于QuickTime.以前研究的时候就花了一番的功夫,尤其是如何把它完美的融入到视频点播应用中,更是费尽了心思,主要问题是处理mp4文件庞大的"媒体头".当然,流媒体点播也可以采用flv格式来做,flv也可以封装H.264视频数据的,不过Adobe却不推荐这么做,人家说毕竟mp4才是H.264最佳的存储格式嘛. 这几天整理并重构了一下mp4文件的解析程序,融合了分解与合并的程序,以前是c语言写的,应用在linux上运行的服务器程序上,现在改成

OpenCV学习(20) grabcut分割算法

http://www.cnblogs.com/mikewolf2002/p/3330390.html OpenCV学习(20) grabcut分割算法 在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好.算法的原理参见papaer:“GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts 比如下面的一副图,我们只要选定一个四边形框,把框中的图像作为gra

快速中的分割算法的解析与应用

一,分割(partition)算法介绍 所谓分割算法,先选定一个枢轴元素,然后 将数组中的元素分成两部分:比枢轴元素小的部分都位于枢轴元素左边:比枢轴元素大的部分都位于枢轴元素右边 此时,枢轴元素在数组中的位置就被“永久地确定”下来了---将整个数组排序,该枢轴元素的位置不会变化. 另外,枢轴元素的选取对分割算法至关重要.一般而言,终极追求的是:将数组平分.因此,尽可能地让枢轴元素的选取随机化和靠近中位数. 这里采用“三数取中”法选取枢轴元素. 关于快速排序排序算法,可参考:http://www

基于数据波动性的分割算法

我们常见的分割算法有很多种,比如能量法,包络线法之类的,但这些算法难以实现实时分割,今天我给大家分享一个原创的分割算法,是在以前项目中用过的,这两天加以优化,最中整理了一个MATLAB版本的,给大家分享一下. 算法的原理简单介绍一下: 这里给出了一段肌音信号(已经分割好了),是用加速度传感器在手上采集的,每次完成一次动作,就会产生一个数据波动,如果我们需要分析这样一段信号的特征,需要先将这些信号分割出来.   我们在分析时,主要任务时提取出信号帧起始点对应的数据索引,这里我写了一个分割函数: f

OpenCV 源码中分水岭算法 watershed 函数源码注解

为了研究分水岭算法,阅读了OpenCV 2.4.9 中watershed函数的源码实现部分,代码位于 opencv\sources\modules\imgproc\src\segmentation.cpp 文件中.先贴出加了注解的代码,以后补充对分水岭算法的解释. #include "precomp.hpp" /******************************************************* Watershed **********************