如何解决使用Opencv检测梯形和菱形时的公差问题
我应该写一个代码来识别不同的形状,我们得到了一个文件夹,其中提供了不同形状的图像(圆形/三角形/梯形/菱形/正方形/四边形/平行四边形/五边形/六角形)。识别它们后,应以以下格式返回输出:{'Shape':['color',Area,cX,cY]}
我的代码不断使Trapezium和Rhombus混淆。我对其进行了调试,发现这是因为 侧面 和 角度 中的+/- 1公差。我该怎么办?。
以下是我尝试过的一些StackOverflow链接:OpenCV
: How to detect rhombus on an image?
Detecting trapezium,rhombus,square,quadrilateral,parallelogram by Opencv
in Python
OpenCV
shape detection
Tutorial for iPhone OpenCV
on shape recognising [closed]
还有更多,但他们遇到了社区问题,因此我不会在这些问题上浪费您的时间。长话短说,我没有发现任何有用的东西。
import cv2
import numpy as np
img = cv2.imread('Sample3.png',-1)
class ShapeColorRecognition():
shape = 'unidentified'
color = 'undetected'
def __init__(self,img):
global shape,color,cX,cY,area
self.shapeList = []
#Getting Contours
self.img = img
gray = cv2.cvtColor(self.img,cv2.COLOR_BGR2GRAY)
blurred = cv2.blur(gray,(5,5))
ret,thresh = cv2.threshold(blurred,230,255,cv2.THRESH_BINARY)
contours,_ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours[1:]:
#Approximating the contours
approxCont = cv2.approxPolyDP(cnt,0.1*cv2.arcLength(cnt,True),True)
#Calculating the Centroid coordinates of the particular object by moments
M = cv2.moments(cnt)
cX = int(M['m10']/M['m00'])
cY = int(M['m01']/M['m00'])
area = cv2.contourArea(cnt)
#Converting image to the HSV format
hsv = cv2.cvtColor(self.img,cv2.COLOR_BGR2HSV)
#Calling the functions for Shapes and Colors
self.shape(approxCont)
self.color(hsv,cY)
#Final List Containing the shape and the color of the object
self.shapeList.append(tuple([shape,area,cY]))
def shape(self,approx):
"""Getting the name of shape of approximated contour"""
global shape
p1 = approx[0][0]
p2 = approx[1][0]
p3 = approx[-1][0]
p4 = approx[2][0]
if len(approx) == 3:
shape = 'Triangle'
elif len(approx) == 4:
(degrees) = self.get_corner_angle(p1,p2,p3)
(degrees_opp) = self.get_corner_angle_opp(p4,p3)
dist1 = self.distance(p1,p3,p4)
# print(degrees)
if ((89 <= int(degrees) <= 91) and (89 <= int(degrees_opp) <= 91)) and (a == b):
shape = "Square"
elif (a == True or b == True) and (int(degrees) != 90 and int(degrees_opp) != 90):
shape = "Trapezoid"
print(int(degrees_opp))
print(int(degrees))
print(l1)
print(l2)
print(l3)
print(l4)
elif (int(degrees) == int(degrees_opp)) and(a == b):
shape = "Rhombus"
elif (a == True or b == True) and (int(degrees) == int(degrees_opp)):
shape = "Parallelogram"
elif (int(degrees) != int(degrees_opp)) and (a == False and b == False):
shape = "Quadilateral"
print(int(degrees))
print(l1)
print(l2)
print(l3)
print(l4)
elif len(approx) == 5:
shape = 'Pentagon'
elif len(approx) == 6:
shape = 'Hexagon'
else:
shape = 'Circle'
def unit_vector(self,v):
return v / np.linalg.norm(v)
def distance(self,p1,p4):
global l1,l2,l3,l4,a,b
l1 = int(((p4[0] - p3[0])**2 + (p4[1] - p3[1])**2)**0.5)
l2 = int(((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)**0.5)
l3 = int(((p3[0] - p1[0])**2 + (p3[1] - p1[1])**2)**0.5)
l4 = int(((p4[0] - p2[0])**2 + (p4[1] - p2[1])**2)**0.5)
a = l1 == l2
b = l3 == l4
return l1,b
def get_corner_angle(self,p3):
v1 = np.array([p1[0] - p2[0],p1[1] - p2[1]])
v2 = np.array([p1[0] - p3[0],p1[1] - p3[1]])
v1_unit = self.unit_vector(v1)
v2_unit = self.unit_vector(v2)
radians = np.arccos(np.clip(np.dot(v1_unit,v2_unit),-1,1))
return np.degrees(radians)
def get_corner_angle_opp(self,p4,p3):
v3 = np.array([p4[0] - p2[0],p4[1] - p2[1]])
v4 = np.array([p4[0] - p3[0],p4[1] - p3[1]])
v3_unit = self.unit_vector(v3)
v4_unit = self.unit_vector(v4)
radians = np.arccos(np.clip(np.dot(v3_unit,v4_unit),1))
return np.degrees(radians)
def color(self,hsv_img,cY):
"""Gives the name of the color of the shape"""
global color
#Getting Hue,Saturation,value of the centroid of the shape from HSV image
h,s,v = hsv_img[cY,cX]
#Getting final name of the color according their ranges in the HSV color space
h,cX]
if h in range(0,11) or h in range(170,180):
color = 'Red'
elif h in range(51,76):
color = 'Green'
elif h in range(106,131):
color = 'Blue'
return color
#Creating the Object of class
shapeColorObj = ShapeColorRecognition(img)
#Final output
for ans in shapeColorObj.shapeList:
value = []
key = (ans[0])
value.append(ans[1])
value.append(ans[2])
value.append(ans[3])
value.append(ans[4])
# shape.update({key: value})
print(value)
print(key)
# print(shape)
您还可以看到我的形状名称存储在变量中,并且每当我尝试用作键时,都会产生错误
AttributeError: 'str' object has no attribute 'update'
或
TypeError: 'str' object does not support item assignment
这是我的输出:
(base) C:\Users\Windows 10\OneDrive\Desktop\Python\Eynatra assignment>image.py
['Green',36612.5,191,361]
Trapezoid
['Red',22709.0,831,392]
Triangle
['Blue',50968.0,524,361]
Square
非常感谢您 。
This is one of many images (an example)
解决方法
正如我提到的,我得到的公差为+/- 1,因此我使用该公差创建了一个范围并设置了if-elif-else
条件。我想就是这样。如果您认为这还不够,请更正此问题
p.s。我的信誉点已经减少,所以请不要投票。我总是乐于接受建设性的建议。
import cv2
import numpy as np
img = cv2.imread('Sample4.png',-1)
#Class for recognition of the Shapes and Colors the shapes in the image given
class ShapeColorRecognition():
shape = 'unidentified'
color = 'undetected'
def __init__(self,img):
global shape,color,cX,cY,area
self.shapeList = []
#Getting Contours
self.img = img
gray = cv2.cvtColor(self.img,cv2.COLOR_BGR2GRAY)
blurred = cv2.blur(gray,(5,5))
ret,thresh = cv2.threshold(blurred,230,255,cv2.THRESH_BINARY)
contours,_ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours[1:]:
#Approximating the contours
approxCont = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
#Calculating the Centroid coordinates of the particular object by moments
M = cv2.moments(cnt)
cX = int(M['m10']/M['m00'])
cY = int(M['m01']/M['m00'])
area = cv2.contourArea(cnt)
#Converting image to the HSV format
hsv = cv2.cvtColor(self.img,cv2.COLOR_BGR2HSV)
#Calling the functions for Shapes and Colors
self.shape(approxCont)
self.color(hsv,cY)
#Final List Containing the shape and the color of the object
self.shapeList.append(tuple([shape,area,cY]))
def shape(self,approx):
"""Getting the name of shape of approximated contour"""
global shape
p1 = approx[0][0]
p2 = approx[1][0]
p3 = approx[-1][0]
p4 = approx[2][0]
if len(approx) == 3:
shape = 'Triangle'
elif len(approx) == 4:
(degrees) = self.get_corner_angle(p1,p2,p3)
(degrees_opp) = self.get_corner_angle_opp(p4,p3)
dist1 = self.distance(p1,p3,p4)
# print(degrees)
if ((89 <= int(degrees) <= 91) and (89 <= int(degrees_opp) <= 91)) and (a == b):
shape = "Square"
elif (a == True or b == True) and (int(degrees) or int(degrees_opp) !=90) and (int(degrees_opp)-int(degrees) not in (-1,1)):
shape = "Trapezoid"
elif (int(degrees)-int(degrees_opp) in (-1,1)) and(a-b in (-1,1)):
shape = "Rhombus"
elif (a == True or b == True) and (int(degrees) == int(degrees_opp)):
shape = "Parallelogram"
elif (int(degrees) != int(degrees_opp)) and (a == False and b == False):
shape = "Quadilateral"
elif len(approx) == 5:
shape = 'Pentagon'
elif len(approx) == 6:
shape = 'Hexagon'
else:
shape = 'Circle'
def unit_vector(self,v):
return v / np.linalg.norm(v)
def distance(self,p1,p4):
global l1,l2,l3,l4,a,b
l1 = int(((p4[0] - p3[0])**2 + (p4[1] - p3[1])**2)**0.5)
l2 = int(((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)**0.5)
l3 = int(((p3[0] - p1[0])**2 + (p3[1] - p1[1])**2)**0.5)
l4 = int(((p4[0] - p2[0])**2 + (p4[1] - p2[1])**2)**0.5)
a = l1 == l2
b = l3 == l4
return l1,b
def get_corner_angle(self,p3):
v1 = np.array([p1[0] - p2[0],p1[1] - p2[1]])
v2 = np.array([p1[0] - p3[0],p1[1] - p3[1]])
v1_unit = self.unit_vector(v1)
v2_unit = self.unit_vector(v2)
radians = np.arccos(np.clip(np.dot(v1_unit,v2_unit),-1,1))
return np.degrees(radians)
def get_corner_angle_opp(self,p4,p3):
v3 = np.array([p4[0] - p2[0],p4[1] - p2[1]])
v4 = np.array([p4[0] - p3[0],p4[1] - p3[1]])
v3_unit = self.unit_vector(v3)
v4_unit = self.unit_vector(v4)
radians = np.arccos(np.clip(np.dot(v3_unit,v4_unit),1))
return np.degrees(radians)
def color(self,hsv_img,cY):
"""Gives the name of the color of the shape"""
global color
#Getting Hue,Saturation,value of the centroid of the shape from HSV image
h,s,v = hsv_img[cY,cX]
#Getting final name of the color according their ranges in the HSV color space
h,cX]
if h in range(0,11) or h in range(170,180):
color = 'Red'
elif h in range(51,76):
color = 'Green'
elif h in range(106,131):
color = 'Blue'
return color
#Creating the Object of class
shapeColorObj = ShapeColorRecognition(img)
#Final output
output=[]
for ans in shapeColorObj.shapeList:
value = []
key = (ans[0])
value.append(ans[1])
value.append(ans[2])
value.append(ans[3])
value.append(ans[4])
output.append((key,value))
print(dict(sorted(output,key=lambda t: t[1][1],reverse=True)))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。