分水岭分割后在细胞周围绘制圆圈 - openCV/Python

问题描述

我遵循了一个关于分水岭分割的教程,并用它来分割图像中的每个红细胞。我是 openCV 的新手,我想知道是否可以使用分水岭分割在单元格周围绘制圆圈?如果是这样,请您展示一下它是如何完成的。

原图

original image

流域分割的输出

Watershed output

代码如下

import numpy as np
import cv2
from matplotlib import pyplot as plt


def fillHoles(otsuImg):
    # find contours
    contours,_ = cv2.findContours(otsuImg,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    # filter out contours by size
    small_cntrs = []
    for con in contours:
        area = cv2.contourArea(con)
        # print(area)
        if area < 1000: # size threshold
            small_cntrs.append(con)
    cv2.drawContours(otsuImg,small_cntrs,-1,-1)

# load the image
img = cv2.imread('resources/rbc2.png')
img_pyr = cv2.pyrMeanShiftFiltering(img,21,51)
img_median = cv2.medianBlur(img_pyr,9)
img_gray = cv2.cvtColor(img_median,cv2.COLOR_BGR2GRAY)
ret,img_thresh = cv2.threshold(img_gray,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# fill holes of RBC
fillHoles(img_thresh)

# invert the image
img_thresh = cv2.bitwise_not(img_thresh)

# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(img_thresh,cv2.MORPH_OPEN,kernel,iterations=2)

# sure background area
sure_bg = cv2.dilate(opening,iterations=3)

# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret,sure_fg = cv2.threshold(dist_transform,0.1*dist_transform.max(),0)
# _,sure_fg = cv2.threshold(np.uint8(dist_transform),cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 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]


cv2.imshow('markers2',np.uint8(markers))
cv2.imshow('Final output',img)
cv2.waitKey(0)

解决方法

我遇到了同样的问题,最后在最后一步使用了 skimage.segmentation.watershed,以获得可用于计算分水岭单元轮廓的标签。获得轮廓后,您可以照常计算和绘制封闭圆:

# your code above
ret,markers = cv2.connectedComponents(sure_fg)
from skimage.segmentation import watershed
labels = watershed(-dist_transform,markers,mask=img_thresh,watershed_line=False)
watershed_contours =  list(map(lambda l: cv2.findContours((cv_labels == l).astype(np.uint8),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0][0],np.unique(labels)[1:]))
output = img.copy()
for contour in watershed_contours:
    (x,y),radius = cv.minEnclosingCircle(watershed_contours)
    center = (int(x),int(y))
    radius = int(radius)
    cv2.circle(output,center,radius,(0,255,0),2)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...