Bayer图像转RGB

Bayer图像不做赘述


一、Bayer(GRBG)图像转RGB


处理方法:对于某个像素点,存在的分量值不变化,缺少的两个分量值使用Correlation-Adjusted算法

QImage CorrelationAdjusted(QImage srcImg, int type)
{
	int imgW = srcImg.width();
	int imgH = srcImg.height();

	// 	if (srcImg.format() != QImage::Format_Grayscale8)
	// 		return srcImg;

	if (type == 0)
		return srcImg;

	QImage dstImg(imgW, imgH, QImage::Format_Grayscale8);
	QImage colImg(imgW, imgH, QImage::Format_RGB888);

	uchar *srcImgData;// = srcImg.bits();
	uchar *dstImgData;// = dstImg.bits();
	uchar *colImgData;// = colImg.bits();

	uchar r, g, b, temVal;

	for (int i = 0; i < imgH; i++)
	{
		
		dstImgData = dstImg.scanLine(i);
		colImgData = colImg.scanLine(i);
		srcImgData = srcImg.scanLine(i);
		
		//判断边缘两行
		if (i < 2 || i >= imgH - 2)
		{
			int Raver, Rtot, Gaver, Gtot, Baver, Btot;
			for (int j = 0; j < imgW; j++)
			{
				Raver = Rtot = Gaver = Gtot = Baver = Btot = 0;
				if (i % 2 == j % 2)
				{
					if (i > 0)
					{
						if (i % 2) Raver += srcImg.scanLine(i - 1)[j], Rtot++;
						else Baver += srcImg.scanLine(i - 1)[j], Btot++;
					}
					if (i < imgH - 1)
					{
						if (i % 2) Raver += srcImg.scanLine(i + 1)[j], Rtot++;
						else Baver += srcImg.scanLine(i + 1)[j], Btot++;
					}
					if (j > 0)
					{
						if (i % 2) Baver += srcImgData[j - 1], Btot++;
						else Raver += srcImgData[j - 1], Rtot++;
					}
					if (j < imgW - 1)
					{
						if (i % 2) Baver += srcImgData[j + 1], Btot++;
						else Raver += srcImgData[j + 1], Rtot++;
					}
					Gaver = srcImgData[j], Gtot = 1;
				}
				else
				{
					if (i > 0) Gaver += srcImg.scanLine(i - 1)[j], Gtot++;
					if (i < imgH - 1) Gaver += srcImg.scanLine(i + 1)[j], Gtot++;
					if (j > 0) Gaver += srcImgData[j - 1], Gtot++;
					if (j < imgW - 1) Gaver += srcImgData[j + 1], Gtot++;
					
					int Naver = 0, Ntot = 0;
					if (i > 0)
					{
						if (j > 0) Naver += srcImg.scanLine(i - 1)[j - 1], Ntot++;
						if (j < imgW - 1) Naver += srcImg.scanLine(i - 1)[j + 1], Ntot++;
					}
					if (i < imgH - 1)
					{
						if (j > 0) Naver += srcImg.scanLine(i + 1)[j - 1], Ntot++;
						if (j < imgW - 1) Naver += srcImg.scanLine(i + 1)[j + 1], Ntot++;
					}
					if (i % 2)
					{
						Baver = srcImgData[j], Btot = 1;
						Raver = Naver, Rtot = Ntot;
					}
					else
					{
						Raver = srcImgData[j], Rtot = 1;
						Baver = Naver, Btot = Ntot;
					}
				}
				colImgData[j * 3] = Raver / Rtot;
				colImgData[j * 3 + 1] = Gaver / Gtot;
				colImgData[j * 3 + 2] = Baver / Btot;
			}
			continue;
		}

		uchar *aboveLine2 = srcImg.scanLine(i - 2);
		uchar *aboveLine1 = srcImg.scanLine(i - 1);

		uchar *belowLine1 = srcImg.scanLine(i + 1);
		uchar *belowLine2 = srcImg.scanLine(i + 2);

		for (int j = 0; j < imgW; j++)
		{
			/*边缘两列*/
			if (j < 2 || j >= imgW - 2)
			{
				int Raver, Rtot, Gaver, Gtot, Baver, Btot;
				Raver = Rtot = Gaver = Gtot = Baver = Btot = 0;
				if (i % 2 == j % 2)
				{
					if (i % 2)
					{
						Raver += aboveLine1[j], Rtot++;
						Raver += belowLine1[j], Rtot++;
					}
					else
					{
						Baver += aboveLine1[j], Btot++;
						Baver += belowLine1[j], Btot++;
					}
					
					if (j > 0)
					{
						if (i % 2) Baver += srcImgData[j - 1], Btot++;
						else Raver += srcImgData[j - 1], Rtot++;
					}
					if (j < imgW - 1)
					{
						if (i % 2) Baver += srcImgData[j + 1], Btot++;
						else Raver += srcImgData[j + 1], Rtot++;
					}
					Gaver = srcImgData[j], Gtot = 1;
				}
				else
				{
					Gaver += aboveLine1[j], Gtot++;
					Gaver += belowLine1[j], Gtot++;
					if (j > 0) Gaver += srcImgData[j - 1], Gtot++;
					if (j < imgW - 1) Gaver += srcImgData[j + 1], Gtot++;

					int Naver = 0, Ntot = 0;
					if (j > 0)
					{
						Naver += aboveLine1[j - 1], Ntot++; 
						Naver += belowLine1[j - 1], Ntot++;
					}
					if (i < imgH - 1)
					{
						Naver += belowLine1[j + 1], Ntot++; 
						Naver += aboveLine1[j + 1], Ntot++;
					}

					if (i % 2)
					{
						Baver = srcImgData[j], Btot = 1;
						Raver = Naver, Rtot = Ntot;
					}
					else
					{
						Raver = srcImgData[j], Rtot = 1;
						Baver = Naver, Btot = Ntot;
					}
				}
				r = (uchar)(Raver / Rtot);
				g = (uchar)(Gaver / Gtot);
				b = (uchar)(Baver / Btot);
			}
			/*普通行列*/
			else
			{
				if (i % 2 == j % 2)
				{
					r = i % 2 ? (aboveLine1[j] + belowLine1[j]) / 2 : (srcImgData[j - 1] + srcImgData[j + 1]) / 2;
					g = srcImgData[j];
					b = i % 2 ? (srcImgData[j - 1] + srcImgData[j + 1]) / 2 : (aboveLine1[j] + belowLine1[j]) / 2;
				}
				else
				{
					r = i % 2 ? (aboveLine1[j - 1] + aboveLine1[j + 1] + belowLine1[j - 1] + belowLine1[j + 1]) / 4 : srcImgData[j];

					short G1, G2, G3, G4, N1, N2, N3, N4;
					G1 = aboveLine1[j]; G2 = srcImgData[j + 1];
					G3 = belowLine1[j]; G4 = srcImgData[j - 1];
					N1 = aboveLine2[j]; N2 = srcImgData[j + 2];
					N3 = belowLine2[j]; N4 = srcImgData[j - 2];

					if (abs(N1 - N3) < abs(N2 - N4))
						g = (G1 + G3) / 2;
					else if (abs(N1 - N3) > abs(N2 - N4))
						g = (G3 + G4) / 2;
					else
						g = (G1 + G2 + G3 + G4) / 4;

					b = i % 2 ? srcImgData[j] : (aboveLine1[j - 1] + aboveLine1[j + 1] + belowLine1[j - 1] + belowLine1[j + 1]) / 4;
				}
			}

			if (type == 1)
				temVal = r;
			else if (type == 2)
				temVal = g;
			else if (type == 3)
				temVal = b;
			else if (type == 5)
				temVal = b - r > 0 ? b - r : r - b;
			else
				temVal = ((r + g) / 2 - b > 0) ? ((r + g) / 2 - b) : 0;

			colImgData[j * 3] = r;
			colImgData[j * 3 + 1] = g;
			colImgData[j * 3 + 2] = b;
			dstImgData[j] = temVal;
		}
	}
	if (type == 4)
		return colImg;
	return dstImg;
}

二、白平衡处理,使用灰度世界GrayWorld方法

QImage ImageGrayWorld(QImage srcImg)
{
	int imgW = srcImg.width();
	int imgH = srcImg.height();
	QImage dstImg(imgW, imgH, QImage::Format_RGB888);
	uchar *srcData;// = srcImg.bits();
	uchar *dstData;// = dstImg.bits();

	//计算R G B 三分量的平均灰度
	double Raver = 0, Gaver = 0, Baver = 0;
	for (int i = 0; i < imgH; i++)
	{
		srcData = srcImg.scanLine(i);
		for (int j = 0; j < imgW; j++)
		{
			Raver += srcData[j * 3];
			Gaver += srcData[j * 3 + 1];
			Baver += srcData[j * 3 + 2];
		}
	}
	Raver /= (imgW * imgH);
	Gaver /= (imgW * imgH);
	Baver /= (imgW * imgH);

	//计算各通道增益
	double K = (Raver + Gaver + Baver) / 3;
	double Kr = K / Raver;
	double Kg = K / Gaver;
	double Kb = K / Baver;

	//重算RGB值
	for (int i = 0; i < imgH; i++)
	{
		srcData = srcImg.scanLine(i);
		dstData = dstImg.scanLine(i);
		for (int j = 0; j < imgW; j++)
		{
			dstData[j * 3] = srcData[j * 3] * Kr > 255 ? 255 : srcData[j * 3] * Kr;
			dstData[j * 3 + 1] = srcData[j * 3 + 1] * Kg > 255 ? 255 : srcData[j * 3 + 1] * Kg;
			dstData[j * 3 + 2] = srcData[j * 3 + 2] * Kb > 255 ? 255 : srcData[j * 3 + 2] * Kb;
		}
	}
	return dstImg;
}


三、白平衡处理,完美反射方法

QImage ImagePerfectReflector(QImage srcImg)
{
	int imgH = srcImg.height();
	int imgW = srcImg.width();
	QImage dstImg(imgW, imgH, QImage::Format_RGB888);

	uchar *srcData;
	uchar *dstData;

	int Hist[255 * 3 + 10];
	memset(Hist, 0, sizeof(Hist));
	short **Sum = new short*[imgH];
	for (int i = 0; i < imgH; i++)
		Sum[i] = new short[imgW];

	//计算每个像素的R/G/B之和
	short maxValue = 0;
	for (int i = 0; i < imgH; i++)
	{
		srcData = srcImg.scanLine(i);
		for (int j = 0; j < imgW; j++)
		{
			short sum = srcData[j * 3] + srcData[j * 3 + 1] + srcData[j * 3 + 2];
			Hist[sum]++;
			Sum[i][j] = sum;
			if (maxValue < sum)
				maxValue = sum;
		}
	}

	//按照R+G+B值得大小计算出前10%或其他Ratio的白色参考值点的阈值T
	double Ratio = 8;
	double temSum = 0;
	short Threshold;
	for (short i = 765; i >= 0; i--)
	{
		temSum += Hist[i];
		if (temSum > imgW * imgH * Ratio / 100)
		{
			Threshold = i;
			break;
		}
	}

	//遍历图像,计算R+G+B值大于Threshold的所有点的R/G/B分量的累积和的平均值
	double Raver = 0, Gaver = 0, Baver = 0;
	int totAmount = 0;
	for (int i = 0; i < imgH; i++)
	{
		srcData = srcImg.scanLine(i);
		for (int j = 0; j < imgW; j++)
		{
			if (Sum[i][j] > Threshold)
			{
				Raver += srcData[j * 3];
				Gaver += srcData[j * 3 + 1];
				Baver += srcData[j * 3 + 2];
				totAmount++;
			}
		}
	}
	Raver /= totAmount;
	Gaver /= totAmount;
	Baver /= totAmount;

	//对每个点将像素量化到[0,255]之间
	short r, g, b;
	for (int i = 0; i < imgH; i++)
	{
		srcData = srcImg.scanLine(i);
		dstData = dstImg.scanLine(i);
		for (int j = 0; j < imgW; j++)
		{
			r = srcData[j * 3] * maxValue / Raver;
			g = srcData[j * 3 + 1] * maxValue / Gaver;
			b = srcData[j * 3 + 2] * maxValue / Baver;
			if (r > 255) r = 255;
			else if (r < 0) r = 0;
			if (g > 255) g = 255;
			else if (g < 0) g = 0;
			if (b > 255) b = 255;
			else if (b < 0) b = 0;

			dstData[j * 3] = r;
			dstData[j * 3 + 1] = g;
			dstData[j * 3 + 2] = b;
		}
	}
	for (int i = 0; i < imgH; i++)
		delete[] Sum[i];
	delete[] Sum;

	return dstImg;
}

