天天看點

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

1 說明:

=====

1.1 環境:

python3.8,深度作業系統deepin-linux,微軟編輯器vscode,opencv版本4.2.0。

1.2 上一篇:

《強!全套完整中文車牌識别,純python來實作和代碼分析》

1.3 本次講解:超級詳細,一步一步,注釋分析,小白都會。

1.4 注意:代碼為注釋講解版,有點繁瑣,但是可讀性較高,大神可以封裝成函數,去掉注釋和視窗顯示過程。

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

圖檔:來自今日頭條免費正版圖庫

2 圖檔:來自今日頭條免費正版圖庫:

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

僅供學習

===代碼逐漸分析===

3 讀取圖檔并顯示原始圖檔:額外知識

=============================

3.1 cv2法:顯示是原圖,省略。牽涉到知識點是圖檔的通道的拆分和合并。

import cv2origin_image = cv2.imread('/home/xgj/Desktop/car911/2.jpeg')cv2.imshow('image', origin_image)cv2.waitKey(0)
           

3.2 matplotlib法:

import cv2#---第2步:讀取待檢測原始的圖檔---origin_image = cv2.imread('/home/xgj/Desktop/car911/2.jpeg')#---第3步:顯示圖檔法---'''# cv2顯示圖檔法:原圖cv2.imshow('image', origin_image)cv2.waitKey(0)''''''# matplotlib法直接顯示,不是原圖from matplotlib import pyplot as pltplt.imshow(origin_image)plt.show()'''# 調整通道的順序,顯示原圖# 分割通道from matplotlib import pyplot as plt#說明cv2讀取的順序是bgr#而matplotlib顯示rgb,故顯示plt原圖法需要轉換b,g,r = cv2.split(origin_image)# 合并通道img = cv2.merge([r, g, b])plt.imshow(img)plt.show()
           

3.3 圖:

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

原圖顯示

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

不是原圖顯示

4 提取藍色車牌:

============

4.1 代碼:

#---第1步:導入所需子產品---import cv2from matplotlib import pyplot as plt#---第2步:讀取待檢測原始的圖檔---origin_image = cv2.imread('/home/xgj/Desktop/car911/2.jpeg')# 可注釋掉# 調整通道的順序# 分割通道b,g,r = cv2.split(origin_image)# 合并通道img = cv2.merge([r, g, b])#用matplotlib的plt顯示圖檔plt.imshow(img)plt.show()#---第3步:提取車牌部分圖檔---#圖像去噪灰階處理# 3-1:對原始圖檔origin_image進行高斯模糊Gausiian_image = cv2.GaussianBlur(origin_image, (3, 3), 0)#可注釋掉plt.imshow(Gausiian_image)plt.show()# 3-2:灰階化處理圖像gray_image = cv2.cvtColor(Gausiian_image, cv2.COLOR_RGB2GRAY)#可注釋掉plt.imshow(gray_image)plt.show()# 3-3:Sobel算子Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0) # 對x求一階導,垂直檢測#Sobel_y = cv2.Sobel(gray_image, cv2.CV_16S, 0, 1) # 附注:對y求一階導,水準檢測absX = cv2.convertScaleAbs(Sobel_x)  # 轉回uint8#定義車牌imagechepai = absX# 3-4:圖像二值化ret, image2 = cv2.threshold(imagechepai, 0, 255, cv2.THRESH_OTSU)# 3-5:閉操作可以将目标區域連成一個整體,便于後續輪廓的提取。kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 5))image3 = cv2.morphologyEx(image2, cv2.MORPH_CLOSE, kernelX,iterations = 3)#可注釋掉plt.imshow(image3)plt.show()# 3-6:膨脹和腐蝕#通過膨脹連接配接相近的圖像區域,通過腐蝕去除孤立細小的色塊。kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 1))kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 19))#膨脹第1次image4 = cv2.dilate(image3, kernelX)plt.imshow(image4)plt.show()#腐蝕第1次image5 = cv2.erode(image4, kernelX)plt.imshow(image5)plt.show()#腐蝕第2次image6 = cv2.erode(image5, kernelY)plt.imshow(image6)plt.show()#膨脹第2次image7 = cv2.dilate(image6, kernelY)plt.imshow(image7)plt.show()# 3-7:中值濾波:去除圖像或者其它信号中的噪聲。image8 = cv2.medianBlur(image7, 15)plt.imshow(image8)plt.show()# 3-8:查找輪廓contours, hierarchy = cv2.findContours(image8, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 3-9:判斷車牌區域:for item in contours:    rect = cv2.boundingRect(item)    x = rect[0]    y = rect[1]    weight = rect[2]    height = rect[3]    if (weight > (height * 3)) and (weight < (height * 4)):        image9 = origin_image[y:y + height, x:x + weight]  #側位車牌和黃色車牌報錯        #提取車牌,生成車牌圖檔        cv2.imwrite('/home/xgj/Desktop/car911/chepai1.png', image9)        cv2.imshow('image', image9)        cv2.waitKey(0)
           

