✓ c和 γ是正常数
✓ γ < 1 提高灰度级,在正比函数上方,使图像变亮
✓ γ > 1 降低灰度级,在正比函数下方,使图像变暗
创建滑动条改变Gama值
• 例:人体胸上部脊椎骨折的核磁共振图像
代码如下:
/*
*伽马变换--s=cr^γ
* 滑动条改变Gama值,γ<1时将较窄范围的暗色输入转换为较宽范围的输出值;γ>1时将较窄范围的亮色输入转换为较宽范围的输出值。
* OpenCV代码实现,注意此代码使用与灰度图像
*/
#include
#include
using namespace cv;
#define WINDOW_NAME "【滑动条改变Gama值】" //为窗口标题定义的宏
const int g_nMaxGamaValue = 25;//Alpha值的最大值
int g_nGamaValueSlider;//滑动条对应的变量
double g_spiderValue;
//声明存储图像的变量
Mat g_srcImage1;
Mat g_dstImage;
void gammaTransformation(cv::Mat& matInput, cv::Mat& matOutput, float fGamma, float fC /*= 1.0f*/)
{
assert(matInput.elemSize() == 1);
//构造输出图像
matOutput = cv::Mat::zeros(matInput.rows, matInput.cols, matInput.type());
//循环中尽量避免除法
float fNormalFactor = 1.0f / 255.0f;
for (size_t r = 0; r < (size_t)matInput.rows; r++)
{
unsigned char* pInput = matInput.data + r * matInput.step[0];
unsigned char* pOutput = matOutput.data + r * matOutput.step[0];
for (size_t c = 0; c < (size_t)matInput.cols; c++)
{
//gamma变换
float fOutput = std::pow(pInput[c] * fNormalFactor, fGamma) * fC;
//数值溢出判断
fOutput = fOutput > 1.0f ? 1.0f : fOutput;
//输出
pOutput[c] = static_cast
}
}
}
void gammaTransformation_lut(cv::Mat& matInput, cv::Mat& matOutput, float fGamma, float fC /*= 1.0f*/)
{
assert(matInput.elemSize() == 1);
//构造输出图像
matOutput = cv::Mat::zeros(matInput.rows, matInput.cols, matInput.type());
//循环中尽量避免除法
float fNormalFactor = 1.0f / 255.0f;
//构造查询表
std::vector
for (size_t m = 0; m < lookUp.size(); m++)
{
//gamma变换
float fOutput = std::pow(m * fNormalFactor, fGamma) * fC;
//数值溢出判断
fOutput = fOutput > 1.0f ? 1.0f : fOutput;
//输出
lookUp[m] = static_cast
}
for (size_t r = 0; r < (size_t)matInput.rows; r++)
{
unsigned char* pInput = matInput.data + r * matInput.step[0];
unsigned char* pOutput = matOutput.data + r * matOutput.step[0];
for (size_t c = 0; c < (size_t)matInput.cols; c++)
{
//查表gamma变换
pOutput[c] = lookUp[pInput[c]];
}
}
}
void MyGammaCorrection(Mat& src, Mat& dst, float fGamma)
{
CV_Assert(src.data);
// accept only char type matrices
CV_Assert(src.depth() != sizeof(uchar));
// build look up table
unsigned char lut[256];
for( int i = 0; i < 256; i++ )
{
lut[i] = saturate_cast
}
dst = src.clone();
const int channels = dst.channels();
switch(channels)
{
case 1:
{
MatIterator_
for( it = dst.begin
//*it = pow((float)(((*it))/255.0), fGamma) * 255.0;
*it = lut[(*it)];
break;
}
case 3:
{
MatIterator_
for( it = dst.begin
{
//(*it)[0] = pow((float)(((*it)[0])/255.0), fGamma) * 255.0;
//(*it)[1] = pow((float)(((*it)[1])/255.0), fGamma) * 255.0;
//(*it)[2] = pow((float)(((*it)[2])/255.0), fGamma) * 255.0;
(*it)[0] = lut[((*it)[0])];
(*it)[1] = lut[((*it)[1])];
(*it)[2] = lut[((*it)[2])];
}
break;
}
}
}
void on_Trackbar( int, void* )
{
float coef = 5;
//求出当前alpha值相对于最大值的比例
g_spiderValue = (float) g_nGamaValueSlider/(float)g_nMaxGamaValue ;
std::cout << coef * g_spiderValue << std::endl;
// gammaTransformation(g_srcImage1,g_dstImage, coef * g_spiderValue, 1 );
gammaTransformation_lut(g_srcImage1,g_dstImage, coef * g_spiderValue, 1 );
// MyGammaCorrection(g_srcImage1,g_dstImage, coef * g_spiderValue);
imshow( WINDOW_NAME, g_dstImage );
}
int main( int argc, char** argv )
{
g_srcImage1 = imread("10.tif", IMREAD_GRAYSCALE);
if( !g_srcImage1.data ) {
printf("读取第一幅图片错误,请确定目录下是否有imread函数指定图片存在~! \n");
return -1;
}
//设置滑动条初值为15
g_nGamaValueSlider = 15;
namedWindow(WINDOW_NAME, 1);
//在创建的窗体中创建一个滑动条控件
char TrackbarName[50];
sprintf( TrackbarName, "Gama值 %d", g_nMaxGamaValue );
createTrackbar( TrackbarName, WINDOW_NAME, &g_nGamaValueSlider, g_nMaxGamaValue, on_Trackbar );
//结果在回调函数中显示
on_Trackbar( g_nGamaValueSlider, 0 );
waitKey(0);
return 0;
}
原始图像,γ = 2.5校正图像:
原图像、γ = 0.4校正图像:
原图像、γ =5校正图像: