Как получить единственный прямоугольник минимальной области на изображении с несколькими контурами с помощью cv2.minAreaRect (cnt)? - PullRequest
0 голосов
/ 09 апреля 2019

Я хочу использовать только один прямоугольник, чтобы покрыть круг на этом изображении:

my image

И получите этот результат с cv2.minAreaRect(cnt):

After processing

Это изображение, похоже, разделено на несколько частей. Может быть, это потому, что на краю этого изображения есть точка останова. Вы можете сказать мне, как использовать только один прямоугольник, чтобы покрыть этот круг моего изображения? Большое спасибо!

Это мой код:

def draw_min_rect_circle(img, cnts):  # conts = contours
    img = np.copy(img)

    for cnt in cnts:
        x, y, w, h = cv2.boundingRect(cnt)
        cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)  # blue

        min_rect = cv2.minAreaRect(cnt)  # min_area_rectangle
        min_rect = np.int0(cv2.boxPoints(min_rect))
        cv2.drawContours(img, [min_rect], 0, (0, 255, 0), 2)  # green

        (x, y), radius = cv2.minEnclosingCircle(cnt)
        center, radius = (int(x), int(y)), int(radius)  # center and radius of minimum enclosing circle
        img = cv2.circle(img, center, radius, (0, 0, 255), 2)  # red
return img

Ответы [ 2 ]

2 голосов
/ 09 апреля 2019

Вы, вероятно, искали контуры с помощью cv2.findContours() и повторяли их, чтобы нарисовать прямоугольник на изображении. Проблема состоит в том, что ваше изображение не имеет окружности, состоящей из одной соединенной линии, но содержит много ломаных линий

Контуры - это кривые, соединяющие все непрерывные точки (вдоль границы), имеющие одинаковый цвет или интенсивность (документация OpenCV).

Таким образом, чтобы получить лучший результат, вы должны сначала подготовить свое изображение, прежде чем искать контуры. Вы можете использовать различные инструменты для предварительной обработки изображения (вы можете искать документацию OpenCV). В этом случае я бы попытался выполнить процедуру под названием «закрытие» с небольшим ядром. Закрытие - это расширение с последующей эрозией пикселей. Это может помочь соединить ваши маленькие контуры с одним большим контуром (кругом). Затем вы можете выбрать самый большой и нарисовать ограничивающий прямоугольник.

Пример:

Исходное изображение:

enter image description here

import cv2
import numpy as np

img = cv2.imread('test.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((3,3), dtype=np.uint8)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
_, contours, hierarchy = cv2.findContours(closing, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x,y), (x+w, y+h), (255,255,0), 1)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат:

enter image description here

Изображение после выполнения операции закрытия:

enter image description here

Надеюсь, это поможет. Ура!

0 голосов
/ 09 апреля 2019

Что вам нужно сделать, так это то, что вам нужно каким-то образом получить только 1 контур из изображения путем объединения контуров, что немного сложно сделать, поэтому, если вы хотите, чтобы прямоугольник был заключен вокруг всех контуров, вы можете сделать что-то как таковой

def draw_min_rect_circle(img, cnts):  # conts = contours
    img = np.copy(img)
    x1,y1 = np.inf
    x2,y2 = 0
    for cnt in cnts:
        x, y, w, h = cv2.boundingRect(cnt)
        if x > x1:
           x1=x
        if y > y1:
           y1=y
        if x2 < x+w
           x2 = x+w
        if y2 < y+h
           y2 = y+h
     w = x2 - x1
     h = y2 - y1
     r = math.sqrt((w*w) + (h*h)) / 2

     cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
     cv2.circle(img, (x1+w/2,y1+h/2), r, (0, 0, 255), 2)
...