步驟包括:
1.灰度轉換:將彩色圖片轉換為灰度影象,常見的R=G=B=畫素平均值。
2.高斯平滑和中值濾波:去除噪聲。
3.Sobel運算元:提取影象邊緣輪廓,X方向和Y方向平方和開跟。
4.二值化處理:影象轉換為黑白兩色,通常畫素大於127設定為255,小於設定為0。
5.膨脹和細化:放大影象輪廓,轉換為一個個區域,這些區域內包含車牌。
6.通過演算法選擇合適的車牌位置,通常將較小的區域過濾掉或尋找藍色底的區域。
7.標註車牌位置,如果是花兒、人臉、牛角,可能需要特徵提取和訓練。
Python OpenCV 車牌域識 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的方式進行儲存的
- #而matplotlib的imshow預設則是以RGB格式展示
- #所以此處我們必須對圖片的通道進行轉換
- 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 range(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)
複製代碼
輸出結果如下圖所示:
Python OpenCV 車牌域識 Sobel 運算元
二、高斯平滑和中值濾波去噪
Python OpenCV 車牌域識 Sobel 運算元
Python OpenCV 車牌域識 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的方式進行儲存的
- #而matplotlib的imshow預設則是以RGB格式展示
- #所以此處我們必須對圖片的通道進行轉換
- 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 range(4):
- plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
- plt.title(titles[i])
- plt.xticks([]),plt.yticks([])
- plt.show()
複製代碼
輸出結果如下圖所示,分別是原圖、灰度影象、高斯處理和中值濾波處理。
Python OpenCV 車牌域識 Sobel 運算元
三、Sobel運算元提取輪廓和二值化處理有時還需要加強影象中景物的邊緣和輪廓,邊緣和輪廓通常位於影象中灰度突出的地方,因而可以直觀的想到用灰度的差分對邊緣和輪廓進行提取,通常可以通過梯度運算元進行提取。影象銳化的目的是提高影象的對比度,從而使影象更清晰,通過提高鄰域內畫素的灰度差來提高影象的對比度。本文采用Sobel運算元提取邊緣輪廓。
Python OpenCV 車牌域識 Sobel 運算元
閾值又稱為臨界值,它的目的是確定出一個範圍,然後這個範圍內的部分使用同一種方法處理,而閾值之外的部分則使用另一種處理方法或保持原樣。常用的包括產生二值圖:當x<T時y=0,當x>=T時y=255(其中T是閾值)。閾值變換在生物學上的應用比較廣泛,常用語細胞影象分割等。本文采用二值化處理將大於等於170畫素的轉換為255,而下於的轉換為0,使得影象更加清晰。 完整程式碼如下所示: - #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) # 轉回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 range(6):
- plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
- plt.title(titles[i])
- plt.xticks([]),plt.yticks([])
- plt.show()
複製代碼
輸出結果如下所示:
Python OpenCV 車牌域識 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)
- #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) # 轉回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)
- #膨脹和腐蝕操作的核函式
- element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
- element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7))
- # 膨脹讓輪廓突出
- Dilation = cv2.dilate(Binary, element2, iterations = 1)
- # 腐蝕去掉細節
- 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 range(9):
- plt.subplot(3,3,i+1),plt.imshow(images[i],'gray')
- plt.title(titles[i])
- plt.xticks([]),plt.yticks([])
- plt.show()
複製代碼
輸出結果如下圖所示,可以看到輪廓區域已經被提取出來,接下來開始有選擇的進行獲取。
Python OpenCV 車牌域識 Sobel 運算元
五、指定演算法選擇車牌區域該部分程式碼膨脹和腐蝕略有區別,採用closed變數實現。同時獲取最理想的區域,完整程式碼如下所示:
- #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) # 轉回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)
- # 膨脹和腐蝕操作的核函式
- element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
- element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7))
- # 膨脹一次,讓輪廓突出
- Dilation = cv2.dilate(Binary, element2, iterations = 1)
- # 腐蝕一次,去掉細節
- Erosion = cv2.erode(Dilation, element1, iterations = 1)
- # 再次膨脹,讓輪廓明顯一些
- Dilation2 = cv2.dilate(Erosion, element2,iterations = 3)
- cv2.imshow('Dilation2 ', Dilation2)
- cv2.waitKey(0)
- ##########################################
- #建立一個橢圓核函式
- kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25, 25))
- #執行影象形態學, 細節直接查文件,很簡單
- 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 range(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返回的是三個引數
- 引數一:二值化影象
- 引數二:輪廓型別 檢測的輪廓不建立等級關係
- 引數三:處理近似方法 例如一個矩形輪廓只需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 OpenCV 車牌域識 Sobel 運算元
Python OpenCV 車牌域識 Sobel 運算元
|