Todo o processo do projeto de reconhecimento de placas - auto-estudo do conhecimento opencv

o que é opencv?

  1. OpenCV (Open Source Computer Vision Library) é uma biblioteca de visão computacional e aprendizado de máquina de código aberto que fornece interfaces como C++, C e python e suporta plataformas Windows, Linux, Android e MacOS.
  2. A partir de 2016, a aplicação de deep learning tornou-se cada vez mais extensa, e módulos como CNN também foram adicionados ao OpenCV, que podem ser conectados com os modelos treinados pelo Tensorflow e Caffe2.

Fundamentos de digitalização de imagens

Uma imagem é composta de inúmeros pequenos quadrados.
Imagens coloridas - são compostas por pequenos quadrados coloridos , cada quadrado colorido é quantizado por um vetor de três valores . (0, 0, 0) representa preto, (255, 255, 255) representa branco e (255, 0, 0) representa vermelho.
Imagem cinza - é composta de pequenos quadrados cinza , cada um dos quais é quantizado por um vetor de valores numéricos .
insira a descrição da imagem aqui
Uma matriz numérica bidimensional com 508 linhas (altura) e 672 colunas (largura).
insira a descrição da imagem aqui
O computador digitalizará cada pixel em um valor numérico. A "profundidade de bits" da imagem em tons de cinza é de 8 bits (a cor é de 24 bits), o que significa que cada quadrado é digitalizado em um número do tipo uchar entre [0, 255], que é usado 256 números são usados ​​para medir o tom de cinza, quanto maior o valor, mais brilhante o valor, quanto menor o valor, mais cinza, 255 é branco e 0 é preto.

aquisição de imagem

insira a descrição da imagem aqui

import cv2
gray_img = cv2.imread(r'C:\Users\fujie\Pictures\shunli.jpg',1) # 读入图像
cv2.imshow('Image', gray_img) # 显示图像
cv2.imwrite('images/output.jpg', gray_img)     # 保存图像
cv2.waitKey()  #等待时间,毫秒级,0表示任意中止

transformação de imagem

A execução de algumas operações em imagens pode ser considerada um meio de expansão da imagem .

  • O objetivo do aprimoramento de imagem é melhorar o efeito visual da imagem. Para a aplicação de uma determinada imagem, aprimorar propositadamente as características gerais ou locais da imagem, tornar a imagem original pouco clara ou aprimorar alguns recursos interessantes, expandir a imagem. A diferença entre as características de diferentes objetos na imagem, suprime as características desinteressantes, melhora a qualidade da imagem, enriquece a quantidade de informações, interpreta e reconhece a imagem forte, e atende às necessidades de algumas análises de características.

alterar tamanho

(x,y,3)
linha x - altura
coluna y - largura
insira a descrição da imagem aqui

Análise de conteúdo de reconhecimento de placas

  1. A tecnologia de reconhecimento automático da placa de licença é conectar o método de processamento de imagens com a tecnologia de software do computador , a fim de reconhecer com precisão os caracteres da placa de licença e transmitir os dados reconhecidos ao sistema de gerenciamento de tráfego em tempo real, de modo para finalmente realizar a fiscalização de trânsito.
  2. a placa do carro do meu país é geralmente composta por sete caracteres e um ponto.
    O reconhecimento de placas é dividido basicamente em quatro partes: aquisição de imagem (obtenção das informações da imagem do veículo a partir do sensor visual) - localização da placa (encontrando a posição da placa a partir da imagem original) - segmentação de caracteres (segmentação da placa placa em sete caracteres) Usado para reconhecimento de caracteres subsequente) - reconhecimento de caracteres (reconhecendo os caracteres únicos separados para identificar o valor da placa)

Localize a placa de licença

