Обнаружение угла рекламного щита

Я пытался обнаружить изображения рекламных щитов на случайном фоне. Мне удалось локализовать рекламный щит с помощью SSD, это дало мне приблизительную ограничивающую рамку вокруг рекламного щита. Теперь я хочу найти точные углы рекламного щита для своего приложения. Я пробовал использовать разные стратегии, с которыми я столкнулся, такие как определение угла Харриса (с использованием Opencv), поиск пересечений линий с помощью, Canny + морфологические операции + контуры. Подробности о выходе приведены ниже.

Обнаружение угла Харриса. Псевдокод для обнаружения угла Харриса выглядит следующим образом:

img_patch_gray = np.float32(img_patch_gray)
harris_point = cv2.cornerHarris(img_patch_gray,2,3,0.04)
img_patch[harris_point>0.01*harris_point.max()]=[255,0,0]
plt.figure(figsize=IMAGE_SIZE)
plt.imshow(img_patch)

Результат обнаружения ХаррисаЗдесь красные точки - это углы, обнаруженные алгоритмом обнаружения углов Харриса, а точки интереса обведены кружком. в зеленом.

Использование определения линии Хафа. Здесь я пытался найти пересечение линий, а затем выбирал точки. Что-то похожее на ссылку на stackoverflow, но очень сложно получить точные линии, поскольку на рекламных щитах есть текст и графика.

На основе контура. В этом подходе я использовал детектор контуров, за которым следовало расширение (ядро 3 * 3), а затем контур.

bin_img = cv2.Canny(gray_img_patch,100,250)
bin_img = dilate(bin_img, 3)
plt.imshow(bin_img, cmap='gray')
(_,cnts, _) = cv2.findContours(bin_img.copy(), 
cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:10]
cv2.drawContours(img_patch, [cnts[0]],0, (0,255,0), 1)

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

Я использовал openCV 3.4 для всех операций обработки изображений. Используемое Исходное изображениеможно найти здесь. Обратите внимание, что изображение, обсуждаемое здесь, предназначено только для иллюстрации и может быть любым рекламным щитом. Заранее спасибо, приветствуется любая помощь.


person Jasmeen Patel    schedule 15.10.2018    source источник
comment
Это исходное изображение или просто обрезанное без контекста?   -  person Kinght 金    schedule 15.10.2018
comment
сначала размыть изображение с помощью фильтра Гаусса, он удалит мелкие детали / края. Затем попробуйте обнаружение краев по методу «хитрость» или «собел». Вы, вероятно, получите лучшие результаты   -  person user8190410    schedule 15.10.2018
comment
Оператор canny уже включает размытие.   -  person SilverMonkey    schedule 15.10.2018
comment
@Silencer Это обрезанное изображение после локализации рекламного щита.   -  person Jasmeen Patel    schedule 16.10.2018


Ответы (1)


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

import cv2
import numpy as np

# Read the image
img = cv2.imread('billboard.png')

# Blur the image with a big kernel and then transform to gray colorspace
blur = cv2.GaussianBlur(img,(19,19),0)
gray = cv2.cvtColor(blur,cv2.COLOR_BGR2GRAY)

# Perform histogram equalization on the blur and then perform Otsu threshold
equ = cv2.equalizeHist(gray)
_, thresh = cv2.threshold(equ,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Perform opening on threshold with a big kernel (erosion followed by dilation)
kernel = np.ones((20,20),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# Search for contours and select the biggest one
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

# Make a hull arround the contour and draw it on the original image
mask = np.zeros((img.shape[:2]), np.uint8)
hull = cv2.convexHull(cnt)
cv2.drawContours(mask, [hull], 0, (255,255,255),-1)

# Search for contours and select the biggest one again
_, thresh = cv2.threshold(mask,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

# Draw approxPolyDP on the image
epsilon = 0.008*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
cv2.drawContours(img, [cnt], 0, (0,255,0), 5)

# Display the image
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат:

введите здесь описание изображения

person kavko    schedule 15.10.2018