如何在Python和Opencv中检测八角形

如何在Python和Opencv中检测八角形,python,image,opencv,image-processing,shapes,Python,Image,Opencv,Image Processing,Shapes,我正在使用python中的opencv开发一种shape检测算法。 我正在使用库中的轮廓,我已经成功地检测到了一些形状:圆形、矩形和三角形。 唯一的问题是,我只需要检测圆、矩形和八角形。 同样,这个圈子也在运作,但前后不一致。 这是我的代码: import cv2 import numpy as np def nothing(x): # any operation pass cap = cv2.VideoCapture(1) cv2.namedWindow("Trackba

我正在使用python中的opencv开发一种shape检测算法。 我正在使用库中的轮廓,我已经成功地检测到了一些形状:圆形、矩形和三角形。 唯一的问题是,我只需要检测圆、矩形和八角形。 同样,这个圈子也在运作,但前后不一致。 这是我的代码:

import cv2
import numpy as np

def nothing(x):
    # any operation
    pass

cap = cv2.VideoCapture(1)

cv2.namedWindow("Trackbars")
cv2.createTrackbar("L-H", "Trackbars", 0, 180, nothing)
cv2.createTrackbar("L-S", "Trackbars", 66, 255, nothing)
cv2.createTrackbar("L-V", "Trackbars", 134, 255, nothing)
cv2.createTrackbar("U-H", "Trackbars", 180, 180, nothing)
cv2.createTrackbar("U-S", "Trackbars", 255, 255, nothing)
cv2.createTrackbar("U-V", "Trackbars", 243, 255, nothing)

font = cv2.FONT_HERSHEY_COMPLEX

while True:
    _, frame = cap.read()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    l_h = cv2.getTrackbarPos("L-H", "Trackbars")
    l_s = cv2.getTrackbarPos("L-S", "Trackbars")
    l_v = cv2.getTrackbarPos("L-V", "Trackbars")
    u_h = cv2.getTrackbarPos("U-H", "Trackbars")
    u_s = cv2.getTrackbarPos("U-S", "Trackbars")
    u_v = cv2.getTrackbarPos("U-V", "Trackbars")

    lower_yellow = np.array([l_h,l_s, l_v])
    upper_yellow = np.array([u_h, u_s, u_v])

    mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
    kernel = np.ones((5, 5), np.uint8)
    mask = cv2.erode(mask, kernel)

    # Contours detection
    if int(cv2.__version__[0]) > 3:
        # Opencv 4.x.x
        contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    else:
        # Opencv 3.x.x
        _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    for cnt in contours:
        area = cv2.contourArea(cnt)
        approx = cv2.approxPolyDP(cnt, 0.02*cv2.arcLength(cnt, True), True)
        x = approx.ravel()[0]
        y = approx.ravel()[1]

        if area > 400:
            cv2.drawContours(frame, [approx], 0, (0, 0, 0), 5)

            if len(approx) == 3:
                cv2.putText(frame, "Triangle", (x, y), font, 1, (0, 0, 0))
            elif len(approx) == 4:
                cv2.putText(frame, "Rectangle", (x, y), font, 1, (0, 0, 0))
            elif 10 < len(approx) < 20:
                cv2.putText(frame, "Circle", (x, y), font, 1, (0, 0, 0))

    cv2.imshow("Frame", frame)
    cv2.imshow("Mask", mask)

    key = cv2.waitKey(1)
    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()
