目录
前言
插值算法
高质量插值算法
代码示例
相机生成的图像一般是bayer阵列的raw图,这时候如果转换成我们需要的rgb图像,就需要对应的bayer插值算法将丢失的rgb信息通过算法补齐
常见的插值算法一般有如下几种
该方法由Malvar等人提出。高质量插值背后的想法是,要对每个通道中的丢失像素进行插值,仅使用位于同一通道上的相邻像素可能并不准确。换句话说,为了内插图2中的Gx等绿色像素,我们需要使用其相邻绿色像素的值以及现有通道的值。例如,如果在Gx的位置有一个红色值,则必须使用该值以及相邻的可用绿色值。他们称其为方法梯度校正插值。
最后,他们提出了8种不同的5 * 5滤镜,如图3所示。我们需要将滤镜卷积为要插值的像素。
例如,如果我们要估计绿色像素的值,而我们在该位置具有红色像素的值,则需要使用第一个过滤器。我们需要将滤波器中给定的权重乘以给定通道的值,然后将其平均值除以8,因为每个滤波器的权重之和为8。
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_HQLinear(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;
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> 1);
t1 = rgb[0] * 5 +
((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 3]) << 2)
- bayer[bayerStep2]
- bayer[bayerStep + 1]
- bayer[bayerStep + 3]
- bayer[bayerStep3 + 1]
- bayer[bayerStep3 + 3]
- bayer[bayerStep2 + 4]
+ ((bayer[2] + bayer[bayerStep4 + 2] + 1) >> 1);
t0 = (t0 + 4) >> 3;
CLIP(t0, rgb[-blue]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[blue]);
bayer++;
rgb += 3;
}
if (blue > 0) {
for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
/* B at B */
rgb[1] = bayer[bayerStep2 + 2];
/* R at B */
t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
-
(((bayer[2] + bayer[bayerStep2] +
bayer[bayerStep2 + 4] + bayer[bayerStep4 +
2]) * 3 + 1) >> 1)
+ rgb[1] * 6;
/* G at B */
t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
bayer[bayerStep2 + 3] + bayer[bayerStep3 + 2]) << 1)
- (bayer[2] + bayer[bayerStep2] +
bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
+ (rgb[1] << 2);
t0 = (t0 + 4) >> 3;
CLIP(t0, rgb[-1]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[0]);
/* at green pixel */
rgb[3] = bayer[bayerStep2 + 3];
t0 = rgb[3] * 5
+ ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2)
- bayer[3]
- bayer[bayerStep + 2]
- bayer[bayerStep + 4]
- bayer[bayerStep3 + 2]
- bayer[bayerStep3 + 4]
- bayer[bayerStep4 + 3]
+
((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] +
1) >> 1);
t1 = rgb[3] * 5 +
((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2)
- bayer[bayerStep2 + 1]
- bayer[bayerStep + 2]
- bayer[bayerStep + 4]
- bayer[bayerStep3 + 2]
- bayer[bayerStep3 + 4]
- bayer[bayerStep2 + 5]
+ ((bayer[3] + bayer[bayerStep4 + 3] + 1) >> 1);
t0 = (t0 + 4) >> 3;
CLIP(t0, rgb[2]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[4]);
}
} else {
for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
/* R at R */
rgb[-1] = bayer[bayerStep2 + 2];
/* B at R */
t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
-
(((bayer[2] + bayer[bayerStep2] +
bayer[bayerStep2 + 4] + bayer[bayerStep4 +
2]) * 3 + 1) >> 1)
+ rgb[-1] * 6;
/* G at R */
t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
bayer[bayerStep2 + 3] + bayer[bayerStep * 3 +
2]) << 1)
- (bayer[2] + bayer[bayerStep2] +
bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
+ (rgb[-1] << 2);
t0 = (t0 + 4) >> 3;
CLIP(t0, rgb[1]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[0]);
/* at green pixel */
rgb[3] = bayer[bayerStep2 + 3];
t0 = rgb[3] * 5
+ ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2)
- bayer[3]
- bayer[bayerStep + 2]
- bayer[bayerStep + 4]
- bayer[bayerStep3 + 2]
- bayer[bayerStep3 + 4]
- bayer[bayerStep4 + 3]
+
((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] +
1) >> 1);
t1 = rgb[3] * 5 +
((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2)
- bayer[bayerStep2 + 1]
- bayer[bayerStep + 2]
- bayer[bayerStep + 4]
- bayer[bayerStep3 + 2]
- bayer[bayerStep3 + 4]
- bayer[bayerStep2 + 5]
+ ((bayer[3] + bayer[bayerStep4 + 3] + 1) >> 1);
t0 = (t0 + 4) >> 3;
CLIP(t0, rgb[4]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[2]);
}
}
if (bayer < bayerEnd) {
/* B at B */
rgb[blue] = bayer[bayerStep2 + 2];
/* R at B */
t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1)
-
(((bayer[2] + bayer[bayerStep2] +
bayer[bayerStep2 + 4] + bayer[bayerStep4 +
2]) * 3 + 1) >> 1)
+ rgb[blue] * 6;
/* G at B */
t1 = (((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] +
bayer[bayerStep2 + 3] + bayer[bayerStep3 + 2])) << 1)
- (bayer[2] + bayer[bayerStep2] +
bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2])
+ (rgb[blue] << 2);
t0 = (t0 + 4) >> 3;
CLIP(t0, rgb[-blue]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[0]);
bayer++;
rgb += 3;
}
bayer -= width;
rgb -= width * 3;
blue = -blue;
start_with_green = !start_with_green;
}
return 0;
}