摘要:理论任何灰度图像都可以看作是地形表面,其中高强度表示山峰和丘陵,而低强度表示山谷用不同颜色的水标签填充每个孤立的山谷局部最小值,随着水的上升,明显具有不同的颜色的水将开始融合为避免这种情况,需要在水合并的位置建立障碍,在所有的山峰都被水淹没
Image Segmentation with Watershed Algorithm
理论任何灰度图像都可以看作是地形表面,其中高强度表示山峰和丘陵,而低强度表示山谷.用不同颜色的水(标签)填充每个孤立的山谷(局部最小值),随着水的上升,明显具有不同的颜色的水将开始融合.为避免这种情况,需要在水合并的位置建立障碍,在所有的山峰都被水淹没之前,要继续填满水和建造栅栏的工作然后你创建的障碍会给你分割的结果,这就是分水岭背后的“哲学”.
可以访问我了解更多相关内容.
这种方法会导致由于噪声或图像中任何其他不正常的情况而导致的结果过于分散, 因此,OpenCV实现了一个基于标记的分水岭算法,可以在其中指定要合并的和不合并的谷点.这是一个交互式的图像分割,我们所做的就是给我们所知道的对象提供不同的标签,用一种颜色(或强度)标记我们确定为前景或对象的区域,用另一种颜色标记我们确定为背景或非对象的区域,最后标记我们不确定的区域为0,然后应用分水岭算法,我们的标记将会随着我们所给出的标签进行更新,对象的边界将值为-1.
应用我们将看到一个关于如何使用距离变换和分水岭来分割相互触摸的物体的例子.
考虑下面的硬币图像,硬币相互接触.即使把它阈值,它也会互相接触.
我们使用Otsu的二值化找到硬币的近似估计值.
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread("img4.jpg") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) cv2.imshow("show",thresh) cv2.waitKey(0) cv2.destroyAllWindows()
现在我们需要去除图像中的任何小的白噪声,因此我们要使用形态学开运算,为了去除物体上的小洞,我们要使用形态学闭运算,所以,现在我们可以确定,靠近物体中心的区域是前景,远离物体的区域是背景,只有硬币的边界区域是我们不确定的区域.
我们需要提取出我们确信它们是硬币的区域,腐蚀边界像素,不管剩下的是什么,我们都可以确定它是硬币.如果它们不相互接触还可以继续,如果它们相互接触,另一个好的选择是找到距离变换并应用一个合适的阈值.
为此,我们对结果进行了扩张,扩张将对象边界增加为背景,通过这种方法,我们可以确保背景中的任何区域都是真正的背景,因为边界区域被移除.
剩下的区域是我们不知道的区域,无论是硬币还是背景.分水岭算法应该找到它, 这些区域通常围绕着前景和背景相遇的硬币边界(甚至两个不同的硬币相遇),它可以从sure_bg区域中减去sure_fg区域获得.
# noise removal kernel = np.ones((3,3),np.uint8) opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) # sure background area sure_bg = cv2.dilate(opening,kernel,iterations=3) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening,cv.DIST_L2,5) ret, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(),255,0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg,sure_fg)
现在我们可以确定哪些是硬币的区域,哪些是背景,哪些是背景.因此,我们创建标记(它是一个与原始图像相同大小的数组,但使用int32数据类型)并对其内部的区域进行标记.
cv2.connectedComponents()
将图像的背景标记为0,然后其他对象从1开始标记为整数.
我们知道,如果背景是0,那么分水岭将会被认为是未知的区域, 所以我们用不同的整数来标记它,用0表示由未知定义的未知区域.
# Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # 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[unknown==255] = 0
深蓝色区域显示未知区域,硬币的颜色是不同的,与未知区域相比,确定背景的剩余区域以较浅的蓝色显示.
标记已经准备好了,现在是最后一步的时候了,应用分水岭.
markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0]
代码:
import numpy as np import cv2 from matplotlib import pyplot as plt img = cv2.imread("img4.jpg") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) # noise removal kernel = np.ones((3,3),np.uint8) opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) # 形态开运算 # sure background area sure_bg = cv2.dilate(opening,kernel,iterations=3) # Finding sure foreground area dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5) ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) # Finding unknown region sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg,sure_fg) # Marker labelling ret, markers = cv2.connectedComponents(sure_fg) # 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[unknown==255] = 0 markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] cv2.imshow("img",img) cv2.waitKey(0) cv2.destroyAllWindows()
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/42053.html
摘要:十开放模式识别项目开放模式识别项目,致力于开发出一套包含图像处理计算机视觉自然语言处理模式识别机器学习和相关领域算法的函数库。 一、开源生物特征识别库 OpenBROpenBR 是一个用来从照片中识别人脸的工具。还支持推算性别与年龄。使用方法:$ br -algorithm FaceRecognition -compare me.jpg you.jpg二、计算机视觉库 OpenCVOpenC...
摘要:之成为图像处理任务的最佳选择,是因为这一科学编程语言日益普及,并且其自身免费提供许多最先进的图像处理工具。该库包含基本的图像处理功能,包括点操作使用一组内置卷积内核进行过滤以及颜色空间转换。图像处理系统有时被称为图像处理的瑞士军刀。 showImg(https://segmentfault.com/img/remote/1460000019442221);编译:张秋玥、小七、蒋宝尚 本...
阅读 2561·2019-08-30 10:53
阅读 3158·2019-08-29 16:20
阅读 2915·2019-08-29 15:35
阅读 1724·2019-08-29 12:24
阅读 2846·2019-08-28 18:19
阅读 1822·2019-08-23 18:07
阅读 2262·2019-08-23 15:31
阅读 1125·2019-08-23 14:05