Encontre a localização da placa (localize a área) da imagem adquirida e segmente a placa dessa área para segmentação de caracteres subsequente.
Existem quatro tipos principais de métodos de posicionamento de placas:

  1. Segmentação baseada em cores: Utilize informações de espaço de cores, incluindo algoritmo de borda de cores, algoritmo de distância de cores e algoritmo de similaridade.
  2. Segmentação baseada em textura: por exemplo, usando os recursos de textura na direção horizontal da área da placa de licença para realizar a segmentação, incluindo textura wavelet e textura de diferença de gradiente horizontal.
  3. Segmentação com base na detecção de borda
  4. Segmentação baseada na morfologia matemática

Redução de ruído de imagem

Para adquirir uma imagem, a imagem original é colorida e se torna uma imagem em tons de cinza para processamento posterior.
insira a descrição da imagem aqui
A imagem original contém informações de ruído. O ruído pode ser entendido como alterações aleatórias nos valores da escala de cinza causadas por um ou mais motivos. Na maioria dos casos, são necessárias técnicas de suavização (filtragem) para removê-los. Algoritmos de suavização comumente usados ​​incluem suavização gaussiana e suavização média com base na convolução discreta bidimensional. . . Esta operação usa o método de suavização gaussiana.

Filtragem gaussiana : Se o valor de um pixel for muito maior do que os pontos ao redor, pode ser um ruído ou borda de alta frequência. A filtragem gaussiana usa vários pontos ao redor do ponto para fazer uma média ponderada deles, o que equivale a usar o valor circundante para diminuir esse valor alto, que é chamado de suavização. A incorporação matemática da filtragem gaussiana é a operação de reatribuição dos valores de pixel de toda a imagem por meio da média ponderada. (A média ponderada pode ser entendida como o resultado de calcular e somar diferentes partes de acordo com diferentes proporções.)
Link de detalhes

- A imagem resultante é ligeiramente desfocada em comparação com o original. Desta forma, um único pixel torna-se quase insignificante na imagem suavizada gaussiana.
insira a descrição da imagem aqui

  • Suavização gaussiana do OpenCV:
    A suavização gaussiana é feita fazendo uma operação de convolução discreta bidimensional entre duas matrizes, e o kernel de convolução gaussiana é convoluído com a imagem original.
    insira a descrição da imagem aqui

insira a descrição da imagem aqui

  • convolução:
    insira a descrição da imagem aqui
  • A função para construir um kernel de convolução gaussiana na direção vertical unidimensional é fornecida no OpenCV: Mat getGaussianKernel(int ksize, double sigma, in ktype = CV/_64F)

Processamento morfológico

O processamento morfológico é usado principalmente para extrair componentes da imagem que são significativos para expressar e descrever a forma da região da imagem, de modo que o trabalho de reconhecimento subsequente possa capturar as características de forma mais essenciais (mais discriminativas) do objeto alvo, como limites e formas. áreas conectadas, etc. Ao mesmo tempo, técnicas como afinamento, pixelização e corte de rebarbas são frequentemente usadas no pré-processamento e pós-processamento de imagens, tornando-se um poderoso complemento às técnicas de aprimoramento de imagens.

Operações básicas de processamento morfológico: erosão, expansão, operação de abertura, operação de fechamento, hit and miss, extração de esqueleto, etc. Por exemplo, a erosão aumenta as áreas escuras e a dilatação aumenta as áreas claras.
insira a descrição da imagem aqui

Execute a operação de abertura ( a operação de abertura pode tornar o contorno da imagem suave, e também pode desconectar as conexões estreitas e eliminar as rebarbas finas . Esta operação abre caminho para uma extração mais precisa do contorno da placa de licença posteriormente):

Link de detalhes da operação
aberta A operação aberta é principalmente em preto e branco, e a área preta se torna maior. Remova pontos de informação inúteis.
A operação fechada é principalmente comer preto para nada, e a área branca torna-se maior. Aumente a área de realce branco.
insira a descrição da imagem aqui

Combine a imagem original em tons de cinza e a imagem morfológica em uma imagem para operações subsequentes de segmentação de limiar:
insira a descrição da imagem aqui

Segmentação de limite + detecção de borda

