900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【OpenCV】 - 图像分割之分水岭算法 watershed()函数的输出 对marker和image的改变

【OpenCV】 - 图像分割之分水岭算法 watershed()函数的输出 对marker和image的改变

时间:2020-02-08 02:48:26

相关推荐

【OpenCV】 - 图像分割之分水岭算法 watershed()函数的输出 对marker和image的改变

一、背景

最近在学分水岭算法的opencv函数watershed()时,对函数执行完后image和marker的变化一无所知、懵懵懂懂。

于是便结合网上资料和自己现身说法,给大家分享一下【watershed函数的执行效果】。

OpenCV: Image Segmentation with Watershed Algorithm

OpenCV: Image Segmentation

首先说明一点:

传入watershed函数的marker参数可以有三种成分:背景、不确定、前景(也即object)。

比如背景像素填充1,而object1填充2,不确定像素填充0。

下文的“种子数值”代表Object成分的编号。

因此,object1的种子数值是2。

二、直接给结论

watershed函数一旦执行,就会改变marker,但是image不变。

改变A:从基点开始向外填充种子数值,直到边界。

例如下面的第2个硬币对应的种子数值是2,原marker中只有硬币最中间才是填充了2

函数执行后,整个硬币所处区域全被填充2。

改变B:向外填充时,若即将与另一个山谷的积水相涉就停止扩展,最外围便是边界线,marker中的边界线区域填充-1。

还是以第二个硬币为例,第二个硬币的边界像素点填充-1。

也就是说,最后得到的marker想比原marker是更加完善的;原marker的object像素点只需要至少填充一个种子数值,而新marker是将object的所有像素全部填充种子数值,更加精确和点对点。

三、测试(现身说法)

测试用到的图片

测试用到的代码

import cv2 as cvimport numpy as npfrom matplotlib import pyplot as pltdef watershed_demo():# remove noise if anyprint(src.shape)blurred = cv.pyrMeanShiftFiltering(src, 10, 100)# gray\binary imagegray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)cv.imshow("binary-image", binary)# morphology operationkernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)sure_bg = cv.dilate(mb, kernel, iterations=3)cv.imshow("mor-opt", sure_bg)# distance transformdist = cv.distanceTransform(mb, cv.DIST_L2, 3)dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)cv.imshow("distance-t", dist_output*50)ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)surface_fg = np.uint8(surface)cv.imshow("surface-bin", surface_fg)unknown = cv.subtract(sure_bg, surface_fg)ret, markers = cv.connectedComponents(surface_fg)# watershed transformmarkers = markers + 1markers[unknown == 255] = 0print(type(markers))print(np.sum(markers==2))markers = cv.watershed(src, markers=markers)print(np.unique(markers))print(np.sum(markers==2))src[markers==-1] = [0, 0, 255]cv.imshow("result", src)markers = markers + 1plt.imshow(markers)plt.show()src = cv.imread("D:\BaiduNetdiskDownload\pycv-learning\pythonProject\images\coins.jpg")cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)cv.imshow("input image", src)watershed_demo()cv.waitKey(0)cv.destroyAllWindows()

cv.imshow("surface-bin", surface_fg)的输出如下。

这十个白圆块的区域,对应marker填充种子数值的范围。

cv.imshow("result", src)的输出如下。

硬币的边界上绘制了一个红圈,正是利用了上文第二部分的改变B。

plt.imshow(markers)的输出如下。

我们可以看到新得到的marker真正做到对各个硬币进行像素级别的标注,不同硬币object对应不同填充色。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。