使用cv2进行形状识别

问题描述 投票:0回答:1

我的代码有问题,它应该获得两行输入,第一行是图像中有多少个形状,第二行是图像路径。

输出应该是形状类型的数量,示例输入:有一张test1.jpg图像,里面有10个圆圈,输出应该是:1

这是有人使用内核想出的代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def detect_shape(cnt):
    peri = cv2.arcLength(cnt, True)
    vertices = cv2.approxPolyDP(cnt, 0.04 * peri, True)  # Approximate the polygonal curves
    if len(vertices) == 3:
        return "Triangle"
    elif len(vertices) == 4:
        x, y, w, h = cv2.boundingRect(vertices)
        aspect_ratio = float(w) / h
        if 0.95 <= aspect_ratio <= 1.05:
            return "Square"
        else:
            return "Rectangle"
    else:
        return "Circle"

num_shapes = int(input("Enter the number of shapes in the image: "))
image_path = input("Enter the path to the image: ")


image = cv2.imread(image_path)


gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_OTSU)
inv_binary = cv2.bitwise_not(binary)

kernel = 255*np.ones((10, 10), np.uint8) # dilate the binary mask, here and next line
dilated_binary = cv2.dilate(gray, kernel, iterations=1)

mask = cv2.dilate((dilated_binary < 245).astype(np.uint8)*255, kernel, iterations=1) # create another binary mask where the values are lower than 245, here I did some manual checking

contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # find the contour on the mask

filtered_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 100] # filter the contours

circles = 0 
triangles = 0 
rectangles = 0  
for contour in filtered_contours:
        M = cv2.moments(contour)
        if M["m00"] != 0:
            cx = int(M["m10"] / M["m00"])
            cy = int(M["m01"] / M["m00"])
        # approximate the contour
        epsilon = 0.04 * cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, epsilon, True)
        # number of sides
        num_vertices = len(approx)
        # see how many sides and decide which shape
        if num_vertices == 3:
            shape = "Triangle"
            triangles += 1
        elif num_vertices == 4:
            shape = "Rectangle"
            rectangles += 1
        else: # in this case I just put the default as a circle, since there are currently no other options.
            shape = "Circle"
            circles += 1
        plt.text(cx, cy, shape)
         
print("Summary:") 
print("Rects or squares: "+str(rectangles)) 
print("Triangles: "+str(triangles))
print("Circles: "+str(circles))

cv2.imshow('adjusted', mask)
cv2.waitKey()
cv2.destroyAllWindows()



但是有一个问题,只有一张图片我无法解决

因此,如果您将此图像作为输入,它将无法正常工作:

python image opencv kernel
1个回答
0
投票

通过使用 Python/OpenCV cv2.inRange() 对原始图像中的背景灰色进行阈值处理然后反转,您可能会获得更好的阈值结果。或者转换为 HSV 并在饱和度通道上设置阈值,其中灰色背景的饱和度非常低,而彩色区域的饱和度较高

例如,这是饱和通道:

这是饱和通道的阈值:

这是输入上的反转颜色阈值:

© www.soinside.com 2019 - 2024. All rights reserved.