A segmentação por limiar é um algoritmo comum para segmentar imagens diretamente e depende do valor de cinza dos pixels da imagem. Correspondendo a uma única imagem de destino, apenas um limite pode ser selecionado para dividir a imagem em duas categorias: destino e plano de fundo. Isso é chamado de segmentação de limite único; se a imagem de destino for complexa, vários limites podem ser selecionados para separar a área de destino e fundo na imagem. Ela é dividida em várias partes, o que é chamado de segmentação multi-limiar. Neste momento, também é necessário distinguir os alvos da imagem nos resultados da detecção e identificar exclusivamente cada área alvo da imagem a ser distinguida.

Com a limiarização, esperamos conseguir separar nosso objeto de pesquisa do background. A imagem é dividida em várias regiões específicas com propriedades únicas, cada região representa uma coleção de pixels e cada coleção representa um objeto.

Usando o processamento de limite Ostu : Ao usar a função cv.threshold() para processamento de limite, você precisa personalizar um limite e usar esse limite como base para o processamento de limite de imagem. A OTSU pode nos ajudar a atravessar todos os limites possíveis para encontrar o melhor.

insira a descrição da imagem aqui

Faça suavização de execução fechada (sem detecção de borda após segmentação de limite)

Adicione detecção de borda após segmentação de limite: (use a detecção de borda inteligente aqui)
insira a descrição da imagem aqui
e execute uma operação de fechamento para aumentar a área de realce branco:
insira a descrição da imagem aqui
execute uma operação de abertura para remover a parte branca inútil e preencher a lacuna:
insira a descrição da imagem aqui
Por fim, execute a expansão para preencher a lacuna novamente e aumente a parte de destaque branco:
insira a descrição da imagem aqui
Cada contorno pode ser considerado como um conjunto ordenado de pontos (pixels), e agora queremos extrair os contornos dessas áreas brancas. (desenhe a imagem original com o contorno)
insira a descrição da imagem aqui
Agora que temos o contorno, precisamos filtrar o contorno onde a placa está localizada (você pode ver que a área onde a placa está localizada é um retângulo), já que a proporção da largura e altura da placa de licença é fixa (a altura e a largura da placa de licença são fixas, 90mm e 45mm respectivamente), de acordo com essa característica geométrica, filtramos e depois usamos as linhas verdes para selecionar a placa de licença obtida frame e, ao mesmo tempo, interceptar a placa de licença para a próxima segmentação de caracteres.
insira a descrição da imagem aqui
Localize o código completo da placa:

import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
#########该函数能够读取磁盘中的图片文件,默认以彩色图像的方式进行读取
def imread_photo(filename, flags=cv2.IMREAD_COLOR):
    return cv2.imread(filename, flags)


##############这个函数的作用就是来调整图像的尺寸大小,当输入图像尺寸的宽度大于阈值(默认1000),我们会将图像按比例缩小#######
def resize_photo(imgArr,MAX_WIDTH = 1000):
    img = imgArr
    rows, cols= img.shape[:2]     #获取输入图像的高和宽即第0列和第1列
    if cols >  MAX_WIDTH:
        change_rate = MAX_WIDTH / cols
        img = cv2.resize(img ,( MAX_WIDTH ,int(rows * change_rate) ), interpolation = cv2.INTER_AREA)
    return img

# ################高斯平滑###############
#我们首先会对图像水平方向进行卷积,然后再对垂直方向进行卷积,其中sigma代表高斯卷积核的标准差
def gaussBlur(image,sigma,H,W,_boundary = 'fill', _fillvalue = 0):
    #水平方向上的高斯卷积核
    gaussKenrnel_x = cv2.getGaussianKernel(sigma,W,cv2.CV_64F)
    #进行转置
    gaussKenrnel_x = np.transpose(gaussKenrnel_x)
    #图像矩阵与水平高斯核卷积
    gaussBlur_x = signal.convolve2d(image,gaussKenrnel_x,mode='same',boundary=_boundary,fillvalue=_fillvalue)
    #构建垂直方向上的卷积核
    gaussKenrnel_y = cv2.getGaussianKernel(sigma,H,cv2.CV_64F)
    #图像与垂直方向上的高斯核卷积核
    gaussBlur_xy = signal.convolve2d(gaussBlur_x,gaussKenrnel_y,mode='same',boundary= _boundary,fillvalue=_fillvalue)
    return gaussBlur_xy


