代码
## opencv python 基于分水岭算法的图像分割 # 这种方法可能会导致由于噪声或图像中任何其他不正常的情况而导致的结果过于分散 import cv2 import numpy as np from matplotlib import pyplot as plt #读取图片 img = cv2.imread('20210212_78947.jpg') # 灰度图片 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 返回ret '通过INV+OTSU 找到最合适的阈值 thresh返回处理后的图片 ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) cv2.imshow('img1',thresh) # noise removal # 开运算(opening) 等于对图像先进行腐蚀(erode) 然后进行膨胀(dilate). # 通常用于去除小粒噪声 # Python np.ones()函数返回给定形状和数据类型的新数组,其中元素的值设置为1 kernel = np.ones((3,3),np.uint8) print('kernel',kernel) # 形态开运算 # openvc中morphologyEx()函数是一种形态学变化函数。 # 数学形态学可以理解为一种滤波行为,因此也称为形态学滤波。 # 滤波中用到的滤波器(kernal),在形态学中称为结构元素。 # 结构元素往往是由一个特殊的形状构成,如线条、矩形、圆等。 # cv2.morphologyEx(img,op,kernel) # img 经过阈值处理后的数据 # op:cv2.MORPH_OPEN 开运算(open) ,先腐蚀后膨胀的过程。开运算可以用来消除小黑点,在纤细点处分离物体、平滑较大物体的边界的 同时并不明显改变其面积。 # cv2.MORPH_CLOSE 闭运算(close),先膨胀后腐蚀的过程。闭运算可以用来排除小黑洞。 # cv2.MORPH_GRADIENT 形态学梯度(morph-grad),可以突出团块(blob)的边缘,保留物体的边缘轮廓。 # cv2.MORPH_TOPHAT 顶帽(top-hat),将突出比原轮廓亮的部分。 # cv2.MORPH_BLACKHAT 黑帽(black-hat),将突出比原轮廓暗的部分。 opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) # 先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。 sure_bg = cv2.dilate(opening,kernel,iterations=3) # 距离变换函数 cv2.distanceTransform()计算二值图像内任意点到最近背景点的距离。 # cv2.DIST_L2: 欧式距离,此时与最小二乘法相同 # 主要用于计算非零像素到最近零像素点的距离,一般用于求解图像的骨骼,得到的是距离图像数组。 # src:输入的图像,一般为二值图像 # distanceType:所用的求解距离的类型(CV_DIST_L1, CV_DIST_L2 , CV_DIST_C) # maskSize:距离变换掩模的大小 #--------------------- # 下面例子实现的功能就是提取出里面颜色最白的部分 dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5) print('dist_transform',dist_transform) # 70%-100% 的大值变为 白色,255 # 0% - 70% 的小值变为 黑色,0 ret, sure_fg = cv2.threshold(dist_transform,0,255,0) # 存储的数据格式必须为np.uint8,否则之后是显示不出来的 sure_fg = np.uint8(sure_fg) # 减法-寻找不确定区域 unknown = cv2.subtract(sure_bg,sure_fg) cv2.imshow('img6',unknown) #----------------------------------- #该函数用以计算二值图像的连通域标记图像 #不过数据类型会变成int32,他会把图像背景标记为0,其他目标用从1开始标记; # 但是如果光只是这么做的话,分水岭算法会将标为0的位置认为是unknown,所以我们对里面所有的像素的值加一,这样原本为0的位置上的像素的值就是1了。 # 之后我们设置栅栏来阻止水汇聚,我们把图像堪称有连接边的节点集,给定确定的前景区,其中一些节点会连在一起,而另一些没连在一起的,这意味着他们来自不同的山谷, # 所以他们之间需要设置一个栅栏: ret, markers = cv2.connectedComponents(sure_fg) markers = markers+1 # 这里将所有未知区域的像素设置为0 markers[unknown==255] = 0 # 打开门,让水漫起来 markers = cv2.watershed(img,markers) # 将原图中的栅栏位置的颜色设置为蓝色并进行显示 img[markers == -1] = [255,0,0] cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() # 需要去除图像中的任何小的白噪声,因此我们要使用形态学开运算 # 为了去除物体上的小洞 我们要使用形态学闭运算 # 靠近物体中心的区域是前景,远离物体的区域是背景, # 只有硬币的边界区域是我们不确定的区域.