OpenCV (proyecto) reconocimiento de matrículas 1 -- extracción de matrículas (morfología)

Tabla de contenido

1. Extracción de matrículas morfológicas (simple: escenario único)

 1. Lea la imagen y conviértala a escala de grises

 2. Extraiga el contorno (el operador de Sobel extrae el borde en la dirección y)

3. Binarización adaptativa

4. Procesamiento de la operación de cierre, cierre y amasado de la imagen, regionalización de la imagen.

5. Eliminación de ruido por corrosión/expansión para obtener el área de la matrícula

5-1 Corrosión lateral y expansión

5-2 Corrosión longitudinal y expansión

6. Obtén el esquema

6-1 Obtener el esquema

 6-2 Dibujar el contorno y mostrarlo

7. Interceptar y obtener la matrícula

2. Extracción morfológica de matrículas (optimización: múltiples escenarios)

1. Convertir imagen en escala de grises

2. Operación de sombrero de copa

3. El operador Sobel extrae los bordes en la dirección Y

4. Imagen binarizada

5. Segmentación de operación abierta (segmentación vertical)

6. Fusión de operación de cierre

7. Corrosión/expansión en dirección horizontal/vertical

7-1 Dirección longitudinal: corrosión + expansión

 7-2 Dirección horizontal: expansión + corrosión

 8. Expansión por corrosión: eliminación de ruido

 9. Obtén el esquema

10. Encuentra el contorno de la matrícula según las características de la matrícula

el código

 Referencias


1. Extracción de matrículas morfológicas (simple: escenario único)

(Una sola imagen no es mala, pero varias imágenes no son precisas)

 1. Lea la imagen y conviértala a escala de grises

# 1、读取图片,转灰度图
    img = cv.imread('Resource/car.jpg')
    gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    cv.imshow('gray', gray)

 2. Extraiga el contorno (el operador de Sobel extrae el borde en la dirección y)

 Por qué tomar el borde para la dirección Y: para hacer que la imagen sea "delgada" y que sea más fácil arrugar la matrícula.

# 2、提取轮廓(Sobel算子提取y方向)
    y = cv.Sobel(gray, cv.CV_16S, 1,     0)
    # 注:对x/y微分和得到x/y方向图像相反  要得到x/y方向边缘,就要求y/x方向的微分。
    absY = cv.convertScaleAbs(y)
    cv.imshow('Y', absY)

 

3. Binarización adaptativa

Nota: La función de umbral devuelve dos parámetros, ¡el segundo parámetro es la imagen binaria! !

# 3、自适应二值化
    ret, binary = cv.threshold(absY, 0, 255, cv.THRESH_OTSU)
    cv.imshow('binary', binary)

4. Procesamiento de la operación de cierre, cierre y amasado de la imagen, regionalización de la imagen.

Procesamiento de operación cerrada, regionalización de imágenes, fácil de encontrar el área de la matrícula y luego obtener el contorno

Después de probar varios grupos de imágenes, se descubrió que el kernel de convolución de (17, 5) es mejor y puede lograr el objetivo. 

# 4、闭运算处理,把图像闭合、揉团,使图像区域化,便于找到车牌区域,进而得到轮廓
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (17,5))
    print('kernel= \n', kernel)
    close = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel)
    cv.imshow('close', close)

 (Aquí, se usa un núcleo de convolución rectangular).

5. Eliminación de ruido por corrosión/expansión para obtener el área de la matrícula

Aunque la imagen binaria se obtiene arriba y se obtiene el área aproximada, todavía hay demasiados ruidos (impurezas), y el ruido se elimina por erosión y expansión por debajo.

5-1 Corrosión lateral y expansión

# 5-1、水平方向腐蚀/膨胀
    erode = cv.morphologyEx(close, cv.MORPH_ERODE, kernel_x)
    cv.imshow('erode_x', erode)
    dilate = cv.morphologyEx(erode, cv.MORPH_DILATE, kernel_x)
    cv.imshow('dilate_x', dilate)

 

Una vez realizado el procesamiento horizontal, continúe con el procesamiento vertical. 

5-2 Corrosión longitudinal y expansión

# 5-2、竖直方向腐蚀/膨胀
    erode = cv.morphologyEx(dilate, cv.MORPH_ERODE, kernel_y)
    cv.imshow('erode_y', erode)
    dilate = cv.morphologyEx(erode, cv.MORPH_DILATE, kernel_y)
    cv.imshow('dilate_y', dilate)

 

 Como se muestra en la figura anterior, se obtiene el resultado deseado , básicamente solo quedan unos pocos contornos y el área de la matrícula está bien conservada, lo que no afecta el posicionamiento de la matrícula.

