简体   繁体   中英

Contour object detection and extraction in OpenCV Python

I am trying to detect three rectangles from the contour. I have already extracted the entire contour from the whole image. I am attaching the image of extracted contour below. I would like to figure out a way to further extract three rectangular kind panels from the whole contour.

Extracted Contour Image:

在此输入图像描述

Here's a simple approach:

  • Convert image to grayscale
  • Threshold to obtain binary image
  • Perform morphological operations to smooth image
  • Find contours and extract ROI

After converting to grayscale, we threshold to obtain a binary image

image = cv2.imread('1.png')
original = image.copy()

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY)[1]

Next we create a kernel and perform morphological operations to smooth the image. This step "breaks" the joints connecting the three rectangles by eroding the image

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,25))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

From here we find contours and extract the ROI with numpy slicing. The bounding boxes for the desired rectangles are drawn on the original image

cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

image_number = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 3)
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite("ROI_{}.png".format(image_number), ROI)
    image_number += 1

Here's each individual saved ROI

Full code

import cv2

image = cv2.imread('1.png')
original = image.copy()

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,25))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

image_number = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 3)
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite("ROI_{}.png".format(image_number), ROI)
    image_number += 1

cv2.imshow('opening', opening)
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()

This looks like a case for opening with a kernel sufficiently large to erode the lines in between your rectangles.

Another way would be to do the erode multiple times and then call dilate the same number of times.

A little suggestion, you might want to apply a thresh-hold on your image, because it looks like you have some noise (especially on the left and top rectangles).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM