在上篇文章中,咱們介紹瞭如何用filter2D函數來對圖像進行鄰域變換。這篇文章咱們來簡單介紹一下如何對圖像的像素進行變換。ios
對圖像的單個像素進行變換,是圖像處理中一個很常見的操做。好比改變圖像的亮度,對圖像像素進行線性變換,二值化等。下面將以改變圖像的對比度和亮度來舉例。函數
改變圖像的對比度和亮度,歸根到底,就是下面的這個數學公式:ui
這個式子很好理解。就是將原來圖像中的像素值進行比例變換,後又進行了移動。alpha通常叫作增益參數,表徵對比度,而beta成爲偏置參數,表徵亮度變化。spa
對圖像的每一個像素進行操做,其實咱們在前面的文章中已經介紹過了,好比LUT查表操做,直接用指針訪問,或是用迭代器等。下面的這段代碼實現了對圖像對比度和亮度的這一操做,咱們用指針實現:指針
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv/cv.hpp> #include <opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; Mat ChangePixel(const Mat& img,const double alpha,const int beta) { Mat newImg=Mat::zeros(img.size(),img.type ()); // the img to be returned int chnnels=img.channels (); //Get the channels of source img for (int x=0;x<img.rows;x++) //iteration rows { //用指針訪問 const uchar *p=img.ptr <uchar>(x); //因爲img被聲明爲const,因此指針也要聲明爲const uchar *q=newImg.ptr <uchar>(x); int cols=img.cols*chnnels; for (int y=0;y<cols;y++) { q[y]=saturate_cast<uchar>(p[y]*alpha+beta); //注意saturate_cast的使用 } } return newImg; } int main() { int64 time_start=getTickCount (); Mat A=imread ("lena.jpg",CV_LOAD_IMAGE_COLOR); imshow ("A的圖像",A); Mat B=ChangePixel (A,2,0); imshow ("B的圖像",B); int64 time_end=getTickCount (); double time_take=(time_end-time_start)*1000.0/getTickFrequency (); cout<<"The time is "<<time_take<<"ms"<<endl; waitKey (); return 0; }
注意代碼中saturate_cast函數的使用。這個函數用來完成一個類型到另外一個類型的轉換(固然,這種類型的轉換必須是被容許的)。而若是被轉換的值超過了目的類型的界限時,該函數會自動返回界限值。code
好比:
get
這樣,咱們就實現了對圖像對比度和亮度的變換操做:數學
不過,OpenCV中已經有了進行這樣處理的函數:Mat::convertTo,它能夠完成圖像的數據類型轉換,同時,對像素值進行改變。it
若是參數中的rType爲負數,則轉換先後圖像的類型不變,因此,咱們能夠用一行代碼實現咱們原來的操做:io
A.convertTo (B,-1,2,0);並且,在個人電腦上經過試驗,經過這種方法進行操做,所花時間也變少了。