TShopping
標題:
OpenCV圖像識別:車牌定位算法源碼,Python語言實現
[打印本頁]
作者:
woff
時間:
2020-12-18 16:18
標題:
OpenCV圖像識別:車牌定位算法源碼,Python語言實現
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):
'''
定位車牌號碼
'''
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])
#選出面積最大的三個區域
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 mask:
w2 += n
#選出最大權值的區域
if w2.all() > maxweight:
maxindex = i
maxweight = w2
return block[maxindex][0]
def find_license(img):
'''
預處理函數
'''
m = 300 * img.shape[0]/img.shape[1]
#壓縮圖像
img = cv2.resize(img, (300, 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')
strting = cv2.absdiff(stretchedimg, openingimg)
#圖像二位元化
binaryimg = dobinaryzation(strting)
#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((5,19), np.uint8)
closingimg = cv2.morphologyEx(openingimg, cv2.MORPH_CLOSE, kernel)
#清除小區域,定位車牌
rect = locate_license(openingimg, img)
return rect, img
def cut_licence(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)
#print ('mask',mask)
#創建前景模型 大小只能13*5. 行數只能為1. 單通道浮點型
bgdModel = np.zeros((1, 65), np.float64)
#cv2.imshow('bgdModel',bgdModel)
#建前景模型
fgdModel = np.zeros((1, 65), np.float64)
#cv2.imshow('fgdModel',fgdModel)
#分割圖像
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, block, white, width, black_max, white_max):
end = start + 1
for m in range(start+1, width-1):
if (block[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('a.jpg', cv2.IMREAD_COLOR)
#預處理圖像
rect, afterimg = find_license(img)
#cv2.imshow('img',img)
#框出車牌號碼
#cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)畫出矩形
cv2.rectangle(afterimg, (rect[0], rect[1]), (rect[2], rect[3]), (0, 255, 0),2)
cv2.imshow('afterimg', afterimg)
#分割車牌與背景
cutimg = cut_licence(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)
#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))
#保存分割的圖片
#cj.save("result%s.jpg" % (n))
#infile = "result%s.jpg" % (n)
#io.imsave(infile, cj)
print(n)
#im = IMage.open(infile)
#out = im.resize((s_width, s_height), Image.BILINEAR)
#out.save(infile)
cv2.imshow('cutlincese', cj)
cv2.waitKey(0)
cv2.waitKey(0)
cv2.destroyAllWindows()
複製代碼
參考文章
https://www.itdaan.com/tw/9574009e55291df19eabb41ed6569b99
https://www.itread01.com/content/1556791200.html
文章出處
網頁設計,網站架設 ,網路行銷,網頁優化,SEO -
NetYea 網頁設計
歡迎光臨 TShopping (http://www.tshopping.com.tw/)
Powered by Discuz! X3.2