问题描述
我正在尝试找出图像中三角形的方向。下图是:
这些三角形指向上/下/左/右。这不是实际图像。我已经使用了canny边缘检测来找到边缘,然后是轮廓,然后膨胀的图像如下所示。
我找方向的逻辑:
我想使用的逻辑是,在三个角坐标中,如果我能确定三角形的基坐标(具有相同的横坐标或纵坐标值坐标),我就可以制作一个基向量。然后可以使用单位向量和基向量之间的角度来识别方向。但是这种方法只能判断是上/下还是左/右,而不能区分上下或左右。我尝试使用 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 表示三角形向上或向下。
,假设你只有四种情况:[上、下、左、右],这段代码应该很适合你。
想法很简单:
- 获取轮廓的边界矩形。使用:
box = cv2.boundingRect(contour_pnts)
- 使用边界矩形裁剪图像。
- 使用
Sum
选项垂直和水平缩小图像。现在您有了沿每个轴的像素总和。总和最大的轴决定三角形底是垂直还是水平。 - 判断三角形是指向左/右还是上/下:需要检查边界矩形中心是在最大列/行之前还是之后:
代码(假设您从裁剪后的图像开始):
ver_reduce = cv2.reduce(img,cv2.REDUCE_SUM,None,cv2.CV_32F)
hor_reduce = cv2.reduce(img,1,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')
照片: