基於OpenCV實現圖像線性變化

基礎知識:
線性灰度變換函數f(x)是一個一維線性函數
y=f(x)=ax+b
式中;a爲線性函數的斜率,b爲線性函數在y軸的截距,x表示輸入圖像的灰度值,y表示輸出圖像的灰度值。
(1) 當a>1時,輸出圖像的對比度將增加;當a<1時,輸出圖像的對比度將減小。
        (2) 當a=1時,且b不等於0時,操作僅僅使得所有的像素灰度值上移或者下移,其效果使得整個輸出圖像更亮或者更暗
(3) 當a<1時,暗區域將變亮,亮區域將變暗,這種線性改變亮度可能由於像素亮度達到飽和(小於0或者大於255)而丟失一部分細節。
         (4)特殊情況下,當a=1,b=0時,輸入圖像和輸出圖像一致;
                                       當a=-1,b=255,輸出圖像的灰度正好反轉。灰度反轉處理適用於增強暗色圖像中的亮度較大的細節部分,這也是由人的視覺特性決定的。

/*----------------------------------------------------------------------------------------------
* 程序說明:基於OpenCV實現圖像線性變化
*開發環境:
*        win7+vs2010+opencv2.4.8
*創建時間地點:
*        陝西師範大學.2017.2.28
*參考資料:
*        《數字圖像處理與計算機視覺》張錚,徐超-----那本藍色書66頁的算法
*作    者:
*        李先生
-----------------------------------------------------------------------------------------------*/
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\imgproc\imgproc_c.h>
//using namespace std;
using namespace cv;

/*----------------------------------線性變換函數的聲明----------------------------------------
*函數原型
*   	bool LinTran(IplImage *srcImage, double a,double b);
*參數
*       double a:線性變換的斜率
*	    double b:線性變換的截距
*返回值類型    
*       bool類型;true爲成功,false爲失敗
--------------------------------------------------------------------------------------------*/
bool LinTran(IplImage *srcImage, double a,double b);

//---------------------------------【Main 函數】------------------------------------------------
//                                 我們的程序從這裏開始執行
//------------------------------------------------------------------------------------------------
int main()
{
	IplImage* srcImage=cvLoadImage("G:\\Image\\lena.png");   //加載一副圖片
	double a=-1,b=255;                                      //注意:這裏的參數a,b可以根據具體需要進行設置
	CvSize graySize;
	graySize.height=srcImage->height;
	graySize.width=srcImage->width;
	IplImage* grayImage=cvCreateImage(graySize,srcImage->depth,1);
	cvCvtColor(srcImage,grayImage,CV_RGB2GRAY);              //當數據類型一致時,它將圖像從一個顏色空間(通道的數值)轉換到另一個
	LinTran(grayImage,a,b);                                  //調用線性變換函數

	cvNamedWindow("原圖");
	cvNamedWindow("變換結果");
	cvShowImage("原圖",srcImage);
	cvShowImage("變換結果",grayImage);

	waitKey(0);
	return 0;
}

bool LinTran(IplImage *grayImage, double a,double b)       //線性變換函數的實現
{
	if((grayImage->depth)!=8) return false;
	uchar gray;       //存儲當前光標像素的灰度值
	int target;     //存儲當前光標像素的目標值

	for(int h=0;h<grayImage->height;h++)                    //開始遍歷grayImage灰度圖像
	{
		for(int w=0;w<grayImage->width;w++)
		{
			gray=(uchar)*((char*)(grayImage->imageData+h*grayImage->widthStep)+grayImage->nChannels*w); //取出當前座標點的灰度值
			target=a*gray+b;
			if(target<0)  target=0;
			if(target>255)  target=255;
			*(char*)(grayImage->imageData+h*grayImage->widthStep+grayImage->nChannels*w) = target;      //將目標值寫入目標圖像
		}
	}
	return true;
}

效果圖片

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章