標籤:cv c++ 映像銳利化 拉普拉斯運算元
映像銳利化處理的主要目的是突出映像中的細節或者增強被模糊了的細節,這種模糊一般由於錯誤操作或者是特殊映像擷取方法的影響導致的。映像銳利化的方法有很多,這裡主要說下微分運算元的方法來進行映像的銳利化處理。總的來說,微分運算元的響應強度與映像在該點(應用了運算元)的突變程度有關。
數學中的微分描述的是連續函數關於各個變數的變化。但是在映像中,是以眾多像素點來組成整張圖片,所以,雖然映像有兩個方向:水平方向(x方向)和垂直方向(y方向),但是這些方向的值也就是像素點的x值和y值均是離散的。X:1,2,3,…n; Y:1,2,3,…m;那我們就需要用離散的方法來表示出微分。
數學函數的微分可以用不同的術語定義,也有各種方法定義這些差別,然而,對於一階微分的任何定義都必須保證以下幾點:(1)在平坦段(灰階不變的地區)微分值為零;(2)在灰階階梯或斜坡的起始點處微分值非零;(3)沿著斜坡面微分值非零。任何二階微分的定義也類似:(1)在平坦區微分值必為零;(2)在灰階階梯或斜坡的起始點處微分值非零;(3)沿著斜坡面微分值非零。因為我們處理的是數字量,其值是有限的,故最大灰階級的變化也是有限的,變化發生的最短距離是在兩相鄰像素之間。
1.基於一階微分的映像增強原理
對於二元函數的一階偏微分微分表示如下:
定義二元函數的微分為:
這就描述了映像中一個像素點(x,y)的一階微分變化。簡單的總結為一個運算元的話就是一個2*2的矩陣如下
此運算元在映像中應用的意思就是將(x,y)處像素的值減去(x-1,y)處值,與(x,y)出像素值減去(x,y-1)處的像素值相加替換(x,y)處的像素值。這就表徵了映像在(x,y)處的一種變化,將這種變化與(x,y)處原有的值進行疊加,就可以將使這種變化更明顯,也就是放大這種變化,從而達到映像銳利化的目的。
2.基於二階微分的映像增強處理。
首先定義一個二階微分的離散公式,然後構造一個基於此式的濾波器。我們最關注的是一種各向同性濾波器,這種濾波器的響應與濾波器作用的映像的突變方向無關。也就是說,各向同性濾波器是旋轉不變的,即將原始映像旋轉後進行濾波處理給出的結果與先對映像濾波,然後再旋轉的結果相同。
一個二元映像函數f(x,y)的拉普拉斯變換定義為:
因為任意階微分都是線性操作,所以拉普拉斯變換也是一個線性操作。
為了更適合於數位影像處理,這一方程需要表示為離散形式。通過鄰域處理有多種方法定義離散變換,但無論怎樣定義,都必須符合3.7.1節中提到的二階微分處理的性質。在上一節中給出的數字二階微分處理的定義是最常用的一種。考慮到有兩個變數,因此,我們在x方向上對二階偏微分採用下列定義:
類似地,在y方向上為:
式(3.7.1)中的二維拉普拉斯數字實現可由這兩個分量相加得到:
從而得到拉普拉斯運算元
意思同上面的一階微分運算元相同。
這裡解釋一下微分運算元的使用,很簡單,如上面這個就是在處理每個像素點的RGB值時,將該像素的RGB三個值乘以4然後減去他上向左右四個像素點的RGB值,注意R、G、B分別處理。
這樣是變化的表示,我們要想圖片銳利化,應該把這種變化疊加到原像素就行了,也就是
思路很簡單。
一下為自己實現映像基於拉普拉斯運算元的銳利化過程:
void sharpen(const Mat &img, Mat &result){for (int j = 1; j < img.rows - 1; ++j){const uchar *previous = img.ptr<const uchar>(j - 1);const uchar *current = img.ptr<const uchar>(j);const uchar *next = img.ptr<const uchar>(j + 1);uchar *output = result.ptr<uchar>(j);for (int i = 1; i < 3 * (img.cols - 1); ++i)//這裡是基於RGB圖的,如果非RGB圖則無需這樣{*output++ = cv::saturate_cast<uchar>(5 * current[i] - current[i - 1] - current[i + 1]- previous[i] - next[i]);}}result.row(0).setTo(cv::Scalar(0));result.row(result.rows - 1).setTo(cv::Scalar(0));result.col(0).setTo(cv::Scalar(0));result.col(result.cols - 1).setTo(cv::Scalar(0));}
以下為使用opencv中的fiter2D函數通過拉普拉斯運算元實現銳利化操作的代碼
int main(){Mat img, resulta;img = imread("C:/Users/Administrator/Desktop/bbb.jpg");cv::Mat kernela(3, 3, CV_32F, cv::Scalar(0));// assigns kernel values kernela.at<float>(1, 1) = 5.0;kernela.at<float>(0, 1) = -1.0;kernela.at<float>(2, 1) = -1.0;kernela.at<float>(1, 0) = -1.0;kernela.at<float>(1, 2) = -1.0; filter2D(img, resulta, img.depth(), kernela);//cout << img.rowRange(1, 4).colRange(1, 4) << endl;//cout << result.rowRange(1, 4).colRange(1, 4) << endl;imwrite("C:/Users/Administrator/Desktop/solved.jpg", resulta);//imshow("origin", img);//imshow("銳利化結果", resulta);waitKey(0);return 0;}
原始圖片
銳利化後圖片
cv-拉普拉斯運算元銳利化淺析