OpenCV+Python 식별 번호판 과 문자 분할 의 실현
자동차 번호 검 사 는 크게 네 부분 으로 나 눌 필요 가 있다.
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()
운행 효 과 는 그림 과 같다.자동차 번호판 포 지 셔 닝 및 처리
자동차 번호판 의 분할 은 그림 과 같다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Visual Studio 2017에서 OpenCV 템플릿 프로젝트 만들기・Windows 7 Professional 64bit ・Visual Studio 2017 Version 15.9.14 · OpenCV 3.4.1 OpenCV의 도입 방법 등은 아래를 참조하십시오. Visual Stu...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.