您好,登錄后才能下訂單哦!
這篇文章給大家介紹opencv實踐中圖像增強的基本操作是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
上面這幅黑乎乎的圖就是我們今天要處理的圖片,這是書的一頁,但特別特別黑,對于這種因為陰影而導致的細節缺失,我們就可以嘗試對其進行圖像增強了。
圖像增強真的有不少內容,范圍也很廣泛,今天就只針對這個例子進行實踐了。代碼都是成塊兒的,大家可以復制自行組合
整體框架搭建
首先就先寫個框架啦,讀取圖片顯示圖片啥的:
#include <iostream>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;int main(){ Mat img_output; Mat img_input = imread("bookpage.jpg",0); if (img_input.empty()) { cout << "圖片為空" << endl; } //在這加圖片處理的函數 imshow("輸入", img_input); imshow("輸出", img_output); waitKey(); return 0;}
我們以灰度圖將原書頁照片讀進來,顯示如下:
可以看到整個以黑乎乎的,看著太難受了,不過雖然我們人眼看著那些字是無法識別的,但其實在像素層面上,字的輪廓還是依然在的,而我們要做的就是將圖片增強到文字可以為人眼所見的程度。
手機相機處理
在我們開始自己處理之前呢,先看下用手機相機隨便處理一下的結果:
我們自己處理,怎么也得達到這種效果吧。
直方圖均衡化
直方圖均衡化是常見的一種圖像增強技術,直方圖均衡可以讓像素值由狹小區域擴大到整個像素區域,如下圖,橫軸為像素灰度值,豎軸為該像素值在圖片中的比例:
左圖在直方圖均衡化之后,像素值有明顯的擴散分布,進而提高了圖片的對比度。
而本例中就是因為圖像太黑,也就是像素值集中分布在黑色部分,均衡化可以提高對比度,我們可以看下均衡化的效果:
//直方圖均衡化equalizeHist(img_input, img_output);
可以看到效果并不是很好,但這還只是初步處理,也許再進行直方圖局部均衡化就會更好一些了。
閾值化操作
我們可以知道圖片很黑是因為有很多灰度級很低的像素聚集,我們只要將這些像素過濾掉就可以了,過濾我們可以采用閾值化操作或者二值化操作,我們看看閾值化操作:
//閾值化操作threshold(img_input, img_output, 8, 255, THRESH_BINARY);
可以看到結果也并不十分理想。但opencv還有一個自適應閾值函數,這個函數要更為巧妙一些
//自適應閾值函數 adaptiveThreshold(img_input, img_output, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 7, 3);
可以看到雖然我們可以看清楚上面的字,但并不美觀,而且因為閾值化操作的原因,書頁顏色非黑即白,非常失真。
調整亮度和對比度
我們可以遍歷圖片中(i , j)處的像素,并對其進行如下操作:
f(i,j)代表原圖像像素
g(i,j)代表處理后的圖像像素
a 稱為增益,用來調節圖像對比度
b 稱為偏置,用來調整圖像亮度
//@srcImage:輸入單通道圖像//@a:增益,調對比度//@b:偏置,調亮度Mat contrast_bright(Mat img_input,float a = 1, float b = 0){ Mat dstImage,srcImage = img_input; srcImage.copyTo(dstImage); int row = srcImage.rows; int col = srcImage.cols; // 兩個個for循環,執行運算 dstImage(i,j) = a*srcImage(i,j) + b for (int y = 0; y < row; y++) { for (int x = 0; x < col; x++) { dstImage.at<uchar>(y, x) = saturate_cast<uchar>(a*(img_input.at<uchar>(y, x)) + b ); } } return dstImage;}
//調節亮度和對比度 img_output = contrast_bright(img_input,6,60);
可以看到,通過調節亮度和對比度的方法,已經可以達到不錯的效果。
對像素進行log變換和伽馬變換
我們還可以嘗試對圖像進行變換,比如log函數變換和伽馬變換。以伽馬變換為例:
先看一下伽馬變換的公式:
輸入r就是圖片某點像素值,輸出s為變換后的像素值。下圖為該公式c取1,γ取不同值時的函數圖形:
我們可以看到:
當γ小于1時,以γ=0.10為例,該變換會將窄范圍的低級灰度轉變為灰度級較高的值,直觀上體現為圖片變亮。
當γ大于1時,以γ=5.0所示,該變換會將較寬范圍的灰度轉變為低級灰度,直觀上體現為變暗。
簡單代碼實現:
//@img_input:輸入單通道圖像//@gamma:gamma次方//@n_c:乘以常數n_cMat gammaTrans(Mat& img_input, float gamma, int n_c){ Mat img_Gamma(img_input.size(), CV_8UC1); for (int i = 0; i < img_input.rows; i++) { for (int j = 0; j < img_input.cols; j++) { img_Gamma.at<uchar>(i, j) = n_c * pow(img_input.at<uchar>(i, j), gamma); } } normalize(img_Gamma, img_Gamma, 0, 255, CV_MINMAX); //將像素值映射到0-255范圍 return img_Gamma;}
//伽馬變換 img_output = gammaTrans(img_input,0.4,3);
伽馬變換只是方式之一,可以用來像素映射的函數多種多樣,一般都視實際情況而定。
關于opencv實踐中圖像增強的基本操作是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。