Opencv Python - 形状检测

时间:2018-04-12 08:56:53

标签: python python-2.7 image-processing opencv-python

如何分割图像中的两个矩形。还要删除多余的投影来提取矩形的坐标。轮廓检测将整个图像显示为圆形,而不是将其分成两个矩形。enter image description here

请找到输入图片,

enter image description here

detect_shapes.py

  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)    
      blurred = cv2.GaussianBlur(gray, (5, 5), 0)   
      thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
      cnts = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
  cnts = cnts[0] if imutils.is_cv2() else cnts[1]
  sd = ShapeDetector()

  for c in cnts:
        M = cv2.moments(c)
        cX = int((M["m10"] / M["m00"]))
        cY = int((M["m01"] / M["m00"]))
        shape = sd.detect(c)

        c = c.astype("float")
        #c *= ratio
        c = c.astype("int")
        cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
        cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX,
            0.5, (255, 0, 0), 2)

        cv2.imshow("Image", image)
        cv2.waitKey(0)

shapedetector.py

class ShapeDetector:
    def __init__(self):
        pass

    def detect(self, c):
        shape = "unidentified"
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.04 * peri, True)

        if len(approx) == 3:
            shape = "triangle"

        elif len(approx) == 4:
            print("value of approx", approx)
            (x, y, w, h) = cv2.boundingRect(approx)
            ar = w / float(h)

            print("value of ar",ar)
            if (ar >= 0.95 and ar <= 1.05): shape = "Square"
            elif (ar <= 5 and ar >= 3): shape = "Obround"
            else: shape = "rectangle"

        elif len(approx) == 5:
            shape = "pentagon"
        elif len(approx) == 2:
            shape = "line"
            print("value of approx", approx)
        else:
            shape = "circle"
            print("value of approx", approx)
return shape

我需要的输出如下。 enter image description here

1 个答案:

答案 0 :(得分:2)

正如Akhilesh建议的那样,形态OPEN操作将删除连接两个矩形的线。这里有一个优秀的Python教程:https://docs.opencv.org/3.0.0/d9/d61/tutorial_py_morphological_ops.html。使用适用于您的应用程序的最小内核大小,以防止过多的失真。对于测试图像,我使用的内核大小为5.

detect_shapes.py:

import cv2
from shapedetector import ShapeDetector

image = cv2.imread('rectangles.jpg')

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)    
blurred = cv2.GaussianBlur(gray, (5, 5), 0)   
thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]

ksize = 5
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize,ksize))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

cnts = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# ~ cnts = cnts[0] if imutils.is_cv2() else cnts[1]
cnts = cnts[1]
sd = ShapeDetector()

for c in cnts:
    M = cv2.moments(c)
    if M["m00"] != 0:  # prevent divide by zero
        cX = int((M["m10"] / M["m00"]))
        cY = int((M["m01"] / M["m00"]))
        shape = sd.detect(c)

    c = c.astype("float")
    #c *= ratio
    c = c.astype("int")
    cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
    cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX,
        0.5, (255, 0, 0), 2)

cv2.imshow("Image", image)
cv2.waitKey(0)

shapedetector.py:

import cv2

class ShapeDetector:
    def __init__(self):
        pass

    def detect(self, c):
        shape = "unidentified"
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.04 * peri, True)

        if len(approx) == 3:
            shape = "triangle"

        elif len(approx) == 4:
            print("value of approx", approx)
            (x, y, w, h) = cv2.boundingRect(approx)
            ar = w / float(h)

            print("value of ar",ar)
            if (ar >= 0.95 and ar <= 1.05): shape = "Square"
            elif (ar <= 5 and ar >= 3): shape = "Obround"
            else: shape = "rectangle"

        elif len(approx) == 5:
            shape = "pentagon"
        elif len(approx) == 2:
            shape = "line"
            print("value of approx", approx)
        else:
            shape = "circle"
            print("value of approx", approx)

        return shape

输出图片:

output image