基於OpenCV和Python的車牌提取和字元分割
這是一篇介紹基於 OpenCV 和 Python 實現車牌提取專案思路和原始碼的文章,本文涉及一些人工智慧和影像識別技術,具體而言,涉及到關於車牌號碼識別的研究(車牌提取和字元分割),網上查詢到的方案有 tensorflow 和opencv,opencv 也是比較成熟的方案,先從簡單的開始,以下是關於使用opencv實現車牌號碼提取的部分。
1 車牌提取
1.1 實現思路
- 讀取彩色的圖片
- 轉換為灰度圖
- 高斯模糊
- Sobel運算元進行邊緣檢測
- 影像二值化
- 閉操作(腐蝕和擴張)
- 迴圈找到所有的輪廓
- 判斷車牌區域
1.2 原圖
1.3 程式碼詳解
1.3.1 匯入包庫
import cv2 as cv
import matplotlib.pyplot as plt
1.3.2 讀取彩色的圖片
cv.imread("E:/car.png")
1.3.3 轉換為灰度圖
cv.cvtColor(img, cv.COLOR_BGR2GRAY)
1.3.4 高斯模糊
通過高斯模糊,可以去除部分的干擾,讓識別更加準確。
cv.GaussianBlur(img1,(5,5),10)
1.3.5 用Sobel運算元進行邊緣檢測
便於接下來提取輪廓
cv.Sobel(img2,cv.CV_8U,1,0,ksize=1)
cv.Canny(img3,250,100)
1.3.6 進行二值化處理
將影像上的畫素點的灰度值設定為0或255,影像呈現出明顯的只有黑和白。
cv.threshold(img4,0,255,cv.THRESH_BINARY)
1.3.7 閉操作
依次進行腐蝕和擴張,這一步操作可以將目標區域連成一個整體,便於後續輪廓的提取。
cv.getStructuringElement(cv.MORPH_RECT,(43,33))
cv.dilate(img5,kernel)
1.3.8 查詢輪廓
i,j = cv.findContours(img6,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
1.3.9 判斷車牌區域
result = None
for i1 in i:
x,y,w,h = cv.boundingRect(i1)
if w>2*h:
print(1)
plt.imshow(img[y:y+h,x:x+w])
plt.show()
result = img[y:y+h,x:x+w]
1.4 總觀程式碼
import cv2 as cv
import matplotlib.pyplot as plt
# 讀取彩色的圖片
img = cv.imread("E:/car.png")
plt.imshow(img)
plt.show()
# 轉換為灰度圖
img1 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
plt.imshow(img1)
plt.show()
# 用Sobel進行邊緣檢測
# # 高斯模糊
img2 = cv.GaussianBlur(img1,(5,5),10)
plt.imshow(img2)
plt.show()
# Laplacian進行邊緣檢測
img3 = cv.Sobel(img2,cv.CV_8U,1,0,ksize=1)
plt.imshow(img3)
plt.show()
img4 = cv.Canny(img3,250,100)
plt.imshow(img4)
plt.show()
# 進行二值化處理
i,img5 = cv.threshold(img4,0,255,cv.THRESH_BINARY)
plt.imshow(img5)
plt.show()
# 可以侵蝕和擴張
kernel = cv.getStructuringElement(cv.MORPH_RECT,(43,33))
img6 = cv.dilate(img5,kernel)
plt.imshow(img6)
plt.show()
# # 迴圈找到所有的輪廓
i,j = cv.findContours(img6,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
result = None
for i1 in i:
x,y,w,h = cv.boundingRect(i1)
if w>2*h:
print(1)
plt.imshow(img[y:y+h,x:x+w])
plt.show()
result = img[y:y+h,x:x+w]
1.5 最終實現效果
2 車牌識別之字元分割
前面對這牌提取做個詳細描述,與此相類似,車牌的字元分割也是很重要的一部分,字元分割的思想在其他專案中同樣有很重要的作用。因此有必要針對字元分割的思路和實現過程做一個記錄。
2.1 實現思路
總的來說,是基於畫素直方圖的字元分割實現的:首先對圖片進行二值化處理,統計水平方向和豎直方向上各行各列的黑色畫素的個數,根據畫素的特點確定分割位置,進而完成字元分割。
2.2 原圖
2.3 程式碼詳解
2.3.1 匯入包庫
import cv2
from matplotlib import pyplot as plt
2.3.2 讀取影像,並把影像轉換為灰度影像並顯示
cv2.imread('E:/3.png') # 讀取圖片
cv2.cvtColor(img_, cv2.COLOR_BGR2GRAY) # 轉換了灰度化
2.3.3 將灰度影像二值化,設定閾值是100
cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV)
2.3.4 分割字元
水平方向:統計每一行黑色畫素數量n,並記錄。可以根據每一行黑色畫素的數目來確定分割的起始和終止;由圖可知,當 n減小到一定閾值時,為字元的邊緣;
豎直方向:同理,統計每一列的黑色畫素數量v,並記錄。可以可以根據每一列黑色畫素的數目的變化來確定分割的起始和終止。
white = [] # 記錄每一列的白色畫素總和
black = [] # ..........黑色.......
height = img_thre.shape[0]
width = img_thre.shape[1]
white_max = 0
black_max = 0
# 計算每一列的黑白色畫素總和
for i in range(width):
s = 0 # 這一列白色總數
t = 0 # 這一列黑色總數
for j in range(height):
if img_thre[j][i] == 255:
s += 1
if img_thre[j][i] == 0:
t += 1
white_max = max(white_max, s)
black_max = max(black_max, t)
white.append(s)
black.append(t)
2.3.5 分割影像
def find_end(start_):
end_ = start_ + 1
for m in range(start_ + 1, width - 1):
if (black[m] if arg else white[m]) > (0.95 * black_max if arg else 0.95 * white_max): # 0.95這個引數請多調整,對應下面的0.05(針對畫素分佈調節)
end_ = m
break
return end_
2.4 總觀程式碼
import cv2
from matplotlib import pyplot as plt
## 根據每行和每列的黑色和白色畫素數進行圖片分割。
# 1、讀取影像,並把影像轉換為灰度影像並顯示
img_ = cv2.imread('E:/3.png') # 讀取圖片
img_gray = cv2.cvtColor(img_, cv2.COLOR_BGR2GRAY) # 轉換了灰度化
# cv2.imshow('gray', img_gray) # 顯示圖片
# cv2.waitKey(0)
# 2、將灰度影像二值化,設定閾值是100
ret, img_thre = cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV)
# cv2.imshow('white_black image', img_thre) # 顯示圖片
# cv2.waitKey(0)
# 4、分割字元
white = [] # 記錄每一列的白色畫素總和
black = [] # ..........黑色.......
height = img_thre.shape[0]
width = img_thre.shape[1]
white_max = 0
black_max = 0
# 計算每一列的黑白色畫素總和
for i in range(width):
s = 0 # 這一列白色總數
t = 0 # 這一列黑色總數
for j in range(height):
if img_thre[j][i] == 255:
s += 1
if img_thre[j][i] == 0:
t += 1
white_max = max(white_max, s)
black_max = max(black_max, t)
white.append(s)
black.append(t)
# print(s)
# print(t)
arg = False # False表示白底黑字;True表示黑底白字
if black_max > white_max:
arg = True
# 分割影像
def find_end(start_):
end_ = start_ + 1
for m in range(start_ + 1, width - 1):
if (black[m] if arg else white[m]) > (0.95 * black_max if arg else 0.95 * white_max): # 0.95這個引數請多調整,對應下面的0.05(針對畫素分佈調節)
end_ = m
break
return end_
n = 1
start = 1
end = 2
word = []
while n < width - 2:
n += 1
if (white[n] if arg else black[n]) > (0.05 * white_max if arg else 0.05 * black_max):
# 上面這些判斷用來辨別是白底黑字還是黑底白字
# 0.05這個引數請多調整,對應上面的0.95
start = n
end = find_end(start)
n = end
if end - start > 5:
cj = img_[1:height, start:end]
cj = cv2.resize(cj, (15, 30))
word.append(cj)
print(len(word))
for i,j in enumerate(word):
plt.subplot(1,8,i+1)
plt.imshow(word[i],cmap='gray')
plt.show()
2.5 最終實現效果
相關文章
- OpenCV基於顏色資訊的車牌提取OpenCV
- 基於OpenCV的車牌識別(Sobel、顏色定位)OpenCV
- python opencv識別藍牌車牌號 之 取出車牌號 (1/3)PythonOpenCV
- Python正規表示式提取車牌號Python
- OpenCV進階之路:神經網路識別車牌字元OpenCV神經網路字元
- 基於 OpenCv 和 Python 的手指識別及追蹤OpenCVPython
- 車牌識別字元模板庫字元
- 基於matlab的車牌識別(含子程式)Matlab
- 【實戰】基於OpenCV的水錶字元識別(OCR)OpenCV字元
- ${string::N}和${string:N}字元提取字元
- 自學筆記:python+opencv針對藍色來進行簡單的車牌定位筆記PythonOpenCV
- 基於Matlab的車牌識別系統(帶介面、模板庫)Matlab
- 基於OpenCV和dlib的人臉交換實現探究OpenCV
- Python基礎之:struct和格式化字元PythonStruct字元
- 基於python + opencv的影片播放調節功能PythonOpenCV
- PaddlePaddle車牌識別實戰和心得
- 一種基於Android、iOS系統的手機掃描車牌識別技術,本地掃描識別車牌AndroidiOS
- 車牌識別系統、車牌識別整合、車牌識別介面
- 基於OpenCV和YOLOv3深度學習的目標檢測OpenCVYOLO深度學習
- 關於【s】和[t]字元字元
- Opencv利用神經網路進行車牌識別(c++)OpenCV神經網路C++
- [影象處理] Python+OpenCV實現車牌區域識別及Sobel運算元PythonOpenCV
- opencv python 基於KNN的手寫體識別OpenCVPythonKNN
- opencv python 基於SVM的手寫體識別OpenCVPython
- python基於opencv 實現影像時鐘PythonOpenCV
- Python 提取PDF文字和圖片Python
- python字元對映表和字元替換Python字元
- OpenCV + sklearnSVM 實現手寫數字分割和識別OpenCV
- Python拆分列中文和 字元Python字元
- 基於OpenFOAM和Python的流場動態模態分解:從資料提取到POD-DMD分析Python
- 關於在textarea中輸入回車換行和空格字元的正常顯示 (轉)字元
- 利用Python和OpenCV將URL直接轉換成OpenCV格式PythonOpenCV
- 學習OpenCV:骨架提取OpenCV
- 小程式驗證車牌號(含新能源車牌)
- 撲克牌排序:基於基數排序的方法排序
- 用 Python 和 OpenCV 檢測和跟蹤運動物件PythonOpenCV物件
- python教程3.3:字元和編碼Python字元
- opencv和Python的區別是什麼?Python開發!OpenCVPython