OpenCV+Python 식별 번호판 과 문자 분할 의 실현

이 글 은 주로 python 언어 와 OpenCV 라 이브 러 리(cv2)를 바탕 으로 자동차 번호판 구역 식별 과 문자 분할 을 진행 합 니 다.시작 하기 전에 python 에 opencv 를 설치 하 는 환경 에 대해 소개 하지 않 고 자체 적 으로 설정 할 수 있 습 니 다!
자동차 번호 검 사 는 크게 네 부분 으로 나 눌 필요 가 있다.
1.차량 이미지 가 져 오기
2.자동차 번호판 위치 확인,
3.자동차 번호판 문자 분할
4.자동차 번호판 문자 인식
구체 적 소개
자동차 번호판 의 포 지 셔 닝 에 필요 한 것 은 그림 의 이치 가 흑백 으로 변 한 후에 canny 가장자리 검 측 을 한 후에 여러 번 연산 과 폐 연산 을 하여 작은 블록 을 없 애 는 구역 에 사용 하고 큰 구역 을 유지 한 후에 cv2.rectangle 으로 사각형 상 자 를 선택 하여 자동차 번호판 의 위 치 를 정 하 는 것 이다.
자동차 번호판 문자 의 분할 전에 준비 해 야 할 것 은 자동차 번호판 부분 만 보존 하고 다른 부분 을 모두 검은색 배경 으로 바 꾸 는 것 이다.여기 서 저 는 cv2.grabCut 방법 을 사용 하여 그림 을 전경 과 배경 으로 나 눌 수 있 습 니 다.분할 이 완 료 된 후에 이 치 를 거 쳐 흑백 그림 으로 바 꾼 후에 문자 분할 을 할 수 있다.그림 에 검은색 과 흰색 픽 셀 만 있 기 때문에 그림 의 흰색 픽 셀 과 검은색 픽 셀 을 통 해 문 자 를 분할 해 야 합 니 다.각 줄 의 검은색 과 흰색 픽 셀 값 의 위 치 를 판단 하여 문 자 를 찾 는 것 이다.
구체 적 인 절 차 는 다음 과 같다.
1.그 레이스 케 일 변환:컬러 그림 을 그 레이스 케 일 이미지 로 변환 합 니 다.흔히 볼 수 있 는 R=G=B=픽 셀 평균 값 입 니 다.
2.가우스 평활 과 중간 값 필터:소음 제거.
3.Sobel 연산 자:그림 가장자리 윤곽,X 방향 과 Y 방향 제곱 과 굽 을 추출 합 니 다.
4.이치 화 처리:그림 을 흑백 두 가지 색 으로 변환 합 니 다.보통 픽 셀 이 127 보다 크 면 255 로 설정 하고 0 보다 작 습 니 다.
5.팽창 과 세분 화:이미지 의 윤곽 을 확대 하고 하나의 구역 으로 전환 하 며 이런 구역 에는 자동차 번호판 이 포함 되 어 있다.
6.알고리즘 을 통 해 적당 한 번호판 위 치 를 선택 하고 작은 구역 을 걸 러 내 거나 파란색 바닥 을 찾 습 니 다.
7.번호판 위치 표시
8.이미지 절단 과 식별
코드 로 구현:

# -*- coding: utf-8 -*-
"""
@email:[email protected]
@author: cuiran
"""
import cv2
import numpy as np
from PIL import Image
import os.path
from skimage import io,data
def stretch(img):
 '''
       
 '''
 maxi=float(img.max())
 mini=float(img.min())

 for i in range(img.shape[0]):
  for j in range(img.shape[1]):
   img[i,j]=(255/(maxi-mini)*img[i,j]-(255*mini)/(maxi-mini))

 return img

def dobinaryzation(img):
 '''
        
 '''
 maxi=float(img.max())
 mini=float(img.min())

 x=maxi-((maxi-mini)/2)
 #   ,    ret            thresh
 ret,thresh=cv2.threshold(img,x,255,cv2.THRESH_BINARY)
 #           
 return thresh

def find_rectangle(contour):
 '''
       
 '''
 y,x=[],[]

 for p in contour:
  y.append(p[0][0])
  x.append(p[0][1])

 return [min(y),min(x),max(y),max(x)]

def locate_license(img,afterimg):
 '''
      
 '''
 img,contours,hierarchy=cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

 #         
 block=[]
 for c in contours:
  #            ,            
  r=find_rectangle(c)
  a=(r[2]-r[0])*(r[3]-r[1]) #  
  s=(r[2]-r[0])*(r[3]-r[1]) #   

  block.append([r,a,s])
 #       3   
 block=sorted(block,key=lambda b: b[1])[-3:]

 #                 
 maxweight,maxindex=0,-1
 for i in range(len(block)):
  b=afterimg[block[i][0][1]:block[i][0][3],block[i][0][0]:block[i][0][2]]
  #BGR HSV
  hsv=cv2.cvtColor(b,cv2.COLOR_BGR2HSV)
  #       
  lower=np.array([100,50,50])
  upper=np.array([140,255,255])
  #        
  mask=cv2.inRange(hsv,lower,upper)
  #    
  w1=0
  for m in mask:
   w1+=m/255

  w2=0
  for n in w1:
   w2+=n

  #         
  if w2>maxweight:
   maxindex=i
   maxweight=w2

 return block[maxindex][0]

