OpenCV 圖像清晰度(相機自動對焦)


相機的自動對焦要求相機根據拍攝環境和場景的變化,通過相機內部的微型驅動馬達,自動調節相機鏡頭和CCD之間的距離,保證像平面正好投影到CCD的成像表面上。這時候物體的成像比較清晰,圖像細節信息豐富。

相機自動對焦的過程,其實就是對成像清晰度評價的過程,對焦不准確,拍攝出來的圖像清晰度低,視覺效果模糊,如果是在工業檢測測量領域,對焦不准導致的后果可能是致命的;對焦准確的圖像清晰度較高,層次鮮明,對比度高。

圖像清晰度評價算法有很多種,在空域中,主要思路是考察圖像的領域對比度,即相鄰像素間的灰度特征的梯度差;在頻域中,主要思路是考察圖像的頻率分量,對焦清晰的圖像高頻分量較多,對焦模糊的圖像低頻分量較多。

這里實現3種清晰度評價方法,分別是Tenengrad梯度方法、Laplacian梯度方法和方差方法。

 

Tenengrad梯度方法

Tenengrad梯度方法利用Sobel算子分別計算水平和垂直方向的梯度,同一場景下梯度值越高,圖像越清晰。以下是具體實現,這里衡量的指標是經過Sobel算子處理后的圖像的平均灰度值,值越大,代表圖像越清晰。

 1 #include <highgui/highgui.hpp>
 2 #include <imgproc/imgproc.hpp>
 3  
 4 using namespace std;  5 using namespace cv;  6  
 7 int main()  8 {  9     Mat imageSource = imread("2.jpg"); 10  Mat imageGrey; 11  
12  cvtColor(imageSource, imageGrey, CV_RGB2GRAY); 13  Mat imageSobel; 14     Sobel(imageGrey, imageSobel, CV_16U, 1, 1); 15  
16     //圖像的平均灰度
17     double meanValue = 0.0; 18     meanValue = mean(imageSobel)[0]; 19  
20     //double to string
21  stringstream meanValueStream; 22     string meanValueString; 23     meanValueStream << meanValue; 24     meanValueStream >> meanValueString; 25     meanValueString = "Articulation(Sobel Method): " + meanValueString; 26     putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2); 27     imshow("Articulation", imageSource); 28  waitKey(); 29 }

使用三張測試圖片模擬不同對焦。第一張最清晰,得分最高,第二三張越來越模糊,得分依次降低。

 

 

 

 

Laplacian梯度方法:

Laplacian梯度是另一種求圖像梯度的方法,在上例的OpenCV代碼中直接替換Sobel算子即可。

 1 #include <highgui/highgui.hpp>
 2 #include <imgproc/imgproc.hpp>
 3  
 4 using namespace std;  5 using namespace cv;  6  
 7 int main()  8 {  9     Mat imageSource = imread("1.jpg"); 10  Mat imageGrey; 11  
12  cvtColor(imageSource, imageGrey, CV_RGB2GRAY); 13  Mat imageSobel; 14  
15  Laplacian(imageGrey, imageSobel, CV_16U); 16     //Sobel(imageGrey, imageSobel, CV_16U, 1, 1); 17  
18     //圖像的平均灰度
19     double meanValue = 0.0; 20     meanValue = mean(imageSobel)[0]; 21  
22     //double to string
23  stringstream meanValueStream; 24     string meanValueString; 25     meanValueStream << meanValue; 26     meanValueStream >> meanValueString; 27     meanValueString = "Articulation(Laplacian Method): " + meanValueString; 28     putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2); 29     imshow("Articulation", imageSource); 30  waitKey(); 31 }

用同樣的三張測試圖片測試,結果一致,隨着對焦模糊得分降低:

 

 

方差方法:

方差是概率論中用來考察一組離散數據和其期望(即數據的均值)之間的離散(偏離)成都的度量方法。方差較大,表示這一組數據之間的偏差就較大,組內的數據有的較大,有的較小,分布不均衡;方差較小,表示這一組數據之間的偏差較小,組內的數據之間分布平均,大小相近。

對焦清晰的圖像相比對焦模糊的圖像,它的數據之間的灰度差異應該更大,即它的方差應該較大,可以通過圖像灰度數據的方差來衡量圖像的清晰度,方差越大,表示清晰度越好。

 1 #include <highgui/highgui.hpp>
 2 #include <imgproc/imgproc.hpp>
 3  
 4 using namespace std;  5 using namespace cv;  6  
 7 int main()  8 {  9     Mat imageSource = imread("2.jpg"); 10  Mat imageGrey; 11  
12  cvtColor(imageSource, imageGrey, CV_RGB2GRAY); 13  Mat meanValueImage; 14  Mat meanStdValueImage; 15  
16     //求灰度圖像的標准差
17  meanStdDev(imageGrey, meanValueImage, meanStdValueImage); 18     double meanValue = 0.0; 19     meanValue = meanStdValueImage.at<double>(0, 0); 20  
21     //double to string
22  stringstream meanValueStream; 23     string meanValueString; 24     meanValueStream << meanValue*meanValue; 25     meanValueStream >> meanValueString; 26     meanValueString = "Articulation(Variance Method): " + meanValueString; 27  
28     putText(imageSource, meanValueString, Point(20, 50), CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(255, 255, 25), 2); 29     imshow("Articulation", imageSource); 30  waitKey(); 31 }

方差數值隨着清晰度的降低逐漸降低:

 

在工業應用中,最清晰的對焦拍攝出來的圖像不一定是最好的,有可能出現摩爾紋(水波紋)現象,一般需要在最清晰對焦位置附件做一個微調。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM