OpenCV(项目)车牌识别3 -- 模板匹配
目錄
一、基礎理論
1、思想
2、大致過程
二、詳細過程
1、首先需要模板庫
2、得到模板
3、原圖限定大小
4、模板匹配
5、匹配所有子文件夾,保存最佳得分(最匹配項)
三、大致過程(細分類,節省時間)
1、漢字匹配
?2、英文字符匹配
3、數字/英文匹配
?4、顯示
模板匹配總代碼
參考資料
一、基礎理論
1、思想
把提取到的每一張字符,和模板庫中的所有字符進行對比。
2、大致過程
先拿到模板庫,把模板和待匹配的圖像大小限制一致,匹配每一張子模板圖,匹配每張模板圖匹配后都會有一個得分,得分最高的最相近。再把每個子文件夾最高得分對比,用index找到最高的那個子文件夾下標,得到模板。
二、詳細過程
1、首先需要模板庫
模板庫下載鏈接1:(推薦)
https://download.csdn.net/download/great_yzl/21974008
模板庫下載鏈接2:(不推薦)
http://www.zengqiang.club/blog/34
一個大文件夾下包含很多子文件夾:
?
?每一個子文件夾內包含該字符的一系列模板(為了更精確,犧牲了不少時間):
2、得到模板
# 路徑path = 'Template/' + List[i] + '/' + filename# 1、得到模板template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1) #彩(類似imread)gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY) #灰ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #二值cv.imshow('template', template)cv.waitKey(0)
3、原圖限定大小
# 2、原圖限定大小(和模板相似)h, w = template.shapeimage = cv.resize(image, (w, h))cv.imshow('image_', image)cv.waitKey(0)
4、模板匹配
??按照名稱列表的方式,遍歷模板庫的所有子文件夾、子文件夾內的所有子圖。
# 3、模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)
?
5、匹配所有子文件夾,保存最佳得分(最匹配項)
匹配所有子文件夾的子圖:?
# 模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)
?每個文件夾的最佳得分:
# 一個文件夾的最高得分(得分越高,匹配度越高)best_score.append(max(score))# 根據所有文件夾的最佳得分確定下標index = best_score.index(max(best_score))+34
三、大致過程(細分類,節省時間)
由于第一個必定是漢字,第二個必定是英文字符,后面的必定是英文字符/數字,我們在那里只需要做相應的判斷即可。節約了很多時間。
1、漢字匹配
# (1) 漢字(首個位置只能是漢字(省))(為了節約時間)if con == 0:# 遍歷34——65文件夾(漢字)for i in range(34,65):# 單個圖片的得分score = []ForderPath = 'Template/' + List[i]# 遍歷單文件夾(每一個文件匹配)for filename in os.listdir(ForderPath):# 路徑path = 'Template/' + List[i] + '/' + filename# 1、得到模板template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1) #彩(類似imread)gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY) #灰ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #二值# 2、原圖限定大小(和模板相似)h, w = template.shapeimage = cv.resize(image, (w, h))cv.imshow('image_', image)cv.waitKey(0)# 3、模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)# 4、保存子文件夾的最高得分(得分越高,匹配度越高)best_score.append(max(score))# 5、根據所有文件夾的最佳得分確定下標index = best_score.index(max(best_score))+34
?
?2、英文字符匹配
# (2) 字母(第二個位置只能為字母)elif con == 1:# 遍歷10~34文件夾(字母文件夾)for i in range(10,34):# 單個圖片的得分score = []ForderPath = 'Template/' + List[i]# 遍歷單文件夾(每一個文件匹配)for filename in os.listdir(ForderPath):# 路徑path = 'Template/' + List[i] + '/' + filename# 模板template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1) #彩(類似imread)gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY) #灰ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #二值h, w = template.shapeimage = cv.resize(image, (w, h))# 模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)# 一個文件夾的最高得分(得分越高,匹配度越高)best_score.append(max(score))# 根據所有文件夾的最佳得分確定下標index = best_score.index(max(best_score)) + 10
3、數字/英文匹配
# (3) 數字+字母else:# 遍歷0~34文件夾(數字+字母)for i in range(34):# 單個圖片的得分score = []ForderPath = 'Template/' + List[i]# 遍歷單文件夾(每一個文件匹配)for filename in os.listdir(ForderPath):# 路徑path = 'Template/' + List[i] + '/' + filename# 模板template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1) #彩(類似imread)gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY) #灰ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #二值h, w = template.shapeimage = cv.resize(image, (w, h))# 模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)# 一個文件夾的最高得分(得分越高,匹配度越高)best_score.append(max(score))# 根據所有文件夾的最佳得分確定下標index = best_score.index(max(best_score))
?
?4、顯示
在切割字符函數的尾部,所有字符切割完、立刻進行模板匹配,同一張車牌所有字符切割完畢后,進行顯示。?
# 顯示識別結果(圖像)Show_Result_Image()
# 顯示識別結果(圖像)
def Show_Result_Image():p = image_rect[0], image_rect[1]w, h = image_rect[2] , image_rect[3]# 框出車牌cv.rectangle(img, (p[0],p[1]), (p[0]+w, p[1]+h), (0,0,255), 2)# 輸出字符(中文)result = Text(img, str(final_result), p, (255,0,0), 16)cv.imshow('result-%d'%count, result)# cv.waitKey(0)
?
模板匹配總代碼
# 顯示文字(中文)(用的PIL,RGB正常顯示,即和opencv的RGB相反)
def Text(image, text, p, color, size):# cv2讀取圖片# BGR轉RGB:cv2和PIL中顏色的hex碼的儲存順序不同cv2_image = cv.cvtColor(image, cv.COLOR_RGB2BGR)pil_image = Image.fromarray(cv2_image)# PIL圖片上打印漢字draw = ImageDraw.Draw(pil_image) # 圖片上打印font = ImageFont.truetype("./simhei.ttf", size, encoding="utf-8") # 參數1:字體文件路徑,參數2:字體大小draw.text((p[0]-60, p[1]-20), text, color, font=font)# PIL圖片轉cv2 圖片cv2_result = cv.cvtColor(np.array(pil_image), cv.COLOR_RGB2BGR)# cv2.imshow("圖片", cv2_result) # 漢字窗口標題顯示亂碼# cv.imshow("photo", cv2_result) # 輸出漢字return cv2_result# 顯示識別結果(文字)
def Show_Result_Words(index):print(List[index])final_result.append(List[index])print(final_result)# 顯示識別結果(圖像)
def Show_Result_Image():p = image_rect[0], image_rect[1]w, h = image_rect[2] , image_rect[3]# 框出車牌cv.rectangle(img, (p[0],p[1]), (p[0]+w, p[1]+h), (0,0,255), 2)# 輸出字符(中文)result = Text(img, str(final_result), p, (255,0,0), 16)cv.imshow('result-%d'%count, result)# cv.waitKey(0)# 三、模板匹配
# 原圖和模板進行對比,越匹配,得分越大
def Template_Match(image):# 單文件夾內的最佳得分best_score = []# 遍歷所有文件夾(每一個文件夾匹配)# (1) 漢字(首個位置只能是漢字(省))(為了節約時間)if con == 0:# 遍歷34——65文件夾(漢字)for i in range(34,65):# 單個圖片的得分score = []ForderPath = 'Template/' + List[i]# 遍歷單文件夾(每一個文件匹配)for filename in os.listdir(ForderPath):# 路徑path = 'Template/' + List[i] + '/' + filename# 1、得到模板template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1) #彩(類似imread)gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY) #灰ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #二值# 2、原圖限定大小(和模板相似)h, w = template.shapeimage = cv.resize(image, (w, h))# 3、模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)# 4、保存子文件夾的最高得分(得分越高,匹配度越高)best_score.append(max(score))# 5、根據所有文件夾的最佳得分確定下標index = best_score.index(max(best_score))+34# (2) 字母(第二個位置只能為字母)elif con == 1:# 遍歷10~34文件夾(字母文件夾)for i in range(10,34):# 單個圖片的得分score = []ForderPath = 'Template/' + List[i]# 遍歷單文件夾(每一個文件匹配)for filename in os.listdir(ForderPath):# 路徑path = 'Template/' + List[i] + '/' + filename# 模板template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1) #彩(類似imread)gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY) #灰ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #二值h, w = template.shapeimage = cv.resize(image, (w, h))# 模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)# 一個文件夾的最高得分(得分越高,匹配度越高)best_score.append(max(score))# 根據所有文件夾的最佳得分確定下標index = best_score.index(max(best_score)) + 10# (3) 數字+字母else:# 遍歷0~34文件夾(數字+字母)for i in range(34):# 單個圖片的得分score = []ForderPath = 'Template/' + List[i]# 遍歷單文件夾(每一個文件匹配)for filename in os.listdir(ForderPath):# 路徑path = 'Template/' + List[i] + '/' + filename# 模板template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1) #彩(類似imread)gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY) #灰ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) #二值h, w = template.shapeimage = cv.resize(image, (w, h))# 模板匹配,得到得分(匹配度越高,得分越大)result = cv.matchTemplate(image, template, cv.TM_CCOEFF)score.append(result[0][0]) #得分(每張模板圖)# 一個文件夾的最高得分(得分越高,匹配度越高)best_score.append(max(score))# 根據所有文件夾的最佳得分確定下標index = best_score.index(max(best_score))# 顯示結果(文字)(每識別一個顯示一次)Show_Result_Words(index)
????????總的來講,為了追求較高的精度,匹配時間較長, 一張車牌約20秒。這里的模板匹配不算非常的精確,并且耗時嚴重,已經逐漸被淘汰了,這里只是作為學習用途,沒有太高的實際應用價值。(后期進軍深度學習/機器學習,可能會對這些進行優化)。有什么好的建議大家可以提出來,共同進步,謝謝~
參考資料
https://www.bilibili.com/video/BV1yg4y187kU?p=3
總結
以上是生活随笔為你收集整理的OpenCV(项目)车牌识别3 -- 模板匹配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 奇葩错误:cv.imread()读取失败
- 下一篇: OpenCV(项目)车牌识别4 -- 总