使用Opencv检测梯形和菱形时的公差问题

如何解决使用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 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res