gpt4 book ai didi

python-3.x - 用opencv查找手写箭头的特征

转载 作者:行者123 更新时间:2023-12-02 16:07:09 24 4
gpt4 key购买 nike

我正在尝试检索手写箭头的方向:
去除阴影并应用二值化和扩张线条后,以下是图像:

enter image description here
enter image description here
enter image description here

现在我想知道箭头的方向,所以我尝试使用 HoughLines,

lines = cv2.HoughLines(edges, rho=1, theta=np.pi / 180, threshold=20) 

但是似乎它生成了太多行(大约 54 行),我希望它只生成 3 行,这样我就可以找到这些行的交点。我可以将线条分组为相似角度(+/- 20 度)的组,然后平均角度。但我不确定应该是什么 rho 平均线,有人可以举一个简单的例子吗?

还有其他更准确的方法吗?

我很高兴听到,谢谢大家

最佳答案

我建议采用不同的方法。总之,方法如下(匆忙完成,可能需要一些调整):

  • 找到包围整个箭头的最小面积矩形(旋转矩形)的中心。 (第三张图中画的圆圈)
  • 找到所有白点的重心。它将向箭头的实际头部移动一点。 (在第四张图片中作为特征向量的原点绘制)
  • 找到所有白点的特征向量。
  • 找到位移向量(重心 - 旋转矩形的中心)

  • 现在:
  • 箭头角度(无方向):是第一个特征向量的角度
  • 箭头方向:是(第一个特征向量和中心位移向量)的点积的符号

  • 代码:

    与 PCA 相关的部分受 this 的启发并大部分复制自.我只对“getOrientation”方法做了一个小改动,在它返回之前添加了以下几行
    angle = (angle - math.pi) * 180 / math.pi
    return angle, (mean[0,0]), (mean[0,1]), p1

    实现上述逻辑的代码:
    #threshold
    _, img = cv2.threshold(img, 128, 255, cv2.THRESH_OTSU)
    imshow(img)

    #close the image to make sure the contour is connected)
    st_el = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, st_el)
    imshow(img)

    #get white points
    pnts = cv2.findNonZero(img)

    #min area rect
    rect_center = cv2.minAreaRect(pnts)[0]

    #draw rect center
    cv2.circle(img, (int(rect_center[0]), int(rect_center[1])), 3, 128, -1)
    imshow(img)

    angle, pca_center, eigen_vec = getOrientation(pnts, img)

    cc_vec = (rect_center[0] - pca_center[0], rect_center[1] - pca_center[1])
    dot_product = cc_vec[0] * eigen_vec[0] + cc_vec[1] * eigen_vec[1]
    if dot_product > 0:
    angle *= -1

    print ("Angle = ", angle)
    imshow(img)

    编辑

    我建议一个更简单的方法。这种新方法不依赖于 PCA 来找到未定向的角度 [0 - 180]。相反,立即使用最小面积矩形角度。并使用轮廓动量寻找重心。

    更简单的方法代码:
    #get white points
    pnts = cv2.findNonZero(img)

    #min area rect
    rect_center, size, angle = cv2.minAreaRect(pnts)

    #simple fix for angle to make it in [0, 180]
    angle = abs(angle)
    if size[0] < size[1]:
    angle += 90

    #find center of gravity
    M = cv2.moments(img)
    gravity_center = (M["m10"] / M["m00"], M["m01"] / M["m00"])

    #rot rect vec based on angle
    angle_unit_vec = (math.cos(angle * 180 / math.pi), math.sin(angle * 180 / math.pi))

    #cc_vec = gravity center - rect center
    cc_vec = (gravity_center[0] - rect_center[0], gravity_center[1] - rect_center[1])

    #if dot product is negative add 180 -> angle between [0, 360]
    dot_product = cc_vec[0] * angle_unit_vec[0] + cc_vec[1] * angle_unit_vec[1]
    angle += (dot_product < 0) * 180

    #draw rect center
    cv2.circle(img, (int(rect_center[0]), int(rect_center[1])), 3, 128, -1)
    cv2.circle(img, (int(gravity_center[0]), int(gravity_center[1])), 3, 20, -1)

    imshow(img)
    print ("Angle = ", angle)

    编辑 2:
    此编辑包括以下更改:
  • 使用 cv2.fitLine() 并使用拟合的线角进行方向。
  • 将angle_unit_vec 替换为以重心为原点并平行于拟合线的向量。

  • 代码
    #get white points
    pnts = cv2.findNonZero(img)
    #min area rect
    rect_center, size, angle = cv2.minAreaRect(pnts)

    #fit line to get angle
    [vx, vy, x, y] =cv2.fitLine(pnts, cv2.DIST_L12, 0, 0.01, 0.01)
    angle = (math.atan2(vy, -vx)) * 180 / math.pi

    M = cv2.moments(img)
    gravity_center = (M["m10"] / M["m00"], M["m01"] / M["m00"])

    angle_vec = (int(gravity_center[0] + 100 * vx), int(gravity_center[1] + 100 * vy))

    #cc_vec = gravity center - rect center
    cc_vec = (gravity_center[0] - rect_center[0], gravity_center[1] - rect_center[1])

    #if dot product is positive add 180 -> angle between [0, 360]
    dot_product = cc_vec[0] * angle_vec[0] + cc_vec[1] * angle_vec[1]
    angle += (dot_product > 0) * 180


    angle += (angle < 0) * 360


    #draw rect center
    cv2.circle(img, (int(rect_center[0]), int(rect_center[1])), 3, 128, -1)
    cv2.circle(img, (int(gravity_center[0]), int(gravity_center[1])), 3, 20, -1)

    imshow(img)
    print ("Angle = ", angle)

    输出:
    使用来自 edit2 的代码:

    第一张图:

    enter image description here

    第二张图:

    enter image description here

    第三张图:

    enter image description here

    关于python-3.x - 用opencv查找手写箭头的特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60880769/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com