4.2 操作和效果圖:

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

4.3 正位綠色車牌:OK,省略。(新能源汽車車牌,正面非側位OK)

5 bug分析:

============

5.1 圖:

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

側位車牌:bug

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

黃色車牌:bug:(3.jpeg)

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

報錯原因

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

側位車牌:bug

6 黃色車牌定位和提取(圖:3.jpeg):

=============================

6.1 代碼:換一種思維

#---第1步:導入子產品--import cv2import numpy as np#---第2步:讀取原圖---img = cv2.imread('/home/xgj/Desktop/car911/3.jpeg')#可注釋掉cv2.imshow("pic1",img) #顯示原圖cv2.waitKey(0)#---第3步:預處理---# 包括灰階處理,高斯濾波平滑處理,Sobel提取邊界,圖像二值化# 3-1:灰階處理gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)cv2.imshow("pic2", gray_img)cv2.waitKey(0)# 3-2:高斯濾波平滑處理GaussianBlur_img = cv2.GaussianBlur(gray_img, (3, 3), 0)cv2.imshow("pic3", GaussianBlur_img)cv2.waitKey(0)# 3-3:Sobel提取邊界Sobel_img = cv2.Sobel(GaussianBlur_img, -1, 1, 0, ksize=3)cv2.imshow("pic4", Sobel_img)cv2.waitKey(0)# 3-4:圖像二值化ret, binary_img = cv2.threshold(Sobel_img, 127, 255, cv2.THRESH_BINARY)#---第4步:形态學運算---kernel = np.ones((5, 15), np.uint8)# 先閉運算将車牌數字部分連接配接,再開運算将不是塊狀的或是較小的部分去掉close_img = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel)open_img = cv2.morphologyEx(close_img, cv2.MORPH_OPEN, kernel)# 再來一次:修改部分圖像得到的輪廓邊緣不整齊kernel2 = np.ones((10, 10), np.uint8)open_img2 = cv2.morphologyEx(open_img, cv2.MORPH_OPEN, kernel2)#結構元素可以是矩形/橢圓/十字形,可以用cv2.getStructuringElement()來生成不同形狀的結構元素element = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  #矩形結構dilation_img = cv2.dilate(open_img, element, iterations=3)cv2.imshow("pic4", dilation_img)cv2.waitKey(0)#---第5步:擷取輪廓---# 5-1:2個名額,易報錯,與opencv版本有關contours, hierarchy = cv2.findContours(dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 測試邊框識别結果,注釋掉,否則汽車車牌提取後有綠色輪廓,不好看#cv2.drawContours(img, contours, -1, (0, 255, 0), 3)#cv2.imshow("pic5", img)  #繪制輪廓圖#cv2.waitKey(0)# 5-2:從輪廓中提取坐标# 将輪廓規整為長方形rectangles = []for c in contours:    x = []    y = []    for point in c:        y.append(point[0][0])        x.append(point[0][1])    r = [min(y), min(x), max(y), max(x)]    rectangles.append(r)    # 5-3:用顔色識别出車牌區域dist_r = []max_mean = 0for r in rectangles:    carmask = img[r[1]:r[3], r[0]:r[2]]  #車牌區域面積大小    hsv = cv2.cvtColor(carmask, cv2.COLOR_BGR2HSV)    '''    #藍色車牌,可以使用    low = np.array([100, 60, 60])    up = np.array([140, 255, 255])    '''    #黃色車牌    low = np.array([15, 55, 55])    up = np.array([50, 255, 255])        '''    #綠色車牌:系能源汽車報錯,因為車牌底色不是全綠,白色漸變綠色    low = np.array([50, 50, 50])    up = np.array([100, 255, 255])    '''    result = cv2.inRange(hsv, low, up)    # 用計算均值的方式找藍色最多的區塊    mean = cv2.mean(result)    if mean[0] > max_mean:        max_mean = mean[0]        dist_r = r# 畫出識别結果,定位用,截取車牌時就不要了,否則車牌上有綠色框,不好看#cv2.rectangle(img, (dist_r[0]+3, dist_r[1]), (dist_r[2]-3, dist_r[3]), (0, 255, 0), 2)#參數格式:cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)#一般格式#qichechepai = img[y:y + height, x:x + weight]qichechepai = img[dist_r[1]:dist_r[3], dist_r[0]+3:dist_r[2]-3]#提取車牌,生成車牌圖檔cv2.imwrite('/home/xgj/Desktop/car911/chepai3.png', qichechepai)cv2.imshow('qichechepaitiqu', qichechepai)cv2.waitKey(0)
           

6.2 操作和效果圖:

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

6.3 新能源汽車車牌就不适合。

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

号碼底色上白下綠,不适合這種方法

7 側面車牌定位和提取:

=================

7.1 分類器:下載下傳位址

https://github.com/zeusees/HyperLPR/blob/master/model/cascade.xml  #分類器來自别人,感謝
           

7.2 代碼:

#---第1步:導出子產品--import cv2import numpy as np#---第2步:定義偵測函數def detect(image):    # 調用分類器,提前下載下傳好    cascade_path = '/home/xgj/Desktop/car911/cascade.xml'    cascade = cv2.CascadeClassifier(cascade_path)      # 修改圖檔大小    resize_h = 400    height = image.shape[0]    scale = image.shape[1] / float(height)    image = cv2.resize(image, (int(scale * resize_h), resize_h))    # 轉為灰階圖    image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)    #查找車牌    car_plates = cascade.detectMultiScale(image_gray, 1.1, 2, minSize=(36, 9), maxSize=(36 * 40, 9 * 40))    # print("檢測到車牌數", len(car_plates))    #判斷    if len(car_plates) > 0:        for car_plate in car_plates:            x, y, w, h = car_plate            #畫汽車車牌矩形并截取            qichechepai = image[y-10: y + h + 10, x-10: x + w + 10]             cv2.imshow('plate', qichechepai)  #顯示車牌視窗            cv2.imwrite('/home/xgj/Desktop/car911/ccnew.png', qichechepai) #儲存提取汽車車牌            #畫車牌識别定位框            cv2.rectangle(image, (x - 10, y - 10), (x + w + 10, y + h + 10), (0, 255, 0), 2)    cv2.imshow("image", image) #顯示原圖上定位并畫出識别框    if __name__ == '__main__':    #導入原圖    image = cv2.imread('/home/xgj/Desktop/1-chepai-dingwei/fenleiqi/cc.jpeg')     detect(image)    cv2.waitKey(0)    cv2.destroyAllWindows()
           

7.3 操作和效果圖:

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

7.4 側面新能源汽車車牌,可以搞定,小bug:

opencv函數findcontours_一步一步詳細講解:python+opencv的車牌提取大全

2個識别車牌,提取一個車牌

===汽車車牌定位和提取大全===

高手可以整合、定義函數、封裝

不管了,好東西就應該分享。

繼續閱讀