ISP PIPLINE (七) gamma

时间:2023-03-09 06:01:18
ISP PIPLINE (七) gamma

what is the gamma?

CCD、CMOS成像方式是通过像点中的“硅”感受光线的强弱而获得画面。而硅感光是物理成像,它真实地反应光线强度的变化,来多少就输出多少,因此它对光线的反应是线性的。但是它的伽马跟人眼的伽马是冲突的。

左图是人眼看到的画面,右图是ccd,cmos感受到的光电信号。绿线就是gamma曲线

ISP PIPLINE (七) gamma

why does correct with gamma?

就为获得人眼感知的图像。

how to correct the rgb format picture with gamma?

ISP gamma算法依然采用LUT将矫正系数或者映射关系存储起来,提高效率,不用再每次计算。

Gamma矫正的数值为1/2.2,大约为0.45。

附上代码:

#include <fstream>
#include <sstream>
#include <iostream>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <ctime>
#pragma warning( disable : 4244 )
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
	Mat imgMat = imread("test1.jpg");
	if (imgMat.empty())
		return -1;
	Mat imgGamma(imgMat.size(), CV_8UC3);

	// 建立Gamma矫正表
	float gamma_val = 0.45;
	unsigned char LUT[256] = { 0 };
	for (int i = 0; i < 256; i++)
		LUT[i] = (unsigned char)(pow((float)(i / 255.0), gamma_val)*(float)255.0);

	//遍历图像修改每一个通道上对应像素灰度值
	int nWidth = imgMat.rows;
	int nHight = imgMat.cols;
	for (int r = 0; r < nHight; r++)
	{
		for (int c = 0; c < nWidth; c++)
		{
			imgMat.data[r*nWidth * 3 + c * 3 + 0] = LUT[(uchar)imgMat.data[r*nWidth * 3 + c * 3 + 0]];
			imgMat.data[r*nWidth * 3 + c * 3 + 1] = LUT[(uchar)imgMat.data[r*nWidth * 3 + c * 3 + 1]];
			imgMat.data[r*nWidth * 3 + c * 3 + 2] = LUT[(uchar)imgMat.data[r*nWidth * 3 + c * 3 + 2]];
		}
	}
	imshow("3_2", imgMat);
	waitKey(0);
}

如下图(偷拍同事,肖像权已买,他发誓要把lena给顶替掉):

ISP PIPLINE (七) gamma