Bayer图像转RGB

来源:互联网 发布:修改linux的ip地址 编辑:程序博客网 时间:2024/05/16 10:02
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;elseg = (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;elsetemVal = ((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的白色参考值点的阈值Tdouble 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, CrYCbCr[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,Mrfor (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,Drfor (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;}


原创粉丝点击