精华内容
下载资源
问答
  • 分水岭图像分割

    2014-07-17 22:27:55
    基于分水岭阈值分割算法实现了图像的阈值分割,利用gdal库实现多种图像格式,适用广泛
  • 一种参数化的形态学分水岭图像分割方法
  • watershed分水岭图像分割方法C++代码_亲测可用
  • 分水岭图像分割算法

    2018-11-11 16:52:19
    采用分水岭分割算法进行图像分割,能比较准确的分割自然条件下的果树等图像。仍有一些不足之处,希望大家指点
  • 基于膨胀运算的分水岭图像分割,王旭,丁世飞,图像分割是图像分析和模式识别的关键环节,同时也是一个经典难题。传统的分水岭变换由于对图像噪声的敏感会产生严重的过分割现象
  • OpenCV基于分水岭图像分割算法

    热门讨论 2013-05-08 18:23:32
    OpenCV基于分水岭图像分割算法,经过分水岭算法后,不同的标记肯定会在不同的区域中,例如头发部分,我画了一条线标记, 处理后就把头发部分分割了出来,还比如胳膊那一块,正好也分割出来了
  • watershed-分水岭图像分割,内含两个分水岭程序,个人曾用自己的测试图片测试过,认为一个效果good,一个效果一般,但针对不同图像效果不同,需要因图像而宜,保证可运行。
  • 图像分割经典算法分水岭图像分割算法 c++实现 很好用
  • 如何利用opencv分水岭图像分割算法threshold来分割图像区域? 函数说明: void watershed( InputArray image, InputOutputArray markers ); image:原图像 markers:包含了轮廓点的数据集合 void distanceTransform...

    如何利用opencv分水岭图像分割算法watershed来分割图像区域?

    函数说明:

    void watershed( InputArray image, InputOutputArray markers );
    image:原图像
    markers:包含了轮廓点的数据集合

    void distanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize)
    src – 8-bit, 单通道(二值化)输入图片。
    dst – 输出结果中包含计算的距离,这是一个32-bit float 单通道的Mat类型数组,大小与输入图片相同。
    distanceType – 计算距离的类型那个,可以是 CV_DIST_L1、CV_DIST_L2 、CV_DIST_C。
    maskSize – 距离变换掩码矩阵的大小

    概述

    分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭算法的一个重要特征。

    使用流程

    总的概括一下watershed图像自动分割的实现步骤:

    1. 图像灰度化、滤波、Canny边缘检测
    2. 查找轮廓,并且把轮廓信息按照不同的编号绘制到watershed的第二个入参merkers上,相当于标记注水点。
    3. watershed分水岭运算
    4. 绘制分割出来的区域,视觉控还可以使用随机颜色填充,或者跟原始图像融合以下,以得到更好的显示效果。

    代码:

    JNIEXPORT void JNICALL
    Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv *, jobject, jlong addrGray,
                                                                     jlong addrRgba) {
        Mat &mGr = *(Mat *) addrGray;
        Mat &mRgb = *(Mat *) addrRgba;
        vector<KeyPoint> v;
    
        looperAddNum++;
        if (looperAddNum > 60) {
            looperAddNum = 0;
            if (looperIndexNum < 100)
                looperIndexNum += 1;
        }
    
    
        // Load the image
        Mat src;
        cvtColor(mRgb, src, COLOR_RGBA2RGB);
        // Check if everything was fine
        // Show source image
        // 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
        // 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 );
        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);
        // 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);
        // 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);
    
        // 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);
        // 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);
            }
        }
    
        cvtColor(dst, mRgb, COLOR_RGB2BGRA);
    
    
        LOGI("index %d", looperIndexNum);
    
    
    }
    
    }
    

    效果:
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 文档里包含了分水岭图像分割的代码以及算法总结,非常全面,代码均为C++代码,简单实用
  • 基于小波的变换的分水岭图像分割方法研究,又需要的可以看看啊
  • 基于形态学梯度重构和标记提取的分水岭图像分割 硕士论文
  • 图像处理,本程序实现了用分水岭算法实现图像分割
  • 区域生长图像分割 regiongrowing (Image,Outregion: Row,Col,Tolerance,MinSize) 函数:regiongrowing (ImageMedian, Regions, 1, 1, 2, 100) ImageMedian:输入的单通道图像 Regions:输出的一组区域 参数3...

    区域生长图像分割

    regiongrowing (Image,Outregion: Row,Col,Tolerance,MinSize)

    函数:regiongrowing (ImageMedian, Regions, 1, 1, 2, 100)

    ImageMedian:输入的单通道图像

    Regions:输出的一组区域

    参数3和4:矩形的宽和高,奇数,可以视为卷积核

    参数5:像素灰度值差-阈值

    参数6:输出区域的最小像素数,默认为100

     

    *区域分割
    read_image (Image, 'mreut')
    dev_close_window ()
    get_image_size (Image, Width, Height)
    dev_open_window (0, 0, Width, Height, 'white', WindowHandle)
    median_image (Image, ImageMedian, 'circle', 2, 'mirrored')
    regiongrowing (ImageMedian, Regions, 1, 1, 2, 100)
    fill_up_shape (Regions, RegionFillUp, 'area', 1, 100)
    closing_circle (RegionFillUp, RegionClosing, 7.5)
    dev_clear_window ()
    dev_set_draw ('fill')
    dev_set_color ('green')
    dev_display (RegionClosing)
    dev_set_color ('black')
    dev_set_draw ('margin')
    dev_display (RegionClosing)

     

    分水岭图像分割

    watersheds_threshold (ImageInvert, Basins, 5)

    参数分别为输入图像;输出盆地区域;灰度阈值

    *分水岭分割
    dev_set_draw ('margin')
    dev_set_colored (12)
    
    read_image (Image, 'pellets')
    dev_display (Image)
    threshold (Image, Region, 105, 255)
    connection (Region, ConnectedRegions)
    select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 20, 99999)
    dev_display (SelectedRegions)
    
    distance_transform (SelectedRegions, DistanceImage, 'octagonal', 'true', 380, 350)
    convert_image_type (DistanceImage, ImageConverted, 'byte')
    invert_image (ImageConverted, ImageInvert)
    watersheds_threshold (ImageInvert, Basins, 5)
    dev_display (Basins)
    intersection (Basins, SelectedRegions, RegionIntersection)
    dev_display (RegionIntersection)

    展开全文
  • //形态学操作 - 彩色图像,目的是去掉干扰,让结果更好 Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); morphologyEx(src, src, MORPH_ERODE, k);//完成分水岭变换 watershed(src, markers...

    #include #include

    using namespacecv;using namespacestd;int main(int argc, char**argv) {

    Mat src= imread("D:/images/coins_001.jpg");if(src.empty()) {

    printf("could not load image...\n");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>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(t), Scalar::all(static_cast(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

    vectorcolors;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(row, col);if (index > 0 && index <=contours.size()) {

    dst.at(row, col) = colors[index - 1];

    }else{

    dst.at(row, col) = Vec3b(0, 0, 0);

    }

    }

    }

    imshow("Final Result", dst);

    printf("number of objects : %d\n", contours.size());

    waitKey(0);return 0;

    }

    展开全文
  • 这里写自定义目录标题图像分割距离变换图像分水岭处理流程代码导出与导入导出导入 图像分割 图像分割(Image Segmentation)是图像处理最重要的处理手段之一。 图像分割的目标是将图像中像素根据一定的规则分为...

    图像分割

    • 图像分割(Image Segmentation)是图像处理最重要的处理手段之一。
    • 图像分割的目标是将图像中像素根据一定的规则分为若干(N)个cluster集合,每个集合包含一类像素。
    • 根据算法分为监督学习方法和无监督学习方法,图像分割的算法多数都是无监督学习方法 (KMeans !)

    距离变换

    距离变换的定义 :计算图像中像素点到最近零像素点的距离,也就是零像素点的最短距离。

    距离变换的常见算法

    • 不断膨胀/腐蚀得到
    • 基于倒角距离(distance transform)
      ------对于一个有特征点和非特征点的二值图像,此距离变换就是求解每一个点到最近特征点的距离

    距离变换常用应用

    • 细化轮廓;
    • 寻找质心;

    API

    C++: void distanceTransform(
    InputArray src,
    OutputArray dst,
    OutputArray labels, 
    int distanceType,
    int maskSize,
    int abelType=DIST_LABEL_CCOMP)
    

    参数说明

    • src – 8-bit, 单通道(二值化)输入图片。
    • dst – 输出结果中包含计算的距离,这是一个32-bit float 单通道的Mat类型数组,大小与输入图片相同。
    • labels – 可选的2D标签输出(离散 Voronoi 图),类型为 CV_32SC1 大小同输入图片。
    • distanceType – 计算距离的类型那个,可以是 CV_DIST_L1、CV_DIST_L2 、CV_DIST_C。
      -----CV_DIST_L2(maskSize=5)的计算结果是精确的,CV_DIST_L2(maskSize=3)是一个快速计算方法。
    • mask_size 距离变换掩模的大小,可以是 3 或 5. 对 CV_DIST_L1 或 CV_DIST_C 的情况,参数值被强制设定为 3, 因为 3×3 mask 给出 5×5 mask 一样的结果

    图像分水岭

    将图像中的边缘转换成”山脉”,将均匀区域转化为“山谷”,这样有助于分割目标

    算法: 基于浸泡理论 ------- 简单来说就是输出图像的极大值

    处理流程

    在这里插入图片描述

    代码

    //关键:画一个圆作为标记这个不理解
    
    # include <opencv2\opencv.hpp>
    # include <iostream>
    using namespace std;
    using namespace cv;
    Mat src, src_gray;
    int main(int argc, char**argv) {
    
    	src = imread("H:\\tuku\\jiuwei.jpg");
    	if (!src.data)
    	{
    		cout << "can't find the picture...";
    		return -1;
    	}
    	imshow("sourceimg", src);
    	//换背景为黑色
    	for (int row = 0; row < src.rows; row++)
    		for (int col = 0; col < src.cols; col++) {
    			if (src.at<Vec3b>(row, col) == Vec3b(255, 255, 255))
    			{
    				src.at<Vec3b>(row, col)[0] = 0;
    				src.at<Vec3b>(row, col)[1] = 0;
    				src.at<Vec3b>(row, col)[2] = 0;
    			}
    		}
    	imshow("blackground src", src);
    	Mat kernel = (Mat_<float>(3, 3) << 1, 1, 1, 1, -8, 1, 1, 1, 1);
    
    	//sharpen
    	Mat imgLaplance;
    	Mat sharpenimg = src;
    	filter2D(src, imgLaplance, CV_32F, kernel, Point(-1, -1),0,BORDER_DEFAULT);
    
    	//拉普拉斯有浮点数计算,位数要提高到32
    	src.convertTo(sharpenimg, CV_32F);
    
    	//原图减边缘(白色)实现边缘增强
    	Mat resultImg = sharpenimg- imgLaplance;
    	resultImg.convertTo(resultImg, CV_8UC3);
    	imshow("sharpen Image", resultImg);
    	src = resultImg;
    	//转化成2值图像
    	Mat binary;
    	cvtColor(resultImg, resultImg, CV_BGR2GRAY);
    	threshold(resultImg, binary, 80, 255, THRESH_BINARY | THRESH_OTSU);
    	imshow("binary", binary);
    
    	//距离变换
    	Mat distImg;
    	distanceTransform(binary, distImg, DIST_L1, 5,CV_32F);
    
    	//归一化
    	normalize(distImg, distImg, 0, 1, NORM_MINMAX);
        imshow("distance chang", distImg);
    
    	//again 二值化
    	threshold(distImg, distImg, 0.55, 1, THRESH_BINARY);
    	imshow("again binary threshold", distImg);
    
    	//腐蚀(使连在一起的分开)
    	Mat k1 = Mat::ones(7,7, CV_8UC1);
    	erode(distImg, distImg, k1);
    	imshow("erode", distImg);
    
    	//标记
    	Mat dist_8u;
    	distImg.convertTo(dist_8u, CV_8U);
    	vector<vector<Point>> contours;
    	vector<Vec4i> hierachy;
    	findContours(dist_8u, contours, hierachy,RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0)); //finContours只支持CV_8UC1的格式,所以要进行通道转换
    
    	//创建标记
    	Mat marsker = Mat::zeros(src.size(), CV_32SC1);// 如果使用 CV_8UC1 ,watershed 函数会报错
    	                      //因为masker最后的边缘存储是-1,所以必须使用有符号的
    	
    	//话标记
    	for (size_t i = 0; i < contours.size(); i++) {
    		drawContours(marsker, contours, static_cast<int>(i), Scalar(static_cast<int>(i) + 1), -1);
    	}
    	circle(marsker, Point(5, 5), 3, Scalar(255, 255, 255), -1);
    	//关键代码!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    	// 创建marker,标记的位置如果在要分割的图像块上会影响分割的结果,如果不创建,分水岭变换会无效
    	imshow("marsker", marsker*1000);  //执行后,dist_m的像素值十分的小,扩大了1000倍,才看出来了轮廓
    
    	//分水岭变换
    	watershed(src, marsker); //根据距离变换的标记,在原图上分离
    	            
    	Mat water = Mat::zeros(marsker.size(), CV_8UC1);
    	marsker.convertTo(water, CV_8UC1);
    	bitwise_not(water, water, Mat());
    	imshow("water Image", water);
    	// 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));
    		
    	}
    	
    		    // fill with color and display final result
    	Mat dst = Mat::zeros(marsker.size(), CV_8UC3);
    	for (int row = 0; row < marsker.rows; row++) {
    		  for (int col = 0; col < marsker.cols; col++) {
    			   int index = marsker.at<int>(row, col);
    			   if (index > 0 && index <= static_cast<int>(contours.size())) {
    		       dst.at<Vec3b>(row, col) = colors[index - 1];
    		
    			}
    		       else {
    			        dst.at<Vec3b>(row, col) = Vec3b(0, 0, 0);
    				     }
    			
    		}
    		
    	}
    	    imshow("Final Result", dst);
    	    waitKey(0);
    	     return 0;
    	waitKey(0);
    	return 0;
    }
    

    输出效果

    在这里插入图片描述在这里插入图片描述

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    输出的图像不知道为何,不是特别理想。第一次写博客,有大神路过请不宁赐教

    展开全文
  • 研究了掌纹识别问题,对掌纹图像特征提取、多特征的融合技术作了一定程度的探讨。采用数学形态学方法提取掌纹线特征;基于Gabor滤波器描述掌纹图像的纹理特征。利用掌纹的线特征和纹理特征两个信息分别作两个分类器...
  • [转载]分水岭图像分割算法

    千次阅读 2013-08-12 15:29:28
    基于形态学分水岭分割 到现在为止,已经讨论了基于3种主要概念的分割方法:(a)间断的检测;(b)门限处理和(c)区域处理。每种方法各有优点(例如,全局门限处理的速度优势)和缺点(如,以灰度级的间断检测为基础的...
  • 求大神们指教 1632601299@qq.com 这是我邮箱。有源码 的大神们指点一下
  • 什么是图像分割图像分割(Image Segmentation)是图像处理最重要的处理手段之一。 图像分割的目标是将图像中像素根据一定的规则分为若干(N)个cluster集合,每个集合包含一类像素。 根据算法分为监督学习方法和无...
  • https://blog.csdn.net/ChangWei_wenzhou/article/details/83583230?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.channel_param demo将对下面这张罗勒叶子使用分水岭图像分割算法... img = cv2.imread(r'C:\Users\Owen\Pictures\luoleye2.jpg') 然后是转换为灰度图,随后二值化。 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #二值化 ret,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,249
精华内容 499
关键字:

分水岭图像分割