6. Obtén el esquema

Aquí quiero mostrar primero el contorno exterior, incluido el contorno de la matrícula.

6-1 Obtener el esquema

# 6-1、得到轮廓
    contours, hierarchy = cv.findContours(dilate_y, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

 6-2 Dibujar el contorno y mostrarlo

# 6-2、画出轮廓
    cv.drawContours(img_copy, contours, -1, (255,0,255), 2)
    cv.imshow('Contours', img_copy)

Obtenga el código del esquema y el efecto: 

# 6、获取外轮廓
    img_copy = img.copy()
    # 6-1、得到轮廓
    contours, hierarchy = cv.findContours(dilate_y, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    # 6-2、画出轮廓并显示
    cv.drawContours(img_copy, contours, -1, (255,0,255), 2)
    cv.imshow('Contours', img_copy)

7. Interceptar y obtener la matrícula

 Primero juzgue las características de la matrícula (como el ancho: la altura es generalmente de 3 a 4), y luego juzgue de acuerdo con esta característica, y solo conserve las imágenes (matrículas) que cumplan con las características.

 # 7、遍历所有轮廓,找到车牌轮廓
    for contour in contours:
        # 7-1、得到矩形区域:左顶点坐标、宽和高
        rect = cv.boundingRect(contour)
        # 7-2、判断宽高比例是否符合车牌标准,截取符合图片
        if rect[2]>rect[3]*3 and rect[2]<rect[3]*5:
            # 截取车牌并显示
            img = img[rect[1]:(rect[1]+rect[3]), rect[0]:(rect[0]+rect[2])]
            cv.imshow('license plate', img)

 

2. Extracción morfológica de matrículas (optimización: múltiples escenarios)

1. Convertir imagen en escala de grises

gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    cv.imshow('gray', gray)

2. Operación de sombrero de copa

Extraiga la parte más brillante para que el área de la matrícula sea más evidente.

# 2、顶帽运算
    # gray = cv.equalizeHist(gray)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (17,17))
    tophat = cv.morphologyEx(gray, cv.MORPH_TOPHAT, kernel)
    cv.imshow('tophat', tophat)

3. El operador Sobel extrae los bordes en la dirección Y

Verticalice el área de la matrícula para que la matrícula sea más evidente

# 3、Sobel算子提取y方向边缘(揉成一坨)
    y = cv.Sobel(tophat, cv.CV_16S, 1,     0)
    absY = cv.convertScaleAbs(y)
    cv.imshow('absY', absY)

4. Imagen binarizada

Seleccione el umbral de acuerdo con su situación real. Cuanto mayor sea el umbral, más umbrales se vuelven blancos (255) y menos parte blanca. (El umbral aquí es relativamente pequeño, pero hay muchas ventajas y desventajas cuando el umbral es grande)

# 4、自适应二值化(阈值自己可调)
    ret, binary = cv.threshold(absY, 75, 255, cv.THRESH_BINARY)
    cv.imshow('binary', binary)

5. Segmentación de operación abierta (segmentación vertical)

Para evitar que la operación de cierre posterior se conecte con impurezas externas por error, es necesario separarlas mediante la operación de apertura. 

# 5、开运算处理(纵向去噪,分隔)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 15))
    Open = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)
    cv.imshow('Open', Open)

Antes de dividir

Se puede observar que estas impurezas se han integrado por completo en la placa de matrícula, siendo muy difícil separarlas posteriormente.

 Después de dividir :

Aunque hay una pequeña cantidad de conexiones, no son las grandes conexiones anteriores y son relativamente fáciles de quitar.

6. Fusión de operación de cierre

# 6、闭运算合并,把图像闭合、揉团,使图像区域化,便于找到车牌区域,进而得到轮廓
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (41, 15))
    close = cv.morphologyEx(Open, cv.MORPH_CLOSE, kernel)
    cv.imshow('close', close)

El efecto está arriba.

7. Corrosión/expansión en dirección horizontal/vertical