def find_license(img):
 '''
      
 '''
 m=400*img.shape[0]/img.shape[1]

 #    
 img=cv2.resize(img,(400,int(m)),interpolation=cv2.INTER_CUBIC)

 #BGR       
 gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

 #    
 stretchedimg=stretch(gray_img)

 '''     ,      '''
 r=16
 h=w=r*2+1
 kernel=np.zeros((h,w),np.uint8)
 cv2.circle(kernel,(r,r),r,1,-1)
 #   
 openingimg=cv2.morphologyEx(stretchedimg,cv2.MORPH_OPEN,kernel)
 #     ,       cv2.absdiff('  1','  2')
 strtimg=cv2.absdiff(stretchedimg,openingimg)

 #     
 binaryimg=dobinaryzation(strtimg)

 #canny    
 canny=cv2.Canny(binaryimg,binaryimg.shape[0],binaryimg.shape[1])

 '''      ,       ,      '''
 #     
 kernel=np.ones((5,19),np.uint8)
 closingimg=cv2.morphologyEx(canny,cv2.MORPH_CLOSE,kernel)

 #     
 openingimg=cv2.morphologyEx(closingimg,cv2.MORPH_OPEN,kernel)

 #       
 kernel=np.ones((11,5),np.uint8)
 openingimg=cv2.morphologyEx(openingimg,cv2.MORPH_OPEN,kernel)

 #     ,      
 rect=locate_license(openingimg,img)

 return rect,img

def cut_license(afterimg,rect):
 '''
       
 '''
 #        
 rect[2]=rect[2]-rect[0]
 rect[3]=rect[3]-rect[1]
 rect_copy=tuple(rect.copy())
 rect=[0,0,0,0]
 #    
 mask=np.zeros(afterimg.shape[:2],np.uint8)
 #            13*5,     1,      
 bgdModel=np.zeros((1,65),np.float64)
 #      
 fgdModel=np.zeros((1,65),np.float64)
 #    
 cv2.grabCut(afterimg,mask,rect_copy,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
 mask2=np.where((mask==2)|(mask==0),0,1).astype('uint8')
 img_show=afterimg*mask2[:,:,np.newaxis]

 return img_show

def deal_license(licenseimg):
 '''
        
 '''
 #        
 gray_img=cv2.cvtColor(licenseimg,cv2.COLOR_BGR2GRAY)

 #         
 kernel=np.ones((3,3),np.float32)/9
 gray_img=cv2.filter2D(gray_img,-1,kernel)

 #     
 ret,thresh=cv2.threshold(gray_img,120,255,cv2.THRESH_BINARY)

 return thresh


def find_end(start,arg,black,white,width,black_max,white_max):
 end=start+1
 for m in range(start+1,width-1):
  if (black[m] if arg else white[m])>(0.98*black_max if arg else 0.98*white_max):
   end=m
   break
 return end


if __name__=='__main__':
 img=cv2.imread('test_images/car001.jpg',cv2.IMREAD_COLOR)
 #     
 rect,afterimg=find_license(img)

 #     
 cv2.rectangle(afterimg,(rect[0],rect[1]),(rect[2],rect[3]),(0,255,0),2)
 cv2.imshow('afterimg',afterimg)

 #       
 cutimg=cut_license(afterimg,rect)
 cv2.imshow('cutimg',cutimg)

 #        
 thresh=deal_license(cutimg)
 cv2.imshow('thresh',thresh)
 cv2.waitKey(0)

 #    
 '''
        
 '''
 #        
 white=[]
 black=[]
 height=thresh.shape[0] #263
 width=thresh.shape[1] #400
 #print('height',height)
 #print('width',width)
 white_max=0
 black_max=0
 #            
 for i in range(width):
  line_white=0
  line_black=0
  for j in range(height):
   if thresh[j][i]==255:
    line_white+=1
   if thresh[j][i]==0:
    line_black+=1
  white_max=max(white_max,line_white)
  black_max=max(black_max,line_black)
  white.append(line_white)
  black.append(line_black)
  print('white',white)
  print('black',black)
 #arg true      ,False     
 arg=True
 if black_max<white_max:
  arg=False

 n=1
 start=1
 end=2
 s_width=28
 s_height=28
 while n<width-2:
  n+=1
  #              0.05       0.95     
  if(white[n] if arg else black[n])>(0.02*white_max if arg else 0.02*black_max):
   start=n
   end=find_end(start,arg,black,white,width,black_max,white_max)
   n=end
   if end-start>5:
    cj=thresh[1:height,start:end]

    # new_image = cj.resize((s_width,s_height),Image.BILINEAR)
    # cj=cj.reshape(28, 28)
    print("result/%s.jpg" % (n))
    #        by cayden
    # cj.save("result/%s.jpg" % (n))
    infile="result/%s.jpg" % (n)
    io.imsave(infile,cj)

    # im = Image.open(infile)
    # out=im.resize((s_width,s_height),Image.BILINEAR)
    # out.save(infile)

    cv2.imshow('cutlicense',cj)
    cv2.waitKey(0)


 cv2.waitKey(0)
 cv2.destroyAllWindows()
운행 효 과 는 그림 과 같다.
자동차 번호판 포 지 셔 닝 및 처리

자동차 번호판 의 분할 은 그림 과 같다.

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기