繁体   English   中英

如何使用 OpenCV 在图像中找到三角形的方向

[英]How to find the direction of triangles in an image using OpenCV

我试图在图像中找到三角形的方向。 下面是图片:

在此处输入图像描述

这些三角形指向向上/向下/向左/向右。 这不是实际图像。 我已经使用精明的边缘检测来查找边缘,然后是轮廓,然后放大的图像如下所示。

我找到方向的逻辑:

我想使用的逻辑是在三个角坐标中如果我可以识别三角形的基本坐标(具有相同的横坐标或纵坐标值坐标),我可以制作一个基本向量。 然后可以使用单位向量和基向量之间的角度来识别方向。 但是这种方法只能判断是上/下还是左/右,而不能区分上下或左右。 我尝试使用cv2.goodFeaturesToTrack找到角落,但据我所知,它只给出了整个图像中最有效的 3 个点。 所以我想知道是否有其他方法可以找到三角形的方向。

这是我在 python 中的代码,用于区分三角形/正方形和圆形:

#blue_masking
mask_blue=np.copy(img1)
row,columns=mask_blue.shape
for i in range(0,row):
    for j in range(0,columns):
        if (mask_blue[i][j]==25):
            mask_blue[i][j]=255
        else: 
            mask_blue[i][j]=0
blue_edges = cv2.Canny(mask_blue,10,10)
kernel_blue = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(2,2))
dilated_blue = cv2.dilate(blue_edges, kernel)
blue_contours,hierarchy = 
cv2.findContours(dilated_blue,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for cnt in blue_contours:
    area = cv2.contourArea(cnt)
    perimeter = cv2.arcLength(cnt,True)
    M = cv2.moments(cnt)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    if(12<(perimeter*perimeter)/area<14.8):
        shape="circle"
    elif(14.8<(perimeter*perimeter)/area<18):
        shape="squarer"
    elif(18<(perimeter*perimeter)/area and area>200):
        shape="triangle"
    print(shape) 
    print(area)
    print((perimeter*perimeter)/area,"\n")
    
cv2.imshow('mask_blue',dilated_blue)
cv2.waitKey(0)
cv2.destroyAllWindows()

  

源图像可以在这里找到: img1

请帮忙,我怎样才能找到三角形的方向?
谢谢你。

好吧,Mark 提到了一种可能效率不高但可能更准确的解决方案。 我认为这个应该同样有效,但可能不太准确。 但是由于您已经有一个查找三角形的代码,请在找到三角形轮廓后尝试添加以下代码:

hull = cv2.convexHull(cnt)    # convex hull of contour
hull = cv2.approxPolyDP(hull,0.1*cv2.arcLength(hull,True),True)
# You can double check if the contour is a triangle here
# by something like len(hull) == 3

你应该得到一个三角形的 3 个外壳点,这些应该是你的三角形的 3 个顶点。 鉴于您的三角形始终仅在 4 个方向上“面向”; 对于朝左或朝右的三角形,船体的 Y 坐标将与质心的 Y 坐标接近,它指向左还是右取决于船体 X 是否小于或大于质心 X。类似地使用船体和质心 X Y 表示向上或向下的三角形。

假设你只有四种情况:[上、下、左、右],这段代码应该很适合你。

这个想法很简单:

  1. 获取轮廓的边界矩形。 使用: box = cv2.boundingRect(contour_pnts)
  2. 使用边界矩形裁剪图像。
  3. 使用Sum选项垂直和水平缩小图像。 现在您有了沿每个轴的像素总和。 总和最大的轴决定了三角形底是垂直的还是水平的。
  4. 要确定三角形是指向左/右还是上/下:您需要检查边界矩形中心是在最大列/行之前还是之后:

代码(假设您从裁剪的图像开始):

ver_reduce = cv2.reduce(img,  0, cv2.REDUCE_SUM, None, cv2.CV_32F)
hor_reduce = cv2.reduce(img,  1, cv2.REDUCE_SUM, None, cv2.CV_32F)

#For smoothing the reduced vector, could be removed
ver_reduce = cv2.GaussianBlur(ver_reduce, (3, 1), 0)
hor_reduce = cv2.GaussianBlur(hor_reduce, (1, 3), 0)

_,ver_max, _, ver_col = cv2.minMaxLoc(ver_reduce)
_,hor_max, _, hor_row = cv2.minMaxLoc(hor_reduce)

ver_col = ver_col[0]
hor_row = hor_row[1]

contour_pnts = cv2.findNonZero(img) #in my code I do not have the original contour points

rect_center, size,  angle = cv2.minAreaRect(contour_pnts )

print(rect_center)

if ver_max > hor_max:
    if rect_center[0] > ver_col:
        print ('right')
    else:
        print ('left')
else:
    if rect_center[1] > hor_row:
        print ('down')
    else:
        print ('up')

相片:

向上案例

正确的案例

羽绒服

左壳

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM