[圖像處理] Python+OpenCV實現(xiàn)車牌區(qū)域識別及Sobel算子丨【拜托了,物聯(lián)網(wǎng)!】
由于最近太忙,這篇文章只給出相關(guān)代碼供大家學習,過一段時間會詳細的寫一些列Python圖像處理的文章,包括各種算法原理、圖像識別、圖像增強、圖像分類、深度學習等。本篇文章主要調(diào)用OpenCV庫(cv2)進行車牌區(qū)域識別,具體步驟包括:
1.灰度轉(zhuǎn)換:將彩色圖片轉(zhuǎn)換為灰度圖像,常見的R=G=B=像素平均值。
2.高斯平滑和中值濾波:去除噪聲。
3.Sobel算子:提取圖像邊緣輪廓,X方向和Y方向平方和開跟。
4.二值化處理:圖像轉(zhuǎn)換為黑白兩色,通常像素大于127設(shè)置為255,小于設(shè)置為0。
5.膨脹和細化:放大圖像輪廓,轉(zhuǎn)換為一個個區(qū)域,這些區(qū)域內(nèi)包含車牌。
6.通過算法選擇合適的車牌位置,通常將較小的區(qū)域過濾掉或?qū)ふ宜{色底的區(qū)域。
7.標注車牌位置,如果是花兒、人臉、牛角,可能需要特征提取和訓練。
本篇文章為基礎(chǔ)性文章,希望對你有所幫助,主要提供些思路,也是自己教學的內(nèi)容。如果文章中存在錯誤或不足之處,還請海涵。同時,推薦大家閱讀我以前的文章了解其他知識。
一、讀取圖像及灰度轉(zhuǎn)換
代碼如下:
#encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取圖片 imagePath = '10.jpg' img = cv2.imread(imagePath) #opencv默認的imread是以BGR的方式進行存儲的 #而matplotlib的imshow默認則是以RGB格式展示 #所以此處我們必須對圖片的通道進行轉(zhuǎn)換 lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #灰度圖像處理 GrayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) print(u"讀入lenna圖的shape為", GrayImage.shape) #顯示圖形 titles = ['Source Image','Gray Image'] images = [lenna_img, GrayImage] for i in xrange(2): plt.subplot(1,2,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show() cv2.imshow('Gray.bmp', GrayImage) cv2.waitKey(0)
二、高斯平滑和中值濾波去噪
這里原理推薦我以前C++圖像處理的文章,如下:
https://blog.csdn.net/column/details/eastmount-mfc.html
完整代碼如下所示:
#encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取圖片 imagePath = '10.jpg' img = cv2.imread(imagePath) #opencv默認的imread是以BGR的方式進行存儲的 #而matplotlib的imshow默認則是以RGB格式展示 #所以此處我們必須對圖片的通道進行轉(zhuǎn)換 lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #灰度圖像處理 GrayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) print(u"讀入lenna圖的shape為", GrayImage.shape) #直方圖均衡化 #equ = cv2.equalizeHist(gray) #高斯平滑 Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT) #Gaussian = cv2.GaussianBlur(GrayImage, (9, 9),0) #中值濾波 Median = cv2.medianBlur(Gaussian, 5) #顯示圖形 titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image'] images = [lenna_img, GrayImage, Gaussian, Median] for i in xrange(4): plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
三、Sobel算子提取輪廓和二值化處理
有時還需要加強圖像中景物的邊緣和輪廓,邊緣和輪廓通常位于圖像中灰度突出的地方,因而可以直觀的想到用灰度的差分對邊緣和輪廓進行提取,通??梢酝ㄟ^梯度算子進行提取。圖像銳化的目的是提高圖像的對比度,從而使圖像更清晰,通過提高鄰域內(nèi)像素的灰度差來提高圖像的對比度。本文采用Sobel算子提取邊緣輪廓。
完整代碼如下所示:
#encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取圖片 imagePath = '10.jpg' img = cv2.imread(imagePath) #opencv默認的imread是以BGR的方式進行存儲的 lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #灰度圖像處理 GrayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) print(u"讀入lenna圖的shape為", GrayImage.shape) #直方圖均衡化 #equ = cv2.equalizeHist(gray) # 高斯平滑 Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT) # 中值濾波 Median = cv2.medianBlur(Gaussian, 5) # Sobel算子 XY方向求梯度 x = cv2.Sobel(Median, cv2.CV_8U, 1, 0, ksize = 3) #X方向 y = cv2.Sobel(Median, cv2.CV_8U, 0, 1, ksize = 3) #Y方向 absX = cv2.convertScaleAbs(x) # 轉(zhuǎn)回uint8 absY = cv2.convertScaleAbs(y) Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5,0) cv2.imshow('dilation2', Sobel) cv2.waitKey(0) # 二值化處理 周圍像素影響 ret, Binary = cv2.threshold(Sobel, 170, 255, cv2.THRESH_BINARY) cv2.imshow('dilation2',Binary) cv2.waitKey(0) #顯示圖形 titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image', 'Sobel Image', 'Binary Image'] images = [lenna_img, GrayImage, Gaussian, Median, Sobel, Binary] for i in xrange(6): plt.subplot(2,3,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
輸出結(jié)果如下所示:
四、膨脹和腐蝕處理
接下來進行膨脹和腐蝕處理,其中膨脹讓輪廓突出,腐蝕去掉細節(jié)。
#encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取圖片 imagePath = '10.jpg' img = cv2.imread(imagePath) #opencv默認的imread是以BGR的方式進行存儲的 lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #灰度圖像處理 GrayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) print(u"讀入lenna圖的shape為", GrayImage.shape) #直方圖均衡化 #equ = cv2.equalizeHist(gray) #高斯平滑 去噪 Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT) #Gaussian = cv2.GaussianBlur(GrayImage, (9, 9),0) #中值濾波 Median = cv2.medianBlur(Gaussian, 5) #Sobel算子 XY方向求梯度 cv2.CV_8U x = cv2.Sobel(Median, cv2.CV_32F, 1, 0, ksize = 3) #X方向 y = cv2.Sobel(Median, cv2.CV_32F, 0, 1, ksize = 3) #Y方向 #absX = cv2.convertScaleAbs(x) # 轉(zhuǎn)回uint8 #absY = cv2.convertScaleAbs(y) #Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) gradient = cv2.subtract(x, y) Sobel = cv2.convertScaleAbs(gradient) cv2.imshow('dilation2', Sobel) cv2.waitKey(0) #二值化處理 周圍像素影響 blurred = cv2.GaussianBlur(Sobel, (9, 9),0) #再進行高斯去噪 #注意170可以替換的 ret, Binary = cv2.threshold(blurred , 90, 255, cv2.THRESH_BINARY) cv2.imshow('dilation2', Binary) cv2.waitKey(0) #膨脹和腐蝕操作的核函數(shù) element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1)) element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7)) # 膨脹讓輪廓突出 Dilation = cv2.dilate(Binary, element2, iterations = 1) # 腐蝕去掉細節(jié) Erosion = cv2.erode(Dilation, element1, iterations = 1) # 再次膨脹 Dilation2 = cv2.dilate(Erosion, element2,iterations = 3) cv2.imshow('Dilation2 ', Dilation2) cv2.waitKey(0) #顯示圖形 titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image', 'Sobel Image', 'Binary Image', 'Dilation Image', 'Erosion Image', 'Dilation2 Image'] images = [lenna_img, GrayImage, Gaussian, Median, Sobel, Binary, Dilation, Erosion, Dilation2] for i in xrange(9): plt.subplot(3,3,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
五、指定算法選擇車牌區(qū)域
該部分代碼膨脹和腐蝕略有區(qū)別,采用closed變量實現(xiàn)。同時獲取最理想的區(qū)域,完整代碼如下所示:
#encoding:utf-8 #BY:Eastmount CSDN 2018-08-06 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取圖片 imagePath = '10.jpg' img = cv2.imread(imagePath) #opencv默認的imread是以BGR的方式進行存儲的 lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #灰度圖像處理 GrayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) print(u"讀入lenna圖的shape為", GrayImage.shape) #直方圖均衡化 #equ = cv2.equalizeHist(gray) #高斯平滑 去噪 Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT) #Gaussian = cv2.GaussianBlur(GrayImage, (9, 9),0) #中值濾波 Median = cv2.medianBlur(Gaussian, 5) #Sobel算子 XY方向求梯度 cv2.CV_8U x = cv2.Sobel(Median, cv2.CV_32F, 1, 0, ksize = 3) #X方向 y = cv2.Sobel(Median, cv2.CV_32F, 0, 1, ksize = 3) #Y方向 #absX = cv2.convertScaleAbs(x) # 轉(zhuǎn)回uint8 #absY = cv2.convertScaleAbs(y) #Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) gradient = cv2.subtract(x, y) Sobel = cv2.convertScaleAbs(gradient) cv2.imshow('dilation2', Sobel) cv2.waitKey(0) #二值化處理 周圍像素影響 blurred = cv2.GaussianBlur(Sobel, (9, 9),0) #再進行一次高斯去噪 #注意170可以替換的 ret, Binary = cv2.threshold(blurred , 170, 255, cv2.THRESH_BINARY) cv2.imshow('dilation2', Binary) cv2.waitKey(0) # 膨脹和腐蝕操作的核函數(shù) element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1)) element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7)) # 膨脹一次,讓輪廓突出 Dilation = cv2.dilate(Binary, element2, iterations = 1) # 腐蝕一次,去掉細節(jié) Erosion = cv2.erode(Dilation, element1, iterations = 1) # 再次膨脹,讓輪廓明顯一些 Dilation2 = cv2.dilate(Erosion, element2,iterations = 3) cv2.imshow('Dilation2 ', Dilation2) cv2.waitKey(0) ########################################## #建立一個橢圓核函數(shù) kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25, 25)) #執(zhí)行圖像形態(tài)學, 細節(jié)直接查文檔,很簡單 closed = cv2.morphologyEx(Binary, cv2.MORPH_CLOSE, kernel) closed = cv2.erode(closed, None, iterations=4) closed = cv2.dilate(closed, None, iterations=4) cv2.imshow('erode dilate', closed) cv2.waitKey(0) ########################################## #顯示圖形 titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image', 'Sobel Image', 'Binary Image', 'Dilation Image', 'Erosion Image', 'Dilation2 Image'] images = [lenna_img, GrayImage, Gaussian, Median, Sobel, Binary, Dilation, Erosion, closed] for i in xrange(9): plt.subplot(3,3,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show() cv2.imshow('Gray', GrayImage) cv2.waitKey(0) """ 接下來使用Dilation2圖片確定車牌的輪廓 這里opencv3返回的是三個參數(shù) 參數(shù)一:二值化圖像 參數(shù)二:輪廓類型 檢測的輪廓不建立等級關(guān)系 參數(shù)三:處理近似方法 例如一個矩形輪廓只需4個點來保存輪廓信息 """ (_, cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_LIST, #RETR_TREE cv2.CHAIN_APPROX_SIMPLE) #畫出輪廓 c = sorted(cnts, key=cv2.contourArea, reverse=True)[0] print c #compute the rotated bounding box of the largest contour rect = cv2.minAreaRect(c) print 'rectt', rect Box = np.int0(cv2.boxPoints(rect)) print 'Box', Box #draw a bounding box arounded the detected barcode and display the image Final_img = cv2.drawContours(img.copy(), [Box], -1, (0, 0, 255), 3) cv2.imshow('Final_img', Final_img) cv2.waitKey(0)
Python實現(xiàn)車牌定位及分割 - 簡書
https://blog.csdn.net/sinat_36458870/article/details/78825571
OpenCV圖像識別:車牌定位算法源碼,Python語言實現(xiàn)_sumkee911‘s coding-CSDN博客_python 車牌定位
感恩能與大家在華為云遇見!
希望能與大家一起在華為云社區(qū)共同成長。原文地址:https://blog.csdn.net/Eastmount/article/details/81461679
【拜托了,物聯(lián)網(wǎng)!】有獎征文火熱進行中:https://bbs.huaweicloud.com/blogs/296704
(By:娜璋之家 Eastmount 2021-10-03 夜于武漢)
OpenCV Python 圖像處理
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。