4.白平衡处理,动态阈值方法

QImage ImageAutoWhiteBalance(QImage srcImg)
{
	int imgH = srcImg.height();
	int imgW = srcImg.width();
	QImage dstImg = QImage(imgW, imgH, QImage::Format_RGB888);

	uchar *srcData;
	uchar *dstData;

	uchar **YCbCr = new uchar*[imgH];
	for (int i = 0; i < imgH; i++)
		YCbCr[i] = new uchar[imgW * 3 + 10];

	int Red, Green, Blue;
	int maxY = 0;

	//RGB 转 YCbCr 系数
	int mul = 20;
	int semul = 1 << (mul - 1);
	int YiR = (int)( 0.299000f * (1 << mul) + 0.5);
	int YiG = (int)( 0.587000f * (1 << mul) + 0.5);
	int YiB = (int)( 0.114000f * (1 << mul) + 0.5);
	int CbR = (int)(-0.168736f * (1 << mul) + 0.5);
	int CbG = (int)(-0.331264f * (1 << mul) + 0.5);
	int CbB = (int)( 0.500000f * (1 << mul) + 0.5);
	int CrR = (int)( 0.500000f * (1 << mul) + 0.5);
	int CrG = (int)(-0.418688f * (1 << mul) + 0.5);
	int CrB = (int)(-0.081312f * (1 << mul) + 0.5);

	for (int i = 0; i < imgH; i++)
	{
		srcData = srcImg.scanLine(i);
		for (int j = 0; j < imgW; j++)
		{
			Red = srcData[j * 3];
			Green = srcData[j * 3 + 1];
			Blue = srcData[j * 3 + 2];
			//Y, Cb, Cr
			YCbCr[i][j * 3] = (byte)((YiR * Red + YiG * Green + YiB * Blue + semul) >> mul);
			YCbCr[i][j * 3 + 1] = (byte)(128 + ((CbR * Red + CbG * Green + CbB * Blue + semul) >> mul));
			YCbCr[i][j * 3 + 2] = (byte)(128 + ((CrR * Red + CrG * Green + CrB * Blue + semul) >> mul));

			if (maxY < YCbCr[i][j * 3])
				maxY = YCbCr[i][j * 3];
		}
	}
	int deltW = imgW / 4;
	int deltH = imgH / 3;
	double Db[12], Dr[12];
	double Mb[12], Mr[12];
	short *HistY = new short[maxY + 1];
	double *HistRGB = new double[3 * (maxY + 1)];
	for (int i = 0; i < 3 * (maxY + 1); i++)
		HistRGB[i] = 0;
	for (int i = 0; i < maxY + 1; i++)
		HistY[i] = 0;

	int totWhite = 0;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			Mb[i * 4 + j] = Mr[i * 4 + j] = 0;
			Db[i * 4 + j] = Dr[i * 4 + j] = 0;

			//计算每个区域Cb,Cr分量平均值Mb,Mr
			for (int r = i * deltH; r < (i + 1) * deltH; r++)
			{
				for (int c = j * deltW; c < (j + 1) * deltW; c++)
				{
					Mb[i * 4 + j] += YCbCr[r][c * 3 + 1];
					Mr[i * 4 + j] += YCbCr[r][c * 3 + 2];
				}
			}
			Mb[i * 4 + j] /= (deltW * deltH);
			Mr[i * 4 + j] /= (deltW * deltH);
			//计算每个区域Cb,Cr分量的绝对差的累积值Db,Dr
			for (int r = i * deltH; r < (i + 1) * deltH; r++)
			{
				for (int c = j * deltW; c < (j + 1) * deltW; c++)
				{
					Db[i * 4 + j] += abs(YCbCr[r][c * 3 + 1] - Mb[i * 4 + j]);
					Dr[i * 4 + j] += abs(YCbCr[r][c * 3 + 2] - Mr[i * 4 + j]);
				}
			}
			Db[i * 4 + j] /= (deltW * deltH);
			Dr[i * 4 + j] /= (deltW * deltH);

			//确定白色参考点
			for (int r = i * deltH; r < (i + 1) * deltH; r++)
			{
				srcData = srcImg.scanLine(r);
				for (int c = j * deltW; c < (j + 1) * deltW; c++)
				{
					if (abs(YCbCr[r][c * 3 + 1] - (Mb[i * 4 + j] + Db[i * 4 + j] * abs(Mb[i * 4 + j]) / Mb[i * 4 + j])) < 1.5 * Db[i * 4 + j]
						&& abs(YCbCr[r][c * 3 + 2] - (1.5 * Mr[i * 4 + j] + Dr[i * 4 + j] * abs(Mr[i * 4 + j]) / Mr[i * 4 + j])))
					{
						int ValueY = (int)YCbCr[r][c * 3];
						HistY[ValueY]++;
						totWhite++;
						HistRGB[ValueY * 3] += srcData[c * 3];
						HistRGB[ValueY * 3 + 1] += srcData[c * 3 + 1];
						HistRGB[ValueY * 3 + 2] += srcData[c * 3 + 2];
					}
				}
			}

		}
	}

	int totNum = 0;

	//按大小取其亮度值10%的为最终确定的白色参考点,并计算R,G,B平均值
	double Raver = 0, Gaver = 0, Baver = 0;
	for (int i = maxY; i >= 0; i--)
	{
		totNum += HistY[i];
		Raver += HistRGB[i * 3];
		Gaver += HistRGB[i * 3 + 1];
		Baver += HistRGB[i * 3 + 2];
		if (1.0 * totNum / totWhite >= 0.1)
		{
			Raver /= totNum;
			Gaver /= totNum;
			Baver /= totNum;
			break;
		}
	}
	//计算每个通道的增益
	double Rgain = maxY / Raver;
	double Ggain = maxY / Gaver;
	double Bgain = maxY / Baver;

	//计算最终每个通道的分量值
	for (int i = 0; i < imgH; i++)
	{
		srcData = srcImg.scanLine(i);
		dstData = dstImg.scanLine(i);
		for (int j = 0; j < imgW; j++)
		{
			dstData[j * 3] = Rgain*srcData[j * 3] > 255 ? 255 : Rgain*srcData[j * 3];
			dstData[j * 3 + 1] = Ggain*srcData[j * 3 + 1] > 255 ? 255 : Ggain*srcData[j * 3 + 1];
			dstData[j * 3 + 2] = Bgain*srcData[j * 3 + 2] > 255 ? 255 : Bgain*srcData[j * 3 + 2];
		}
	}
	
	//内存释放
	delete[] HistY;
	delete[] HistRGB;
	for (int i = 0; i < imgH; i++)
		delete[] YCbCr[i];
	delete[] YCbCr;
	return dstImg;
}


  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值