Подтвердить что ты не робот

Поиск расположения прямоугольников в изображении с помощью OpenCV

Я пытаюсь использовать OpenCV для "синтаксического анализа" скриншотов из игры iPhone Blocked. Снимок экрана обрезается, чтобы выглядеть так:

Blocked screenshot

Я полагаю, что сейчас я просто пытаюсь найти координаты каждого из 4 точек, составляющих каждый прямоугольник. Я видел пример файла squares.c, который поставляется с OpenCV, но когда я запускаю этот алгоритм на этом изображении, он имеет 72 прямоугольника, включая прямоугольные области пробелов, которые я, очевидно, не хочу считать одним из моих прямоугольники. Каков лучший способ приблизиться к этому? Я пробовал делать некоторые исследования Google, но для всех результатов поиска очень мало релевантной полезной информации.

4b9b3361

Ответ 1

Подобный вопрос уже обсуждался: Как распознать прямоangularьники на этом изображении?

Что касается ваших данных, прямоangularьники, которые вы пытаетесь найти, являются единственными черными объектами. Таким образом, вы можете попытаться выполнить пороговую бинаризацию: черные пиксели - это те, у которых ВСЕ три значения RGB меньше 40 (я нашел это эмпирически). Эта простая операция делает вашу картинку похожей на это:

binarized picture

После этого вы можете применить преобразование Хафа, чтобы найти строки (обсуждаемые в теме, на которую я ссылался), или вы можете сделать это проще. Вычислить интегральные проекции черных пикселей на оси X и Y. (Проекция на X является вектором x_i - числа черных пикселей, для которого первая координата равна x_i). Таким образом, вы получаете возможные значения x и y как пики проекций. Затем просмотрите все возможные сегменты, ограниченные найденными x и y (если между (x_i, y_j) и (x_i, y_k) много черных пикселей, вероятно, есть линия). Наконец, составьте отрезки в прямоangularьники!

Ответ 2

Я только что основал свой оригинальный метод и делал, как предложил Роберт в своем комментарии к моему вопросу. После того, как я получу свой список прямоугольников, я затем пробегаю и вычисляю средний цвет по каждому прямоугольнику. Я проверяю, соответствуют ли красные, зеленые и синие компоненты среднего цвета в пределах 10% от цветов серого и синего прямоугольников, и если они я сохраняю прямоугольник, если они не отбрасываются. Этот процесс дает мне что-то вроде этого:

screenshot

Из этого тривиально получить нужную мне информацию (ориентацию, начальную точку и длину каждого прямоугольника, учитывая окно игры как сетку 6x6).

Ответ 3

Блоки выглядят как растровые изображения - почему бы вам не использовать простой шаблон для разных шаблонов для каждого размера блока/цвета/ориентации?

Ответ 4

Так как ваша проблема - это маленькие прямоугольники, я бы начал с их удаления. Поскольку эти строки намного тоньше границ прямоугольников, я бы начал с применения морфологических операций на изображении.

Использование структурного элемента, который выглядит следующим образом:

 element = [ 1 1
             1 1 ]

следует удалить строки шириной менее двух пикселей. После удаления небольших строк алгоритм поиска прямоугольника OpenCV, скорее всего, выполнит всю оставшуюся работу. Эрозия может быть выполнена в OpenCV с помощью функции cvErode

Ответ 5

Попробуйте один из многих угловых детекторов, таких как угловой детектор Harris. также, как правило, неплохо попробовать это при нескольких разрешениях: так что сделайте некоторую предварительную обработку разного увеличения. Похоже, что вам нужен какой-то цветной квадрат с преобладанием, тогда вы можете подавить другие цвета, сначала используя что-то вроде cvsplit..... и затем пороговое значение цвета... так что только этот регион остается... следуйте этому с помощью операция обрезки... Я думаю, что это тоже могло бы работать...

Ответ 6

Здесь полное решение Python. Основная идея:


Здесь визуализация каждого обнаруженного контура прямоangularьника

enter image description here

Результаты

enter image description here

import cv2

image = cv2.imread('1.png')
blur = cv2.pyrMeanShiftFiltering(image, 11, 21)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.015 * peri, True)
    if len(approx) == 4:
        x,y,w,h = cv2.boundingRect(approx)
        cv2.rectangle(image,(x,y),(x+w,y+h),(36,255,12),2)

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