python - 打开 CV 分水岭没有正确分割椭圆对象
问题描述
尝试创建一种方法来处理图像以计算不同类型的平板电脑。以下代码对圆形对象运行良好,但是椭圆形会产生我无法找到解决方法的问题。
kernel = np.ones((5,5),np.uint8)
image = cv2.imread('sample.jpg')
shifted = cv2.GaussianBlur(image, (15, 15), 1)
shifted = cv2.pyrMeanShiftFiltering(shifted, 21, 51)
shifted = cv2.erode(shifted,kernel,iterations=1)
shifted = cv2.dilate(shifted,kernel,iterations=1)
cv2.imwrite("step1.jpg", shifted)
gray = cv2.cvtColor(shifted, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imwrite("step2.jpg", thresh)
thresh = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
cv2.imwrite("step3.jpg", thresh)
thresh = cv2.bitwise_not(thresh)
thresh = cv2.erode(thresh,kernel,iterations=1)
cv2.imwrite("step4.jpg", thresh)
D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=10,
labels=thresh)
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))
for label in np.unique(labels):
if label == 0:
continue
mask = np.zeros(gray.shape, dtype="uint8")
mask[labels == label] = 255
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)
((x, y), r) = cv2.minEnclosingCircle(c)
cv2.circle(image, (int(x), int(y)), int(r), (0, 255, 0), 2)
cv2.putText(image, "#{}".format(label), (int(x) - 10, int(y)),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
cv2.imwrite("step5.jpg", image)
cv2.waitKey(0)
正在使用的图像是:
过滤后的输出:
任何有关如何解决此问题的教学点将不胜感激。
解决方案
我认为有更好的方法来使用分水岭运算符。
它依赖于良好的渐变,但如果图像与这张相似,您应该能够有效地做到这一点。此外,今天有非常强大的边缘检测器,比我在这个演示中使用的要好得多。
import cv2
import numpy as np
import higra as hg
from skimage.segmentation import relabel_sequential
import matplotlib.pyplot as plt
def main():
img_path = "pills.jpg"
img = cv2.imread(img_path)
img = cv2.resize(img, (256, 256))
img = cv2.GaussianBlur(img, (9, 9), 0)
edges = cv2.Canny(img, 100, 100)
size = img.shape[:2]
graph = hg.get_4_adjacency_graph(size)
edge_weights = hg.weight_graph(graph, edges, hg.WeightFunction.mean)
tree, altitudes = hg.watershed_hierarchy_by_area(graph, edge_weights)
segments = hg.labelisation_horizontal_cut_from_threshold(tree, altitudes, 500)
segments, _, _ = relabel_sequential(segments)
print('The number of pills is ', segments.max() - 1)
plt.imshow(segments)
plt.show()
if __name__ == "__main__":
main()
最初,我调整图像大小以加快计算速度并应用模糊来减少背景渐变。我检测它的边缘(梯度)并用它作为边缘权重创建一个图;然后我计算按区域排序的分水岭层次结构并阈值它获得该级别的连接组件,从中您可以计算段数。
推荐阅读
- php - ReadImage() 不工作 PHP 和 ImageMagick
- swiftui - 如何在swiftui中使用completionHandler响应?
- python - 根据其他字典键对 Python 中的字典进行排序
- javascript - JS - 检查对象是否包含在另一个对象中
- html - 设置宽度和高度以改进 CLS 会导致纵横比问题
- curl - 在centos服务器中执行未知的curl命令
- r - 在自定义 R 函数中使用时间序列模型
- linux - 如何在 Yocto 中更改文件所有权
- python - 使用相机重置背景滚动未正确重置
- javascript - 如何正确打开 JQuery AJAX Success 的新窗口?