如何在opencv中使用分水岭分割python
How to use watershed segmentation in opencv python
我有一个问题,如何使用 python 中的分水岭分割在此图像中单独分割粒子。我的主要目标是通过应用过滤器 medianBlur 然后应用 Canny 边缘检测方法来消除噪声。
[![img = cv2.imread('sands.jpg')
img = cv2.medianBlur(img,7)
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imo = cv2.Canny(img,140,255)][1]][1]
我想增强 Canny 边缘检测功能产生的轮廓,因为我使用此图像检测图像内粒子的区域特性以估计面积。
这是一种改编自此 blog post
的方法
- 将图像转换为灰度
- 大津获取二值图像的阈值
- 计算欧氏距离变换
- 执行连通分量分析
- 应用分水岭
- 遍历标签值并提取对象
这是结果
在遍历每个等高线的同时,可以累加总面积
1388903.5
import cv2
import numpy as np
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from scipy import ndimage
# Load in image, convert to gray scale, and Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Compute Euclidean distance from every binary pixel
# to the nearest zero pixel then find peaks
distance_map = ndimage.distance_transform_edt(thresh)
local_max = peak_local_max(distance_map, indices=False, min_distance=20, labels=thresh)
# Perform connected component analysis then apply Watershed
markers = ndimage.label(local_max, structure=np.ones((3, 3)))[0]
labels = watershed(-distance_map, markers, mask=thresh)
# Iterate through unique labels
total_area = 0
for label in np.unique(labels):
if label == 0:
continue
# Create a mask
mask = np.zeros(gray.shape, dtype="uint8")
mask[labels == label] = 255
# Find contours and determine contour area
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
c = max(cnts, key=cv2.contourArea)
area = cv2.contourArea(c)
total_area += area
cv2.drawContours(image, [c], -1, (36,255,12), 4)
print(total_area)
cv2.imshow('image', image)
cv2.waitKey()
我有一个问题,如何使用 python 中的分水岭分割在此图像中单独分割粒子。我的主要目标是通过应用过滤器 medianBlur 然后应用 Canny 边缘检测方法来消除噪声。
[![img = cv2.imread('sands.jpg')
img = cv2.medianBlur(img,7)
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imo = cv2.Canny(img,140,255)][1]][1]
我想增强 Canny 边缘检测功能产生的轮廓,因为我使用此图像检测图像内粒子的区域特性以估计面积。
这是一种改编自此 blog post
的方法- 将图像转换为灰度
- 大津获取二值图像的阈值
- 计算欧氏距离变换
- 执行连通分量分析
- 应用分水岭
- 遍历标签值并提取对象
这是结果
在遍历每个等高线的同时,可以累加总面积
1388903.5
import cv2
import numpy as np
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from scipy import ndimage
# Load in image, convert to gray scale, and Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Compute Euclidean distance from every binary pixel
# to the nearest zero pixel then find peaks
distance_map = ndimage.distance_transform_edt(thresh)
local_max = peak_local_max(distance_map, indices=False, min_distance=20, labels=thresh)
# Perform connected component analysis then apply Watershed
markers = ndimage.label(local_max, structure=np.ones((3, 3)))[0]
labels = watershed(-distance_map, markers, mask=thresh)
# Iterate through unique labels
total_area = 0
for label in np.unique(labels):
if label == 0:
continue
# Create a mask
mask = np.zeros(gray.shape, dtype="uint8")
mask[labels == label] = 255
# Find contours and determine contour area
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
c = max(cnts, key=cv2.contourArea)
area = cv2.contourArea(c)
total_area += area
cv2.drawContours(image, [c], -1, (36,255,12), 4)
print(total_area)
cv2.imshow('image', image)
cv2.waitKey()