【问题标题】:How to find the principal axis of a blob which goes through the centroid of the blob?如何找到穿过斑点质心的斑点的主轴?
【发布时间】:2021-04-24 15:41:14
【问题描述】:

我想找到通过 blob 质心的 blob 的主轴。我能够找到 blob 的质心,但是如何找到主轴?

这是我尝试过的:

import cv2
import numpy as np

img = cv2.imread('skin6.jpg')

imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh2 = cv2.threshold(imgray, 155, 255, cv2.THRESH_BINARY_INV)

#find the maximum contour
contours, heir = cv2.findContours(thresh2, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)

tmpArea = np.zeros(img.shape)
cv2.drawContours(tmpArea,[c],0,(255, 255, 255),cv2.FILLED)

#centroid
M = cv2.moments(c)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

cv2.circle(tmpArea, (cx, cy), 5, (0, 0, 255), -1)

cv2.imshow("tmpArea", tmpArea)
cv2.waitKey(0)

这些是我使用的图像:

我期待这样的事情。它应该与轮廓正确连接: Expected

【问题讨论】:

    标签: python opencv blob axis centroid


    【解决方案1】:

    您可以在检测到的轮廓上使用cv2.fitEllipseThere's an OpenCV tutorial on that topic. 你得到拟合椭圆的中心、两个轴的长度(请详细查看cv2.ellipse)和旋转角度。根据这些信息,让主轴穿过中心只是一些数学运算。

    这是您的代码,经过一些修改和添加:

    import cv2
    import numpy as np
    
    # Images
    img = cv2.imread('images/1KXQA.jpg')
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    thresh2 = cv2.threshold(img_gray, 155, 255, cv2.THRESH_BINARY_INV)[1]
    tmpArea = np.zeros(img.shape)
    
    # Contours
    contours = cv2.findContours(thresh2, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[0]
    c = max(contours, key=cv2.contourArea)
    cv2.drawContours(tmpArea,[c],0,(255, 255, 255),cv2.FILLED)
    
    # Centroid
    M = cv2.moments(c)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    cv2.circle(tmpArea, (cx, cy), 5, (0, 0, 255), -1)
    
    # Ellipse
    e = cv2.fitEllipse(c)
    cv2.ellipse(tmpArea, e, (0, 255, 0), 2)
    
    # Principal axis
    x1 = int(np.round(cx + e[1][1] / 2 * np.cos((e[2] + 90) * np.pi / 180.0)))
    y1 = int(np.round(cy + e[1][1] / 2 * np.sin((e[2] + 90) * np.pi / 180.0)))
    x2 = int(np.round(cx + e[1][1] / 2 * np.cos((e[2] - 90) * np.pi / 180.0)))
    y2 = int(np.round(cy + e[1][1] / 2 * np.sin((e[2] - 90) * np.pi / 180.0)))
    cv2.line(tmpArea, (x1, y1), (x2, y2), (255, 255, 0), 2)
    
    # Output
    cv2.imshow('tmpArea', tmpArea)
    cv2.waitKey(0)
    

    输出如下:

    ----------------------------------------
    System information
    ----------------------------------------
    Platform:      Windows-10-10.0.16299-SP0
    Python:        3.8.5
    NumPy:         1.19.5
    OpenCV:        4.5.1
    ----------------------------------------
    

    【讨论】:

    • 感谢您的回答,但我的数据集中存在不对称的皮肤损伤,因此不适用于这些图像。有没有其他方法可以获得主轴? @HansHirse
    • @NaduniJayaweera 然后请在您的问题中添加其他图像,显示所需的主轴,可能是手动绘制的。对于第二张新提供的图片,我不确定您想要的最终结果是什么。
    • 添加了预期的输出@HansHirse
    • @NaduniJayaweera 不幸的是,该图像本身并不是很有帮助,因为没有描述,主轴实际上是什么。是的,它是带有角度theta的蓝线,但是定义是什么,那条蓝线是如何获得的?而且,您的示例中对应的蓝线是什么?请将它们画到您的图像中,并为主轴提供适当的描述。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多