从周围的边界框中提取车牌平行四边形?

Moa*_*ana 10 python opencv image-processing computer-vision yolo

因此,我训练了一个对象识别神经网络(YOLOv3),以检测以各种倾斜和直角拍摄的汽车图片的车牌周围的边界框,并且该网络确实可靠。但是现在我想利用图像处理从包围它的包围盒中提取车牌平行四边形,而不必训练另一个神经网络来这样做。样本图片:

样本图片

我已尝试使用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()
Run Code Online (Sandbox Code Playgroud)

这是一些示例结果:

(第一行图像是边缘检测阶段的结果)

成功者:

成功的例子

不成功:

不成功的例子

Kinda成功者:

样例成功

绘制未找到四边形/平行四边形但找到面积最大的多边形的情况:

非四边形的例子

所有这些结果都具有完全相同的参数集(阈值等)

我也尝试过使用cv2.HoughLines应用Hough变换,但我不知道为什么无论我将累加器阈值设置得多么低,都始终错过垂直倾斜的线。另外,当我降低阈值时,这些斜线无处不在:

霍夫变换的例子

以及我用来绘制霍夫线的代码:

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()
Run Code Online (Sandbox Code Playgroud)

仅使用图像处理技术真的很难达到很高的成功率吗?当然,机器学习将像小菜一碟一样解决这个问题,但是我认为这是一个过大的选择,无论如何我都没有带注释的数据。

lee*_*ter 2

您可以使用滤色镜来检测所需的区域。
车牌的边界似乎通常用白色标记。您可以检测图像中的白色像素并绘制最外层位置之间的线。

该算法看起来像:

  1. 指定您想要检测的 RGB 值
  2. 检测这些 RGB 值出现的位置 (x,y)
  3. 识别左上角、左下角、右上角和右下角位置
  4. 在这些位置之间绘制线条

PyImagesearch 中的这个颜色检测示例可能会帮助您编写代码。

当然,检测白色车牌不适用于白色汽车。

为了考虑白色汽车,您可以检查您提供的边界框图像的边框上是否检测到任何白色。如果是这样,请尝试在最外面的蓝色、红色或黑色像素之间绘制线条(因为车牌字母具有这种颜色)。