Стол обнаружения как поверхность дает много прямоугольников - PullRequest
0 голосов
/ 25 марта 2020

Я хочу получить прямоугольник поверхности стола. Поэтому я подумал, что смогу сделать это с помощью opencv с помощью функций findContours и contourArea. Теперь, когда результатом является то, когда я беру максимальное значение contourArea, оно принимает все как область. Когда я этого не делаю, это дает другой результат, см. Изображения.

Green rectangle over the whole image

Rectangles everywhere

Есть ли способ объединить прямоугольники, чтобы он обнаруживал стол как поверхность? Потому что я хочу знать, находятся ли эти вещи на поверхности или удалены от поверхности.

Код:

import cv2
import numpy as np

file = "/Users/mars/Downloads/table.jpg"

im1 = cv2.imread(file, 0)
im = cv2.imread(file)

ret, thresh_value = cv2.threshold(im1, 180, 255, cv2.THRESH_BINARY_INV)

kernel = np.ones((5, 5), np.uint8)
dilated_value = cv2.dilate(thresh_value, kernel, iterations=1)

contours, hierarchy = cv2.findContours(dilated_value, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt = contours[max_index]
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 2)

cv2.imwrite('result.jpg', im)

1 Ответ

2 голосов
/ 25 марта 2020

Основная причина, по которой ваш код не работает, заключается в том, что вы используете cv2.THRESH_BINARY_INV.
Инвертирование полярности, превращает область таблицы в черный цвет, а findContours ищет белые контуры.

Я предлагаю использовать следующие этапы:

  • Преобразовать в двоичное изображение - используйте THRESH_OTSU для автоматического порога c (это более надежно, чем использование фиксированного порога).
  • Используйте морфологическую операцию «закрытие» (закрытие похоже на расширение и разрушение).
    закрытие лучше, чем dilate, поскольку оно не меняет размер контура.
  • Найдите контуры, используйте RETR_EXTERNAL вместо RETR_TREE, потому что вы ищете внешний контур.
  • Найти контур с максимальной площадью.

Вот код:

import numpy as np
import cv2

# Read input image
im = cv2.imread('table.jpg')

# Drop one row and column from each side (because the image you posted has a green rectangle around it).
im = im[1:-2, 1:-2, :]

# Convert to Grayscale
im1 = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# Convert to binary image - use THRESH_OTSU for automatic threshold.
ret, thresh_value = cv2.threshold(im1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Use "closing" morphological operation (closing is like dilate and than erode)
thresh = cv2.morphologyEx(thresh_value, cv2.MORPH_CLOSE, np.ones((5, 5)))

cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]  # [-2] indexing is used due to OpenCV compatibility issues.

# Get contour with maximum area
c = max(cnts, key=cv2.contourArea)

# Mark contour with green line
cv2.drawContours(im, [c], -1, (0, 255, 0), 2)


# Show output
cv2.imshow('im', cv2.resize(im, (im.shape[1]//4, im.shape[0]//4)))
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат:
enter image description here

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