目录
前言
相机生成的图像一般是bayer阵列的raw图,这时候如果转换成我们需要的rgb图像,就需要对应的bayer插值算法将丢失的rgb信息通过算法补齐
插值算法
常见的插值算法一般有如下几种
双线性插值算法
双线性插值是再bayer转rgb中最常用的方法。由于直接取旁边像素容易使图像马赛克话,因此,双线性插值通过取其相邻像素的平均值来内插每个通道中的遗漏值,比如蓝色通道,缺少了红色和绿色,就以周边的红色和绿色来算平均值,
选取当前需要插值的像素点,以3*3矩阵去分割,缺少的像素就按下图算平均值即可
代码示例
void ClearBorders(uint8_t *rgb, int sx, int sy, int w)
{
int i, j;
// black edges are added with a width w:
i = 3 * sx * w - 1;
j = 3 * sx * sy - 1;
while (i >= 0) {
rgb[i--] = 0;
rgb[j--] = 0;
}
int low = sx * (w - 1) * 3 - 1 + w * 3;
i = low + sx * (sy - w * 2 + 1) * 3;
while (i > low) {
j = 6 * w;
while (j > 0) {
rgb[i--] = 0;
j--;
}
i -= (sx - 2 * w) * 3;
}
}
int bayer_Bilinear(const uint8_t *B2R_RESTRICT bayer, uint8_t *B2R_RESTRICT rgb, int sx, int sy, int tile)
{
const int bayerStep = sx;
const int rgbStep = 3 * sx;
int width = sx;
int height = sy;
/*
the two letters of the OpenCV name are respectively
the 4th and 3rd letters from the blinky name,
and we also have to switch R and B (OpenCV is BGR)
CV_BayerBG2BGR <-> DC1394_COLOR_FILTER_BGGR
CV_BayerGB2BGR <-> DC1394_COLOR_FILTER_GBRG
CV_BayerGR2BGR <-> DC1394_COLOR_FILTER_GRBG
int blue = tile == CV_BayerBG2BGR || tile == CV_BayerGB2BGR ? -1 : 1;
int start_with_green = tile == CV_BayerGB2BGR || tile == CV_BayerGR2BGR;
*/
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? -1 : 1;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
ClearBorders(rgb, sx, sy, 1);
rgb += rgbStep + 3 + 1;
height -= 2;
width -= 2;
for (; height--; bayer += bayerStep, rgb += rgbStep) {
int t0, t1;
const uint8_t *bayerEnd = bayer + width;
if (start_with_green) {
/* OpenCV has a bug in the next line, which was
t0 = (bayer[0] + bayer[bayerStep * 2] + 1) >> 1; */
t0 = (bayer[1] + bayer[bayerStep * 2 + 1] + 1) >> 1;
t1 = (bayer[bayerStep] + bayer[bayerStep + 2] + 1) >> 1;
rgb[-blue] = (uint8_t) t0;
rgb[0] = bayer[bayerStep + 1];
rgb[blue] = (uint8_t) t1;
bayer++;
rgb += 3;
}
if (blue > 0) {
for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] +
bayer[bayerStep * 2 + 2] + 2) >> 2;
t1 = (bayer[1] + bayer[bayerStep] +
bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] +
2) >> 2;
rgb[-1] = (uint8_t) t0;
rgb[0] = (uint8_t) t1;
rgb[1] = bayer[bayerStep + 1];
t0 = (bayer[2] + bayer[bayerStep * 2 + 2] + 1) >> 1;
t1 = (bayer[bayerStep + 1] + bayer[bayerStep + 3] +
1) >> 1;
rgb[2] = (uint8_t) t0;
rgb[3] = bayer[bayerStep + 2];
rgb[4] = (uint8_t) t1;
}
} else {
for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] +
bayer[bayerStep * 2 + 2] + 2) >> 2;
t1 = (bayer[1] + bayer[bayerStep] +
bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] +
2) >> 2;
rgb[1] = (uint8_t) t0;
rgb[0] = (uint8_t) t1;
rgb[-1] = bayer[bayerStep + 1];
t0 = (bayer[2] + bayer[bayerStep * 2 + 2] + 1) >> 1;
t1 = (bayer[bayerStep + 1] + bayer[bayerStep + 3] +
1) >> 1;
rgb[4] = (uint8_t) t0;
rgb[3] = bayer[bayerStep + 2];
rgb[2] = (uint8_t) t1;
}
}
if (bayer < bayerEnd) {
t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] +
bayer[bayerStep * 2 + 2] + 2) >> 2;
t1 = (bayer[1] + bayer[bayerStep] +
bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] +
2) >> 2;
rgb[-blue] = (uint8_t) t0;
rgb[0] = (uint8_t) t1;
rgb[blue] = bayer[bayerStep + 1];
bayer++;
rgb += 3;
}
bayer -= width;
rgb -= width * 3;
blue = -blue;
start_with_green = !start_with_green;
}
return 0;
}
版权声明:本文为somiss03原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。