點擊上方「小白學視覺」,選擇加"星標"或「置頂」算法
重磅乾貨,第一時間送達swift
本期將介紹如何經過圖像處理從低分辨率/模糊/低對比度的圖像中提取有用信息。微信
下面讓咱們一塊兒來探究這個過程:app
首先咱們獲取了一個LPG氣瓶圖像,該圖像取自在傳送帶上運行的倉庫。咱們的目標是找出LPG氣瓶的批號,以便更新已檢測的LPG氣瓶數量。函數
步驟1:導入必要的庫ui
import cv2import numpy as npimport matplotlib.pyplot as plt
步驟2:加載圖像並顯示示例圖像。spa
img= cv2.imread('cylinder1.png')img1=cv2.imread('cylinder.png')images=np.concatenate(img(img,img1),axis=1)cv2.imshow("Images",images)cv2.waitKey(0)cv2.destroyAllWindows()
LPG氣瓶圖片(a)批次-D26(b)批次C27.net
該圖像的對比度很是差。咱們幾乎看不到批號。這是在燈光條件不足的倉庫中的常見問題。接下來咱們將討論對比度受限的自適應直方圖均衡化,並嘗試對數據集使用不一樣的算法進行實驗。3d
步驟3:將圖像轉換爲灰度圖像code
gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)gray_img1=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
步驟4:找到灰度圖像的直方圖後,尋找強度的分佈。
hist=cv2.calcHist(gray_img,[0],None,[256],[0,256])hist1=cv2.calcHist(gray_img1,[0],None,[256],[0,256])plt.subplot(121)plt.title("Image1")plt.xlabel('bins')plt.ylabel("No of pixels")plt.plot(hist)plt.subplot(122)plt.title("Image2")plt.xlabel('bins')plt.ylabel("No of pixels")plt.plot(hist1)plt.show()
步驟5:如今,使用cv2.equalizeHist()函數來均衡給定灰度圖像的對比度。cv2.equalizeHist()函數可標準化亮度並增長對比度。
gray_img_eqhist=cv2.equalizeHist(gray_img)gray_img1_eqhist=cv2.equalizeHist(gray_img1)hist=cv2.calcHist(gray_img_eqhist,[0],None,[256],[0,256])hist1=cv2.calcHist(gray_img1_eqhist,[0],None,[256],[0,256])plt.subplot(121)plt.plot(hist)plt.subplot(122)plt.plot(hist1)plt.show()
步驟6:顯示灰度直方圖均衡圖像
eqhist_images=np.concatenate((gray_img_eqhist,gray_img1_eqhist),axis=1)cv2.imshow("Images",eqhist_images)cv2.waitKey(0)cv2.destroyAllWindows()
灰度直方圖均衡
讓咱們進一步深刻了解CLAHE
步驟7:
對比度有限的自適應直方圖均衡
該算法能夠用於改善圖像的對比度。該算法經過建立圖像的多個直方圖來工做,並使用全部這些直方圖從新分配圖像的亮度。CLAHE能夠應用於灰度圖像和彩色圖像。有2個參數須要調整。
1. 限幅設置了對比度限制的閾值。默認值爲40
2. tileGridsize設置行和列中標題的數量。在應用CLAHE時,爲了執行計算,圖像被分爲稱爲圖塊(8 * 8)的小塊。
clahe=cv2.createCLAHE(clipLimit=40)gray_img_clahe=clahe.apply(gray_img_eqhist)gray_img1_clahe=clahe.apply(gray_img1_eqhist)images=np.concatenate((gray_img_clahe,gray_img1_clahe),axis=1)cv2.imshow("Images",images)cv2.waitKey(0)cv2.destroyAllWindows()
步驟8:
門檻技術
閾值處理是一種將圖像劃分爲前景和背景的簡單但有效的方法。若是像素強度小於某個預約義常數(閾值),則最簡單的閾值化方法將源圖像中的每一個像素替換爲黑色像素;若是像素強度大於閾值,則使用白色像素替換源像素。閾值的不一樣類型是:
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
cv2.THRESH_OTSU
cv2.THRESH_TRIANGLE
嘗試更改閾值和max_val以得到不一樣的結果。
th=80max_val=255ret, o1 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_BINARY)cv2.putText(o1,"Thresh_Binary",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)ret, o2 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_BINARY_INV)cv2.putText(o2,"Thresh_Binary_inv",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)ret, o3 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_TOZERO)cv2.putText(o3,"Thresh_Tozero",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)ret, o4 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_TOZERO_INV)cv2.putText(o4,"Thresh_Tozero_inv",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)ret, o5 = cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_TRUNC)cv2.putText(o5,"Thresh_trunc",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)ret ,o6= cv2.threshold(gray_img_clahe, th, max_val, cv2.THRESH_OTSU)cv2.putText(o6,"Thresh_OSTU",(40,100),cv2.FONT_HERSHEY_SIMPLEX,2,(255,255,255),3,cv2.LINE_AA)
final=np.concatenate((o1,o2,o3),axis=1)final1=np.concatenate((o4,o5,o6),axis=1)
cv2.imwrite("Image1.jpg",final)cv2.imwrite("Image2.jpg",final1)
Thresh_Binary_inv,Thresh_Binary_inv,Thresh_Tozero
Thresh_Tozero_inv,Thresh_trunc,Thresh_OSTU
步驟9:自適應閾值
在上一節中,咱們使用了全局閾值來應用cv2.threshold()。如咱們所見,因爲圖像不一樣區域的照明條件不一樣,所以得到的結果不是很好。在這些狀況下,您能夠嘗試自適應閾值化。在OpenCV中,自適應閾值處理由cv2.adapativeThreshold()函數執行
此功能將自適應閾值應用於src陣列(8位單通道圖像)。maxValue參數設置dst圖像中知足條件的像素的值。adaptiveMethod參數設置要使用的自適應閾值算法。
cv2.ADAPTIVE_THRESH_MEAN_C:將T(x,y)閾值計算爲(x,y)的blockSize x blockSize鄰域的平均值減去C參數。
cv2.ADAPTIVE_THRESH_GAUSSIAN_C:將T(x,y)閾值計算爲(x,y)的blockSize x blockSize鄰域的加權總和減去C參數。
blockSize參數設置用於計算像素閾值的鄰域的大小,它能夠取值三、五、7等。
C參數只是從均值或加權均值中減去的常數(取決於adaptiveMethod參數設置的自適應方法)。一般,此值爲正,但能夠爲零或負。
gray_image = cv2.imread('cylinder1.png',0)gray_image1 = cv2.imread('cylinder.png',0)thresh1 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)thresh2 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 31, 3)thresh3 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 13, 5)thresh4 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 4)thresh11 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)thresh21 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 31, 5)thresh31 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21,5 )thresh41 = cv2.adaptiveThreshold(gray_image1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 5)
final=np.concatenate((thresh1,thresh2,thresh3,thresh4),axis=1)final1=np.concatenate((thresh11,thresh21,thresh31,thresh41),axis=1)cv2.imwrite('rect.jpg',final)cv2.imwrite('rect1.jpg',final1)
自適應閾值
自適應閾值
步驟10:OTSU二值化
gray_image = cv2.imread('cylinder1.png',0)gray_image1 = cv2.imread('cylinder.png',0)ret,thresh1 = cv2.threshold(gray_image,0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)ret,thresh2 = cv2.threshold(gray_image1,0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imwrite('rect.jpeg',np.concatenate((thresh1,thresh2),axis=1))
OTSU二值化
如今,咱們已經從低對比度的圖像中清楚地識別出批號。
交流羣
歡迎加入公衆號讀者羣一塊兒和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫學影像、GAN、算法競賽等微信羣(之後會逐漸細分),請掃描下面微信號加羣,備註:」暱稱+學校/公司+研究方向「,例如:」張三 + 上海交大 + 視覺SLAM「。請按照格式備註,不然不予經過。添加成功後會根據研究方向邀請進入相關微信羣。請勿在羣內發送廣告,不然會請出羣,謝謝理解~
本文分享自微信公衆號 - 小白學視覺(NoobCV)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。