分水岭算法
一种图像区域的分割法,在分割的过程中,他会把临近的像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近(求梯度)的像素点互相连接起来构成一个封闭的轮廓。
想了解具体的细节请参考
特别详细,很容易理解
但是在代码上会有一些差异
在这里还需要了解图像的腐蚀与膨胀
在这里我只会说他们的意义以及作用,具体的细节请查看(以实际运用为主)
特别容易理解
图像的腐蚀
作用:极大的消除图像中的白噪点,会减少图像中的前景区域
cv.erode(img, kernel, iterations)
{
img 为图像
kernel 为卷积核
iterations为迭代次数(默认值为1)
}
import cv2 as cvwater = cv.imread("img3.jpg")kernel = np.ones((5,5), np.uint8)erodtion = cv.erode(water, kernel, iterations)cv.imshow('erode',erodtion)cv.imshow('source',water)cv.waitKey(0)cv.destroyAllWindows()
让我们看看效果
图像膨胀
效果与图像腐蚀相对,他是去掉图像中的小黑点,扩大前景区域
import cv2 as cvkernel = np.ones((5,5), np.uint8)dilation = cv.dilate(water, kernel, iterations=1)cv.imshow('dilate',dilation)cv.imshow('source',water)cv.waitKey(0)cv.destroyAllWindows()
操作是类似的
接下来我们就用这些实现一下分水岭算法,其中包含一个重要的函数,cv.watershed()
water = cv.imread('D:\QQPCmgr\Desktop\opencv-4.1.0\samples\data\pic1.png')gray = cv.cvtColor(water, cv.COLOR_BGR2GRAY)ret, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)#将图像转变为二值图kernel = np.ones((3, 3), np.uint8)opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel,iterations=2)#采用腐蚀膨胀操作去掉图中的一些噪点sure_bg = cv.dilate(opening, kernel, iterations=3)#通过膨胀操作获取到图中的背景区域distance = cv.distanceTransform(opening, cv.DIST_L2, 5)ret, sure_fg = cv.threshold(distance, 0.1 * distance.max(), 255, 0)#获取图像的前景区域sure_fg = np.uint8(sure_fg)unknown = cv.subtract(sure_bg, sure_fg)#确定图像中前景与背景重合的区域ret, markers = cv.connectedComponents(sure_fg)#增加围栏markers = markers + 1#在背景区域加1,让unknown区域变成0markers[unknown == 255] = 0markers = cv.watershed(water, markers)#以下就是绘制区域water[markers == -1] = [0, 255, 255]plt.imshow(water)plt.show()