Извлечение параллелограмма номерного знака из окружающей ограничительной рамки? - PullRequest
10 голосов
/ 10 апреля 2019

Итак, я обучил нейронную сеть распознавания объектов (YOLOv3), чтобы обнаруживать ограничивающие рамки вокруг номерных знаков автомобильных изображений, снятых под различными наклонными и прямыми углами, и сеть делает это довольно надежно. Однако теперь я хочу извлечь параллелограмм номерного знака из ограничивающего прямоугольника, который окружает его, используя обработку изображений и без необходимости обучать другую нейронную сеть для этого. Образцы изображений:

sample images

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

import cv2
import matplotlib.pyplot as plt
import numpy as np

def auto_canny(image, sigma=0.25):
    # compute the median of the single channel pixel intensities
    v = np.median(image)

    # apply automatic Canny edge detection using the computed median
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0 + sigma) * v))
    edged = cv2.Canny(image, lower, upper)

    # return the edged image
    return edged


# Load the image
orig_img = cv2.imread(input_file)

img = orig_img.copy()

dim1,dim2, _ = img.shape

# Calculate the width and height of the image
img_y = len(img)
img_x = len(img[0])

#Split out each channel
blue, green, red = cv2.split(img)
mn, mx = 220, 350
# Run canny edge detection on each channel

blue_edges = auto_canny(blue)

green_edges = auto_canny(green)

red_edges = auto_canny(red)

# Join edges back into image
edges = blue_edges | green_edges | red_edges

contours, hierarchy = cv2.findContours(edges.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

cnts=sorted(contours, key = cv2.contourArea, reverse = True)[:20]
hulls = [cv2.convexHull(cnt) for cnt in cnts]
perims = [cv2.arcLength(hull, True) for hull in hulls]
approxes = [cv2.approxPolyDP(hulls[i], 0.02 * perims[i], True) for i in range(len(hulls))]

approx_cnts = sorted(approxes, key = cv2.contourArea, reverse = True)
lengths = [len(cnt) for cnt in approx_cnts]

approx = approx_cnts[lengths.index(4)]

#check the ratio of the detected plate area to the bounding box
if (cv2.contourArea(approx)/(img.shape[0]*img.shape[1]) > .2):
    cv2.drawContours(img, [approx], -1, (0,255,0), 1)

plt.imshow(img);plt.show()

Вот несколько примеров результатов:

(Изображения в верхнем ряду - результаты этапа обнаружения краев)

Successfuls:

successful-examples

Unsuccessfuls:

unsuccessful-examples

Успешные дела:

kinda-successful-examples

И случай, когда четырехугольник / параллелограмм не найден, но многоугольник с наибольшей найденной площадью нарисован:

non-quadrilateral-examples

все эти результаты с точно таким же набором параметров (пороги, ... и т. Д.)

Я также пытался применить преобразование Хафа, используя cv2.HoughLines, но я не знаю, почему вертикальные наклонные линии всегда пропускаются, независимо от того, как низко я установил порог аккумулятора. Также, когда я опускаю порог, я получаю эти диагональные линии из ниоткуда:

hough-transform-examples

и код, который я использовал для рисования линий Хафа:

lines = cv2.HoughLines(edges,1,np.pi/180,20)
for i in range(len(lines)):
    for rho,theta in lines[i]:
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))

        cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
plt.imshow(img);plt.show()

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

1 Ответ

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

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

Алгоритм будет выглядеть примерно так:

  1. Укажите значения RGB, которые вы хотели бы обнаружить
  2. Определить позиции (x, y), в которых встречаются эти значения RGB
  3. Укажите верхнее левое, нижнее левое, верхнее правое и нижнее правое положения
  4. Графики между этими позициями

Этот пример определения цвета от PyImagesearch может помочь вам его кодировать.

Конечно, обнаружение белых табличек не сработает на белых машинах.

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

...