精华内容
下载资源
问答
  • opencv图像处理基础总结,基于分水岭算法的图像分割,介绍了分水岭算法的原理、距离变换、opencv有关函数的用法,基于距离的分水岭分割的流程,python代码实现分水岭算法的图像分割

    一、 原理

    1. 分水岭算法原理

    • 任何一副灰度图像都可以被看成拓扑平面,灰度值高的区域可以被看成是山峰,灰度值低的区域可以被看成是山谷。我们向每一个山谷中灌不同颜色的水。随着水的位的升高,不同山谷的水就会相遇汇合,为了防止不同山谷的水汇合,我们需要在水汇合的地方构建起堤坝。不停地灌水,不停地构建堤坝知道所有的山峰都被水淹没。我们构建好的堤坝就是对图像的分割,这就是分水岭算法的背后原理。
    • OpenCV 采用了基于掩模的分水岭算法,在这种算法中我们要设置那些山谷点会汇合,那些不会。这是一种交互式的图像分割,我们要做的就是给我们已知的对象打上不同的标签。如果某个区域肯定是前景或对象,就使用某个颜色(或灰度值)标签标记它。如果某个区域肯定不是对象而是背景就使用另外一个颜色标签标记。而剩下的不能确定是前景还是背景的区域就用 0 标记,这就是我们的标签。然后实施分水岭算法。每一次灌水,我们的标签就会被更新,当两个不同颜色的标签相遇时就构建堤坝,直到将所有山峰淹没,最后我们得到的边界对象(堤坝)的值为 -1。

    2. 距离变换

    • 距离变换的基本含义是计算一个图像中非零像素点到最近的零像素点的距离,也就是到零像素点的最短距离
    • 最常见的距离变换算法就是通过连续的腐蚀操作来实现,腐蚀操作的停止条件是所有前景像素都被完全
    • 腐蚀。这样根据腐蚀的先后顺序,我们就得到各个前景像素点到前景中心骨架像素点的距离
    • 根据各个像素点的距离值,设置为不同的灰度值。这样就完成了二值图像的距离变换

    3. opencv有关函数的用法

    cv2.distanceTransform(src, distanceType, maskSize, dst=None, dstType=None)
    
    • src:输入二值图像
    • distanceType:计算距离的方式
    • maskSize:蒙板尺寸
    cv2.connectedComponents(image, labels=None, connectivity=None, ltype=None)
    
    • image:输入8位单通道图像
    • labels:输出标签地图
    • connectivity:连通性,默认8,还可以取4
    • Itype:输出标签类型 ,默认 CV_32S, 还可以取CV_16U
    cv2.watershed(image, markers)
    
    • image:输入图像
    • markers:标记

    二、基于距离的分水岭分割流程

    • 输入图像,有噪声的话,先进行去噪
    • 转成灰度图像
    • 二值化处理、形态学操作
    • 距离变换
    • 寻找种子、生成marker
    • 实施分水岭算法、输出分割后的图像

    三、python代码实现

    """
    @Author  :叶庭云
    @Date    :2020/9/18 15:01
    @CSDN	 :https://blog.csdn.net/fyfugoyfa
    """
    import cv2 as cv
    import numpy as np
    
    
    def watershed_algorithm(image):
        # 边缘保留滤波EPF  去噪
        blur = cv.pyrMeanShiftFiltering(image,sp=10,sr=100)
        # 转成灰度图像
        gray = cv.cvtColor(blur, cv.COLOR_BGR2GRAY)
        # 得到二值图像   自适应阈值
        ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
        cv.imshow('binary image', binary)
    
        # 形态学操作   获取结构元素  开操作
        kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
        opening = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel=kernel, iterations=2)
        # 确定区域
        sure_bg = cv.dilate(opening, kernel, iterations=3)
        # cv.imshow('mor-opt', sure_bg)
    
        # 距离变换
        dist = cv.distanceTransform(opening, cv.DIST_L2, 3)
        dist_out = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
        # cv.imshow('distance-', dist_out * 50)
        ret, surface = cv.threshold(dist_out, dist_out.max() * 0.6, 255, cv.THRESH_BINARY)
        # cv.imshow('surface-markers', surface)
    
        surface_fg = np.uint8(surface)    # 转成8位整型
        unkonown = cv.subtract(sure_bg, surface_fg)        # 找到位置区域
        # Marker labelling
        ret, markers = cv.connectedComponents(surface_fg)  # 连通区域
        print(ret)
    
        # 分水岭变换
        # Add one to all labels so that sure background is not 0, but 1
        markers = markers + 1
        # Now, mark the region of unknown with zero
        markers[unkonown == 255] = 0
        # 实施分水岭算法了。标签图像将会被修改,边界区域的标记将变为 -1
        markers = cv.watershed(image, markers=markers)
        image[markers == -1] = [0, 0, 255]      # 被标记的区域   设为红色
        cv.imshow('result', image)
    
    
    src = cv.imread(r'./test/042.png')
    src = cv.resize(src, None, fx=0.5, fy=0.5)
    cv.imshow('input image', src)
    watershed_algorithm(src)
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    运行效果如下:



    作者:叶庭云
    CSDN:https://blog.csdn.net/fyfugoyfa
    本文仅用于交流学习,未经作者允许,禁止转载,更勿做其他用途,违者必究。
    文章对你有所帮助的话,欢迎给个赞或者 star 呀,你的支持是对作者最大的鼓励,不足之处可以在评论区多多指正,交流学习呀。

    展开全文
  • 使用VC编写的基于分水岭算法的图像分割程序代码。
  • 1 基于分水岭算法的图像分割及目标计数 1.1 简介 在计算机视觉领域,图像分割(Segmentation)指的是将数字图像细分为多个图像子区域(像素的集合)(也被称作超像素)的过程。图像分割的目的是简化或改变图像的表示...

    1 基于分水岭算法的图像分割及目标计数

    1.1 简介

    计算机视觉领域,图像分割(Segmentation)指的是将数字图像细分为多个图像子区域(像素的集合)(也被称作超像素)的过程。图像分割的目的是简化或改变图像的表示形式,使得图像更容易理解和分析。图像分割通常用于定位图像中的物体和边界线曲线等)。更精确的,图像分割是对图像中的每个像素标签的一个过程,这一过程使得具有相同标签的像素具有某种共同视觉特性。

    1.2 原理及其主要公式

    1.2.1 分水岭算法基本原理

    分水岭分割是基于自然的启发算法来模拟水流通过地形起伏的现象从而研究总结出来的一种分割方法,其基本原理是将图像特征看作地理上的地貌特征,利用像素的灰度值分布特征,对每个符合特征的区域进行划分,形成边界以构成分水岭。

    水位不断上升,汇水盆地之间及其与背景之间的坝也越来越长。构筑水坝的目的是阻止盆地之间及其与背景之间的水汇聚。该过程一直持续,直到到达水的最高水位。最终水坝就是我们希望的分割结果。它的一条重要性质就是水坝组成一条连通的路径,这样,在两个区域之间就给出了连续的边界。

    因为灰度变化较小的区域有较小的梯度值,因此,分水岭分割通常用于一幅图像的梯度,而不是图像本身。这样,汇水盆地的区域最小值就能很好地与待分割区域的较小梯度值联系起来。

    图1-1 原图及图像

    在上面的水岭算法示意图中局部极小值、积水盆地,分水岭线以及水坝的概念可以描述为:

    (1)区域极小值:导数为0的点,局部范围内的最小值点;

    (2)集水盆(汇水盆地):当“水”落到汇水盆地时,“水”会自然而然地流到汇水盆地中的区域极小值点处。每一个汇水盆地中有且仅有一个区域极小值点;

    (3)分水岭:当“水”处于分水岭的位置时,会等概率地流向多个与它相邻的汇水盆地中;

    (4)水坝:人为修建的分水岭,防止相邻汇水盆地之间的“水”互相交汇影响

    分水岭计算方法被分为两个步骤,分别是排序过程和淹没过程。计算时,首先要按照从低到高的排序方式对区域内的每个像素进行灰度级别的排序,然后在从低到高进行淹没,并对每个区域极小值在 H 阶高度的影响域采用先进先出的结构进行标注和判断。通过分水岭的变换所得到输入图像为集水盆图像,每个集水盆之间的边界就是分水岭,而分水岭则代表极大值,所以想要获取图像的信息,需要将梯度图像作为输入图像进行计算,计算公式如下:

    (式1.1)

    在该计算公式中 f(x,y) 则代表原始图像,grad{.} 则代表梯度运算。

    1.2.2 目标计数基本原理

    本文使用的目标计数原理是基于Matlab中的bwboundaries函数实现的。bwboundaries是一个函数,可以用来获取二值图中对象的轮廓,包括外部轮廓与内部边缘。

    [B,L,N]=bwboundaries(show_img,‘noholes’);

    使用上面的语句来获取图像连通区域并求取其轮廓。其中N为物体目标的个数。在使用该函数之前,首先要对原图像进行中值滤波操作去除图像中的噪声;然后进行二值化操作,来将目标物体提取出来;之后再针对目标物体有交叉重叠部分的图像,采用分水岭算法来进行图像分割;最后使用bwboundaries函数,来通过计算目标物体的连通域个数,最终计算出目标物体的数目。

    在实验的过程中,通过计算每个目标的连通域的中心位置,还对每个目标进行了标号,来标记每个物体的位置。实验效果图见图1-2。

    1.3 实验结果

    通过运行分水岭图像分割方法,对三张图片进行了图像分割与物体计数。得到的结果图下图1-1到图1-6所示。其中图1-1的a图为原始图像,图1-1的b图为进行图像分割后的图像;计算得到的三个物体数目分别是48个、10个以及97个。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JsGs9i3j-1588509402663)(https://s1.ax1x.com/2020/04/03/GaH60A.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rwvy4MZp-1588509402665)(https://s1.ax1x.com/2020/04/03/GabG38.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hNoZFzG8-1588509402667)(https://s1.ax1x.com/2020/04/03/GaHymd.png)]

    详细代码及文件下载地址:

    链接: https://www.lanzous.com/ib739mh

    展开全文
  • Python+OpenCV:基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm) #################################################################################################### # 基于分水岭...

    Python+OpenCV:基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm)

    ####################################################################################################
    # 基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm)
    def lmc_cv_image_segmentation_watershed():
        """
            函数功能: 基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm)。
        """
    
        # 读取图像
        image = lmc_cv.imread('D:/99-Research/Python/Image/water_coins.jpg', flags=lmc_cv.IMREAD_UNCHANGED)
        rgb_image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2RGB)
        rgb_image_result = rgb_image.copy()
        gray_image = lmc_cv.cvtColor(rgb_image, lmc_cv.COLOR_RGB2GRAY)
    
        # 基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm)
        ret, thresh_image = lmc_cv.threshold(gray_image, 0, 255, lmc_cv.THRESH_BINARY_INV + lmc_cv.THRESH_OTSU)
    
        # noise removal
        kernel = np.ones((3, 3), np.uint8)
        opening_image = lmc_cv.morphologyEx(thresh_image, lmc_cv.MORPH_OPEN, kernel, iterations=2)
        # sure background area
        sure_bg_image = lmc_cv.dilate(opening_image, kernel, iterations=3)
        # Finding sure foreground area
        dist_transform = lmc_cv.distanceTransform(opening_image, lmc_cv.DIST_L2, 5)
        ret, sure_fg_image = lmc_cv.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
        # Finding unknown region
        sure_fg_image = np.uint8(sure_fg_image)
        unknown = lmc_cv.subtract(sure_bg_image, sure_fg_image)
    
        # Marker labelling
        ret, markers_image = lmc_cv.connectedComponents(sure_fg_image)
        # Add one to all labels so that sure background is not 0, but 1
        markers_image = markers_image + 1
        # Now, mark the region of unknown with zero
        markers_image[unknown == 255] = 0
    
        markers_image = lmc_cv.watershed(rgb_image_result, markers_image)
        rgb_image_result[markers_image == -1] = [255, 0, 0]
    
        # 显示图像
        pyplot.figure('Image Display')
        titles = ['Original Image', 'Thresh Image', 'ForeGround Image', 'BackGround Image', 'Distance Transform Image',
                  'Markers Image', 'Result Image']
        images = [rgb_image, thresh_image, sure_fg_image, sure_bg_image, dist_transform, markers_image, rgb_image_result]
        for i in range(7):
            pyplot.subplot(2, 4, i + 1)
            pyplot.imshow(images[i], 'gray')
            pyplot.title(titles[i])
            pyplot.xticks([])
            pyplot.yticks([])
        pyplot.show()
    
        # 根据用户输入保存图像
        if ord("q") == (lmc_cv.waitKey(0) & 0xFF):
            # 销毁窗口
            pyplot.close('all')
        return

     

    展开全文
  • 实例7:基于分水岭图像分割 #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; Mat watershedCluster(Mat &image, int &numSegments); //

    OpenCV图像分割资料分享:贾志刚的OpenCV图像分割实战视频教程全套资料(包含配套视频、配套PPT的PDF文件、源码和用到的图片素材等)

    实例7:基于分水岭图像分割

    #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("cvtest.png");
    	if (src.empty()) {
    		printf("could not load image...\n");
    		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;
    } 

                                             

    展开全文
  • 利用了分水岭算法的原理及特点, 针对算法所产生的图像分割问题,采用形态学处理函数,以典型的 pears图像为例,用MATLAB 7. 0图像处理软件,进行了仿真研究。结果表明,利用分水岭算法和形态学处理函数,使得图像 中相连...
  • 使用分水岭算法使用基于标记的图像分割 函数:cv.watershed() 理论 任何灰度图像都可以看作是地形表面,其中高强度表示峰和丘陵,而低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)...
  • 为避免这种情况,需要在水合并位置建立障碍,在所有山峰都被水淹没之前,要继续填满水和建造栅栏工作然后你创建障碍会给你分割的结果,这就是分水岭背后“哲学”.可以访问我了解更多相关内容.这种方法会...
  • 为避免这种情况,需要在水合并位置建立障碍,在所有山峰都被水淹没之前,要继续填满水和建造栅栏工作然后你创建障碍会给你分割的结果,这就是分水岭背后“哲学”.可以访问我了解更多相关内容.这种方法会...
  • 任何灰度图像都可以看作是地形表面,其中高强度表示山峰和丘陵,而低强度表示山谷.用不同颜色水(标签)填充每个孤立山谷(局部最小值),随着水上升,明显具有不同颜色水将开始融合.为避免这种情况,需要...
  • 使用分水岭算法进行基于标记的图像分割 cv.watershed()   理论 任何灰度图像都可以看作是地形表面,其中高强度表示山峰和丘陵,而低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷...
  • 为避免这种情况,需要在水合并位置建立障碍,在所有山峰都被水淹没之前,要继续填满水和建造栅栏工作然后你创建障碍会给你分割的结果,这就是分水岭背后“哲学”. 可以访问我了解更多相关内容. 这种方法...
  • matlab基于分水岭算法处理图像分割的源程序,其中有不同方法,是我收集过来效果比较好,有利于大家学习交流
  • Template 基于分水岭技术的图像分割 算法实现 专 业 班 级 : 1220223 班 学 生 姓 名 : 马越 导 师 姓 名 : 谭艳丽 ? 基于分水岭技术的图像分割算法实现 ? 目录 一课题研究目的意义 二 . 课题研究现状及分析 三 . ...
  • 图像处理中常用的基于分水岭算法的彩色图像分割
  • 提出一种基于分水岭算法的MELK图像分割方法,以解决信息量较小的MELK图像分割问题。综合应用多种技术以避免分水岭算法的过分割问题。首先应用高斯低通滤波器对MELK图像进行增强;采用加权差分算子求取梯度图像;应用...
  • 基于分水岭算法的图像处理,转化为灰度图,将梯度幅值转化为分割函数,
  • 基于分水岭的图像分割算法,将分水岭用于图像分割中,实现了作物病害图像的分割。
  • 用susan算子和分水岭算法图像进行分割的一种方法
  • 一、图像分割的定义根据灰度、颜色、纹理和形状等特征,把图像分成若干个特定、具有独特性质区域,这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显差异性,并提出感兴趣目标技术和过程。...
  • 提出一种新的基于分水岭算法和图论的图像分割方法FWTN(First Watershed Then Normalized cut),以克服传统的分水岭算法造成的图像过度分割。FWIN方法在分水岭算法之后,用Normalized Cut方法在区域之间进行分割,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 411
精华内容 164
关键字:

基于分水岭算法的图像分割