Python 做圖片清晰度識別

Bob-Chen發表於2018-08-17

在通常情況下,圖片是否清晰是個感性認識,同一個圖,有可能你覺得還過得去,而別人會覺得不清晰,缺乏一個統一的標準。然而有一些演算法可以去量化圖片的清晰度,做到有章可循。

原理

如果之前瞭解過訊號處理,就會知道最直接的方法是計算圖片的快速傅立葉變換,然後檢視高低頻分佈。如果圖片有少量的高頻成分,那麼該圖片就可以被認為是模糊的。然而,區分高頻量多少的具體閾值卻是十分困難的,不恰當的閾值將會導致極差的結果。

我們期望的是一個單一的浮點數就可以表示圖片的清晰度。 Pech-Pacheco 在 2000 年模式識別國際會議提出將圖片中某一通道(一般用灰度值)通過拉普拉斯掩模做卷積運算,然後計算標準差,出來的值就可以代表圖片清晰度。

這種方法湊效的原因就在於拉普拉斯運算元定義本身。它被用來測量圖片的二階導數,突出圖片中強度快速變化的區域,和 Sobel 以及 Scharr 運算元十分相似。並且,和以上運算元一樣,拉普拉斯運算元也經常用於邊緣檢測。此外,此演算法基於以下假設:如果圖片具有較高方差,那麼它就有較廣的頻響範圍,代表著正常,聚焦準確的圖片。但是如果圖片具有有較小方差,那麼它就有較窄的頻響範圍,意味著圖片中的邊緣數量很少。正如我們所知道的,圖片越模糊,其邊緣就越少。

有了代表清晰度的值,剩下的工作就是設定相應的閥值,如果某圖片方差低於預先定義的閾值,那麼該圖片就可以被認為是模糊的,高於閾值,就不是模糊的。

實操

原理看起來比較複雜,涉及到很多訊號啊圖片處理的相關知識,下面我們來實操一下,直觀感受下。

由於人生苦短,以及我個人是朋友圈第一 Python 吹子,我選擇使用 Python 來實現,核心程式碼簡單到令人髮指:

import cv2

def getImageVar(imgPath):
	image = cv2.imread(imgPath);
	img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	imageVar = cv2.Laplacian(img2gray, cv2.CV_64F).var()

	return imageVar
複製程式碼

真是人生苦短啊,核心程式碼就三行,簡單解釋下。

import cv2 使用了一個著名的影像處理庫 OpenCV,關於 OpenCV 的安裝這裡不多贅述,需要注意的是它依賴 numpy。

image = cv2.imread(imgPath) 使用 OpenCV 提供的方法讀取圖片。 img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 轉化為灰度圖。如下圖:

Python 做圖片清晰度識別

原圖是這樣的:

Python 做圖片清晰度識別

cv2.Laplacian(img2gray, cv2.CV_64F) 對圖片用 3x3 拉普拉斯運算元做卷積,這裡的 cv2.CV_64F 就是拉普拉斯運算元。

原理部分說過,拉普拉斯運算元經常用於邊緣檢測,所以這裡經過拉普拉斯運算元之後,留下的都是檢測到的邊緣。上圖經過這步處理之後是這樣的:

Python 做圖片清晰度識別

可以看到這裡圖片人物大致還是比較清晰的。

cv2.Laplacian(img2gray, cv2.CV_64F).var() 計算出方差,並最後返回。

上面那張圖按這個計算出來時 3170 多,這個就是最後我們用來判斷清晰度的值。

Python 做圖片清晰度識別

可以再找一張看看:

原圖:

Python 做圖片清晰度識別

做灰度和經過拉普拉斯運算元之後,可以看到人物部分已經不是很清晰了。

Python 做圖片清晰度識別

最後算出來的方差只有 530

Python 做圖片清晰度識別

剩下的工作就是根據整體圖片質量確定閥值了。

侷限性

通過上面的實操,我們知道這個演算法的技巧在於設定合適的閥值,閾值太低會導致正常圖片被誤斷為模糊圖片,閾值太高會導致模糊圖片被誤判為正常圖片。閥值依賴於你實際應用的業務場景,需要根據使用場景的不同做不同的定製。

真正的銀彈並不存在。除了需要定個閥值外,有些圖片可能會故意做個背景模糊或者背景虛化,這種圖片很容易被誤殺。

比如:

Python 做圖片清晰度識別

計算出來是這樣的,後面一大片都是黑的。

Python 做圖片清晰度識別

這個圖前景其實看著還行,但是背景有大片的虛化和模糊,這種情況下比較容易被誤殺。

所以最好還是在瞭解原理之後,根據實際場景來使用。


最後寫了個簡單的指令碼,對傳入的圖片路徑的圖片進行計算,然後返回一個 json 字串。

用法 python getRank.py --imgs=./1.jpg,./2.jpg

原始碼:github.com/bob-chen/de…

碎碎念

記錄一些所思所想,寫寫科技與人文,寫寫生活狀態,寫寫讀書心得,主要是扯淡和感悟。 歡迎關注,交流。

微信公眾號:程式設計師的詩和遠方

公眾號ID : MonkeyCoder-Life

程式設計師的詩和遠方

相關文章