OpenCV, контур покрытия прямоугольниками - PullRequest
0 голосов
/ 22 марта 2020

как с помощью OpenCV можно покрыть неправильную форму несколькими прямоугольниками? См. Примеры фигур.

Прямоугольники должны покрывать максимальную площадь объекта и могут быть под любым углом. Важно, чтобы они не перекрывали друг друга. Если прямоугольник покрывает какой-то фон, это нормально.

Я нашел эту нить , которая разбивает контуры на маленькие прямоугольники, но они не сливаются в максимально возможный прямоугольник. [https://answers.opencv.org/question/25912/split-contours-into-many-small-rectangles/]

Я использую OpenCV с python, но если у вас есть пример кода на C ++, он вполне подойдет.

Перед изображением

Требуемый результат

1 Ответ

1 голос
/ 22 марта 2020

Вот один простой способ разбить это на 4 прямоугольника, используя Python / OpenCV.

  • Чтение ввода
  • Преобразование в серый
  • Порог
  • Получите два контура
  • Вычислите две вертикальные линии по длине внешней (большей) высоты контура, но вдоль сторон внутреннего (меньшего) контура
  • Нарисуйте эти вертикальные линии на пороговом изображении
  • Получить и нарисовать контуры на предыдущем изображении
  • Сохранить результат

Ввод:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('rectangles.png')
hh, ww = img.shape[:2]

# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]

# get contours and get the largest and smallest ones
contour_img = img.copy()
contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
min_area_thresh = hh * ww
max_area_thresh = 0
for cntr in contours:
    cv2.drawContours(contour_img, [cntr], -1, (0, 255, 0), 1)
    area = cv2.contourArea(cntr)
    if area < min_area_thresh:
        xs,ys,ws,hs = cv2.boundingRect(cntr)
        min_area_thresh = area
        small_contour = cntr
    if area > max_area_thresh:
        xl,yl,wl,hl = cv2.boundingRect(cntr)
        max_area_thresh = area
        large_contour = cntr


# compute vertical lines of height of large contour along the sides of the inner contours
x1 = xs
y1 = yl
x2 = x1
y2 = yl + hl - 1
x3 = xs + ws - 1
y3 = yl
x4 = x3
y4 = y2

# draw two vertical lines in black on thresholded image to separate segments
thresh2 = thresh.copy()
cv2.line(thresh2, (x1,y1), (x2,y2), 0, 1) 
cv2.line(thresh2, (x3,y3), (x4,y4), 0, 1) 

# get and draw contours from thresh2
result = thresh2.copy()
result = cv2.merge([result,result,result])
contours = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
    color = list(np.random.random(size=3) * 256)
    cv2.drawContours(result, [cntr], -1, color, 2)

# show thresh and result    
cv2.imshow("input", img)
cv2.imshow("thresh", thresh)
cv2.imshow("contours", contour_img)
cv2.imshow("thresh2", thresh2)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save resulting images
cv2.imwrite('rectangles_contours.png',contour_img)
cv2.imwrite('rectangles_thresh2.png',thresh2)
cv2.imwrite('rectangles_result.png',result)


Большие и маленькие контуры на пороговом изображении:

enter image description here

Отрисованы две черные вертикальные линии на пороговом изображении:

enter image description here

Случайные цветные контуры, нарисованные на предыдущем изображении в результате:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...