导入cv2
将numpy作为np导入
def nothing(x):
#任何手术
通过
cap=cv2.视频捕获(1)
cv2.namedWindow(“轨迹栏”)
cv2.createTrackbar(“L-H”,“Trackbars”,0,180,无)
cv2.createTrackbar(“L-S”,“Trackbar”,66255,无)
cv2.createTrackbar(“L-V”,“Trackbars”,134255,无)
cv2.createTrackbar(“U-H”,“轨迹栏”,180,180,无)
cv2.createTrackbar(“U-S”,“trackbar”,255,255,无)
cv2.createTrackbar(“U-V”,“Trackbars”,243255,无)
font=cv2.font\U好时综合酒店
尽管如此:
_,frame=cap.read()
hsv=cv2.CVT颜色(帧,cv2.COLOR_BGR2HSV)
l_h=cv2.getTrackbarPos(“l-h”,“轨迹栏”)
l_s=cv2.getTrackbarPos(“l-s”、“轨迹栏”)
l_v=cv2.getTrackbarPos(“l-v”、“轨迹栏”)
u_h=cv2.getTrackbarPos(“u-h”,“轨迹栏”)
u_s=cv2.getTrackbarPos(“u-s”、“轨迹栏”)
u_v=cv2.getTrackbarPos(“u-v”、“轨迹栏”)
下部黄色=np.数组([l\U h,l\U s,l\U v])
上部黄色=np.数组([u\u h,u\u s,u\u v])
遮罩=cv2.inRange(hsv,下黄,上黄)
内核=np.one((5,5),np.uint8)
掩码=cv2.腐蚀(掩码,内核)
#轮廓检测
如果int(cv2.\uuuuu版本\uuuuu[0])>3:
#Opencv 4.x.x
轮廓,u=cv2.查找轮廓(遮罩、cv2.RETR_树、cv2.CHAIN_近似图、简单图)
其他:
#Opencv 3.x.x
_,轮廓,u=cv2.查找轮廓(遮罩,cv2.RETR_树,cv2.CHAIN_近似简单)
对于轮廓中的cnt:
面积=cv2。轮廓面积(cnt)
近似=cv2.近似聚合度(cnt,0.02*cv2.弧长(cnt,真),真)
x=大约拉威尔()[0]
y=大约拉威尔()[1]
如果面积>400:
cv2.绘图轮廓(框架,[近似],0,(0,0,0),5)
如果len(近似值)=3:
cv2.putText(框架,三角形,(x,y),字体,1,(0,0,0))
elif len(近似值)=4:
cv2.putText(框架,矩形,(x,y),字体,1,(0,0,0))
elif 10

我想要的是更精确地检测八角形和圆。

要执行形状检测,我们可以使用轮廓近似。假设对象是简单的形状,这里有一种使用阈值+轮廓近似的方法。轮廓近似是基于这样的假设,即曲线可以由一系列短线段近似,这些线段可用于确定轮廓的形状。例如,三角形有三个顶点,正方形/矩形有四个顶点,五边形有五个顶点,等等

  • 获取二值图像。我们加载图像,转换为灰度,然后 获取二值图像

  • 检测形状。使用轮廓近似过滤查找轮廓并识别每个轮廓的形状。这可以通过计算轮廓周长和获得实际轮廓近似值来实现


  • 输入图像

    标记形状

    代码

    导入cv2
    def检测_形(c):
    #计算轮廓周长并执行轮廓近似
    shape=“”
    peri=cv2.弧长(c,真)
    近似值=cv2.近似聚合度(c,0.04*peri,真)
    #三角
    如果len(近似值)=3:
    shape=“三角形”
    #正方形还是长方形
    elif len(近似值)=4:
    (x,y,w,h)=cv2.边界矩形(近似值)
    ar=w/浮子(h)
    #正方形的纵横比大约为
    #等于1,否则,形状为矩形
    
    shape=“square”如果ar>=0.95且ar,感谢您的回答。这很有帮助。我只想说,我使用的是实时图像处理(从相机读取),但您的计算机上的图片只能处理,这很酷,但不符合我的需要。此示例演示了如何对图像执行形状检测,您可以对从相机读取的每一帧进行处理。将检测应用到每一帧都是相同的概念好的,非常感谢你为我演示了这一点。如果出现任何问题,我将通知你。如果解决方案奏效,请考虑让别人知道你的问题已经解决了:
    import cv2
    
    def detect_shape(c):
        # Compute perimeter of contour and perform contour approximation
        shape = ""
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.04 * peri, True)
    
        # Triangle
        if len(approx) == 3:
            shape = "triangle"
    
        # Square or rectangle
        elif len(approx) == 4:
            (x, y, w, h) = cv2.boundingRect(approx)
            ar = w / float(h)
    
            # A square will have an aspect ratio that is approximately
            # equal to one, otherwise, the shape is a rectangle
            shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
    
        # Pentagon
        elif len(approx) == 5:
            shape = "pentagon"
    
        # Hexagon
        elif len(approx) == 6:
            shape = "hexagon"
    
        # Octagon 
        elif len(approx) == 8:
            shape = "octagon"
    
        # Star
        elif len(approx) == 10:
            shape = "star"
    
        # Otherwise assume as circle or oval
        else:
            shape = "circle"
    
        return shape
    
    # Load image, grayscale, Otsu's threshold
    image = cv2.imread('1.png')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    
    # Find contours and detect shape
    cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        # Identify shape
        shape = detect_shape(c)
    
        # Find centroid and label shape name
        M = cv2.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
        cv2.putText(image, shape, (cX - 20, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (36,255,12), 2)
    
    cv2.imshow('thresh', thresh)
    cv2.imshow('image', image)
    cv2.waitKey()