# 7、膨胀/腐蚀(去噪得到车牌区域)
    # 中远距离车牌识别
    kernel_x = cv.getStructuringElement(cv.MORPH_RECT, (25, 7))
    kernel_y = cv.getStructuringElement(cv.MORPH_RECT, (1, 11))
    # 近距离车牌识别
    # kernel_x = cv.getStructuringElement(cv.MORPH_RECT, (91, 31))
    # kernel_y = cv.getStructuringElement(cv.MORPH_RECT, (1, 31))
    # 7-1、腐蚀、膨胀(去噪)
    erode_y = cv.morphologyEx(close, cv.MORPH_ERODE, kernel_y)
    cv.imshow('erode_y', erode_y)
    dilate_y = cv.morphologyEx(erode_y, cv.MORPH_DILATE, kernel_y)
    cv.imshow('dilate_y', dilate_y)
    # 7-1、膨胀、腐蚀(连接)(二次缝合)
    dilate_x = cv.morphologyEx(dilate_y, cv.MORPH_DILATE, kernel_x)
    cv.imshow('dilate_x', dilate_x)
    erode_x = cv.morphologyEx(dilate_x, cv.MORPH_ERODE, kernel_x)
    cv.imshow('erode_x', erode_x)

7-1 Dirección longitudinal: corrosión + expansión

Segmentar objetos que están relativamente cerca arriba y abajo.

 7-2 Dirección horizontal: expansión + corrosión

Conecte más objetos horizontales (después de la operación cerrada anterior, conecte el contenido de la placa nuevamente)

 8. Expansión por corrosión: eliminación de ruido

# 8、腐蚀、膨胀:去噪
    kernel_e = cv.getStructuringElement(cv.MORPH_RECT, (25, 11))
    erode = cv.morphologyEx(erode_x, cv.MORPH_ERODE, kernel_e)
    cv.imshow('erode', erode)
    kernel_d = cv.getStructuringElement(cv.MORPH_RECT, (25, 13))
    dilate = cv.morphologyEx(erode, cv.MORPH_DILATE, kernel_d)
    cv.imshow('dilate', dilate)

 9. Obtén el esquema