def chose_licence_plate(contours, Min_Area=2000):
    temp_contours = []
    for contour in contours:
        if cv2.contourArea(contour) > Min_Area:
            temp_contours.append(contour)
    car_plate = []
    for temp_contour in temp_contours:
        rect_tupple = cv2.minAreaRect(temp_contour)
        rect_width, rect_height = rect_tupple[1]
        if rect_width < rect_height:
            rect_width, rect_height = rect_height, rect_width
        aspect_ratio = rect_width / rect_height
        # 车牌正常情况下宽高比在2 - 5.5之间
        if aspect_ratio > 2 and aspect_ratio < 5.5:
            car_plate.append(temp_contour)
            rect_vertices = cv2.boxPoints(rect_tupple)
            rect_vertices = np.int0(rect_vertices)
    return car_plate

def license_segment( car_plates ):
    if len(car_plates)==1:
        for car_plate in car_plates:
            row_min,col_min = np.min(car_plate[:,0,:],axis=0)
            row_max, col_max = np.max(car_plate[:, 0, :], axis=0)
            cv2.rectangle(img, (row_min,col_min), (row_max, col_max), (0,255,0), 2)
            card_img = img[col_min:col_max,row_min:row_max,:]
            cv2.imshow("img", img)
        cv2.imwrite( "card_img.png", card_img)
        cv2.imshow("card_img.png", card_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    return  "card_img.png"


if __name__ == "__main__":

    img = imread_photo("car_test.png")  # 默认读取彩色图片
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 将彩色图片转换为灰色图片,灰色图像更便于后续处理。
    rgray_img = resize_photo(gray_img)

    # 高斯平滑
    blurImage = gaussBlur(gray_img, 5, 400, 400, 'symm')
    #对bIurImage进行灰度级显示
    blurImage = np.round(blurImage)
    blurImage = blurImage.astype(np.uint8)

    kernel = np.ones((10, 10), np.uint8)
    #开运算
    img_opening = cv2.morphologyEx(blurImage, cv2.MORPH_OPEN, kernel)
    # cv2.imshow("GaussBlur_gray_img", blurImage)
    # cv2.imshow("xingtai_gray_img", img_opening)


    #将两幅图像合成为一幅图像
    img_opening = cv2.addWeighted(rgray_img, 1, img_opening, -1, 0)
    # cv2.imshow("hecheng_gray_img", img_opening)



    #阈值分割
    t, result_img = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    # cv2.imshow("yuzhi_gray_img",result_img)
    #canny边缘检测
    img_edge = cv2.Canny(result_img, 100, 200)
    # cv2.imshow("bianyuan_gray_img", img_edge)
    #闭运算来填充白色物体内细小黑色空洞的区域并平滑其边界
    kernel1 = np.ones((18, 18), np.uint8)
    img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel1)
    # cv2.imshow("biyunsuan", img_edge1)

    kernel2 = np.ones((10, 10), np.uint8)
    img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel2)
    # cv2.imshow("kaiyunsuan", img_edge2)

    kernel = np.ones((20, 20), np.uint8)
    img_dilate = cv2.dilate(img_edge2, kernel)  # 膨胀
    cv2.imshow("dilate", img_dilate)  # 显示图片

    # #查找图像边缘整体形成的矩形区域, contours是找到的多个轮廓
    image, contours, hierarchy = cv2.findContours(img_dilate,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    # cv2.imshow("xunzhao", hierarchy)

    draw_img = img.copy()
    result = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
    # 画出带有轮廓的原始图片
    cv2.imshow('ret',result)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    car_plates = chose_licence_plate(contours)
    card_img = license_segment(car_plates)

Acho que você gosta

Origin blog.csdn.net/weixin_45942265/article/details/124076650
Recomendado
Clasificación