# 9、获取外轮廓
    img_copy = img.copy()
    # 9-1、得到轮廓
    contours, hierarchy = cv.findContours(dilate, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    # 9-2、画出轮廓并显示
    cv.drawContours(img_copy, contours, -1, (255, 0, 255), 2)
    cv.imshow('Contours', img_copy)

 

10. Encuentra el contorno de la matrícula según las características de la matrícula

La relación de aspecto de la matrícula generalmente está entre 3 y 4 , pero primero tengo muchas fotos aquí, y las impurezas adjuntas a algunas fotos no se han limpiado, así que la configuré entre 3 y 6.5.

# 10、遍历所有轮廓,找到车牌轮廓
    i = 0
    for contour in contours:
        # 10-1、得到矩形区域:左顶点坐标、宽和高
        rect = cv.boundingRect(contour)
        # 10-2、判断宽高比例是否符合车牌标准,截取符合图片
        if rect[2]>rect[3]*3 and rect[2]<rect[3]*6.5:
            # 截取车牌并显示
            print(rect)
            img = img[(rect[1]-5):(rect[1]+rect[3]+5), (rect[0]-5):(rect[0]+rect[2]+5)] #高,宽
            try:
                cv.imshow('license plate%d-%d' % (count, i), img)
                # cv.imwrite('img%d-%d.jpg'%(count, i), img)
                i += 1
            except:
                pass
    cv.waitKey(0)

Media y larga distancia :

Tasa de éxito de matrícula normal: 100% (probado 11 casos, todos exitosos)

Tasa de éxito de matrícula inclinada: 67% (Prueba 2 casos, 3 matrículas, la falla de reconocimiento de matrícula más pequeña) (pero el procesamiento no es muy bueno)

Tasa de éxito de matrícula de corta distancia: 0% (Prueba 2 casos, todos fallidos)

 

rango cercano :

(La tasa de éxito a corta distancia es del 50 %, porque solo se realizaron 2)

el código

# 车牌识别
import cv2 as cv
import numpy as np
import os

# 提取车牌(形态学)
def Morph_Distinguish(img):
    # 1、转灰度图
    gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    cv.imshow('gray', gray)

    # 2、顶帽运算
    # gray = cv.equalizeHist(gray)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (17,17))
    tophat = cv.morphologyEx(gray, cv.MORPH_TOPHAT, kernel)
    cv.imshow('tophat', tophat)

    # 3、Sobel算子提取y方向边缘(揉成一坨)
    y = cv.Sobel(tophat, cv.CV_16S, 1,     0)
    absY = cv.convertScaleAbs(y)
    cv.imshow('absY', absY)

    # 4、自适应二值化(阈值自己可调)
    ret, binary = cv.threshold(absY, 75, 255, cv.THRESH_BINARY)
    cv.imshow('binary', binary)

    # 5、开运算分割(纵向去噪,分隔)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 15))
    Open = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)
    cv.imshow('Open', Open)

    # 6、闭运算合并,把图像闭合、揉团,使图像区域化,便于找到车牌区域,进而得到轮廓
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (41, 15))
    close = cv.morphologyEx(Open, cv.MORPH_CLOSE, kernel)
    cv.imshow('close', close)

    # 7、膨胀/腐蚀(去噪得到车牌区域)
    # 中远距离车牌识别
    kernel_x = cv.getStructuringElement(cv.MORPH_RECT, (25, 7))
    kernel_y = cv.getStructuringElement(cv.MORPH_RECT, (1, 11))
    # 近距离车牌识别
    # kernel_x = cv.getStructuringElement(cv.MORPH_RECT, (79, 15))
    # kernel_y = cv.getStructuringElement(cv.MORPH_RECT, (1, 31))
    # 7-1、腐蚀、膨胀(去噪)
    erode_y = cv.morphologyEx(close, cv.MORPH_ERODE, kernel_y)
    cv.imshow('erode_y', erode_y)
    dilate_y = cv.morphologyEx(erode_y, cv.MORPH_DILATE, kernel_y)
    cv.imshow('dilate_y', dilate_y)
    # 7-1、膨胀、腐蚀(连接)(二次缝合)
    dilate_x = cv.morphologyEx(dilate_y, cv.MORPH_DILATE, kernel_x)
    cv.imshow('dilate_x', dilate_x)
    erode_x = cv.morphologyEx(dilate_x, cv.MORPH_ERODE, kernel_x)
    cv.imshow('erode_x', erode_x)

    # 8、腐蚀、膨胀:去噪
    kernel_e = cv.getStructuringElement(cv.MORPH_RECT, (25, 9))
    erode = cv.morphologyEx(erode_x, cv.MORPH_ERODE, kernel_e)
    cv.imshow('erode', erode)
    kernel_d = cv.getStructuringElement(cv.MORPH_RECT, (25, 11))
    dilate = cv.morphologyEx(erode, cv.MORPH_DILATE, kernel_d)
    cv.imshow('dilate', dilate)

    # 9、获取外轮廓
    img_copy = img.copy()
    # 9-1、得到轮廓
    contours, hierarchy = cv.findContours(dilate, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    # 9-2、画出轮廓并显示
    cv.drawContours(img_copy, contours, -1, (255, 0, 255), 2)
    cv.imshow('Contours', img_copy)

    # 10、遍历所有轮廓,找到车牌轮廓
    i = 0
    for contour in contours:
        # 10-1、得到矩形区域:左顶点坐标、宽和高
        rect = cv.boundingRect(contour)
        # 10-2、判断宽高比例是否符合车牌标准,截取符合图片
        if rect[2]>rect[3]*3 and rect[2]<rect[3]*7:
            # 截取车牌并显示
            print(rect)
            img = img[(rect[1]-5):(rect[1]+rect[3]+5), (rect[0]-5):(rect[0]+rect[2]+5)] #高,宽
            try:
                cv.imshow('license plate%d-%d' % (count, i), img)
                cv.imwrite('car_licenses/img%d-%d.jpg'%(count, i), img)
                i += 1
            except:
                pass
    cv.waitKey(0)


if __name__ == '__main__':
    global count
    count=0
    # 遍历文件夹中的每张图片(车)
    for car in os.listdir('cars'):
        # 1、获取路径
        path = 'cars/'+'car'+str(count)+'.jpg'
        # 2、获取图片
        img = cv.imread(path)
        # 3、定位车牌
        Morph_Distinguish(img)         #形态学提取车牌
        count += 1

    cv.waitKey(0)

        La compra de proxy es solo para referencia. En la actualidad, solo puede extraer la matrícula del automóvil a cierta distancia. Está demasiado lejos o demasiado cerca. No es adecuado para inclinar, y es difícil aplicarlo a la realidad. vida. La situación en la vida real es mucho más complicada. ¿Qué hay? Las sugerencias o críticas son libres de hablar. (El procesamiento inclinado se puede agregar aquí más adelante)

 Referencias

[Proyecto de combate] Proyecto de reconocimiento de matrículas basado en coincidencia de plantilla OpenCV_哔哩哔哩_bilibili

Reconocimiento de matrículas basado en python+OpenCV_PYH1009 Blog-CSDN Blog_Sistema de reconocimiento de matrículas basado en Python

Supongo que te gusta

Origin blog.csdn.net/great_yzl/article/details/119934992
Recomendado
Clasificación