目录
前言
插值算法
边缘感应插值算法
代码示例
相机生成的图像一般是bayer阵列的raw图,这时候如果转换成我们需要的rgb图像,就需要对应的bayer插值算法将丢失的rgb信息通过算法补齐
常见的插值算法一般有如下几种
由于边缘感应插值算法用很多,主要不同的点是边缘处如何检测,本文的方法依赖以下的论文,有兴趣的小伙伴可以看一下这个论文,链接在下方
依赖的论文
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_EdgeSense(const uint8_t *B2R_RESTRICT bayer, uint8_t *B2R_RESTRICT rgb, int sx, int sy, int tile)
{
uint8_t *outR, *outG, *outB;
B2R_REGISTER int i3, j3, base;
int i, j;
int dh, dv;
int tmp;
int sx3=sx*3;
// sx and sy should be even
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[0];
outG = &rgb[1];
outB = &rgb[2];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[2];
outG = &rgb[1];
outB = &rgb[0];
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
switch (tile) {
case DC1394_COLOR_FILTER_GRBG: //---------------------------------------------------------
case DC1394_COLOR_FILTER_GBRG:
// copy original RGB data to output images
for (i = 0, i3=0; i < sy*sx; i += (sx<<1), i3 += (sx3<<1)) {
for (j = 0, j3=0; j < sx; j += 2, j3+=6) {
base=i3+j3;
outG[base] = bayer[i + j];
outG[base + sx3 + 3] = bayer[i + j + sx + 1];
outR[base + 3] = bayer[i + j + 1];
outB[base + sx3] = bayer[i + j + sx];
}
}
// process GREEN channel
for (i3= 3*sx3; i3 < (sy - 2)*sx3; i3 += (sx3<<1)) {
for (j3=6; j3 < sx3 - 9; j3+=6) {
base=i3+j3;
dh = abs(((outB[base - 6] +
outB[base + 6]) >> 1) -
outB[base]);
dv = abs(((outB[base - (sx3<<1)] +
outB[base + (sx3<<1)]) >> 1) -
outB[base]);
tmp = (((outG[base - 3] + outG[base + 3]) >> 1) * (dh<=dv) +
((outG[base - sx3] + outG[base + sx3]) >> 1) * (dh>dv));
//tmp = (dh==dv) ? tmp>>1 : tmp;
CLIP(tmp, outG[base]);
}
}
for (i3=2*sx3; i3 < (sy - 3)*sx3; i3 += (sx3<<1)) {
for (j3=9; j3 < sx3 - 6; j3+=6) {
base=i3+j3;
dh = abs(((outR[base - 6] +
outR[base + 6]) >>1 ) -
outR[base]);
dv = abs(((outR[base - (sx3<<1)] +
outR[base + (sx3<<1)]) >>1 ) -
outR[base]);
tmp = (((outG[base - 3] + outG[base + 3]) >> 1) * (dh<=dv) +
((outG[base - sx3] + outG[base + sx3]) >> 1) * (dh>dv));
//tmp = (dh==dv) ? tmp>>1 : tmp;
CLIP(tmp, outG[base]);
}
}
// process RED channel
for (i3=0; i3 < (sy - 1)*sx3; i3 += (sx3<<1)) {
for (j3=6; j3 < sx3 - 3; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outR[base - 3] -
outG[base - 3] +
outR[base + 3] -
outG[base + 3]) >> 1);
CLIP(tmp, outR[base]);
}
}
for (i3=sx3; i3 < (sy - 2)*sx3; i3 += (sx3<<1)) {
for (j3=3; j3 < sx3; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outR[base - sx3] -
outG[base - sx3] +
outR[base + sx3] -
outG[base + sx3]) >> 1);
CLIP(tmp, outR[base]);
}
for (j3=6; j3 < sx3 - 3; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outR[base - sx3 - 3] -
outG[base - sx3 - 3] +
outR[base - sx3 + 3] -
outG[base - sx3 + 3] +
outR[base + sx3 - 3] -
outG[base + sx3 - 3] +
outR[base + sx3 + 3] -
outG[base + sx3 + 3]) >> 2);
CLIP(tmp, outR[base]);
}
}
// process BLUE channel
for (i3=sx3; i3 < sy*sx3; i3 += (sx3<<1)) {
for (j3=3; j3 < sx3 - 6; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outB[base - 3] -
outG[base - 3] +
outB[base + 3] -
outG[base + 3]) >> 1);
CLIP(tmp, outB[base]);
}
}
for (i3=2*sx3; i3 < (sy - 1)*sx3; i3 += (sx3<<1)) {
for (j3=0; j3 < sx3 - 3; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outB[base - sx3] -
outG[base - sx3] +
outB[base + sx3] -
outG[base + sx3]) >> 1);
CLIP(tmp, outB[base]);
}
for (j3=3; j3 < sx3 - 6; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outB[base - sx3 - 3] -
outG[base - sx3 - 3] +
outB[base - sx3 + 3] -
outG[base - sx3 + 3] +
outB[base + sx3 - 3] -
outG[base + sx3 - 3] +
outB[base + sx3 + 3] -
outG[base + sx3 + 3]) >> 2);
CLIP(tmp, outB[base]);
}
}
break;
case DC1394_COLOR_FILTER_BGGR: //---------------------------------------------------------
case DC1394_COLOR_FILTER_RGGB:
// copy original RGB data to output images
for (i = 0, i3=0; i < sy*sx; i += (sx<<1), i3 += (sx3<<1)) {
for (j = 0, j3=0; j < sx; j += 2, j3+=6) {
base=i3+j3;
outB[base] = bayer[i + j];
outR[base + sx3 + 3] = bayer[i + sx + (j + 1)];
outG[base + 3] = bayer[i + j + 1];
outG[base + sx3] = bayer[i + sx + j];
}
}
// process GREEN channel
for (i3=2*sx3; i3 < (sy - 2)*sx3; i3 += (sx3<<1)) {
for (j3=6; j3 < sx3 - 9; j3+=6) {
base=i3+j3;
dh = abs(((outB[base - 6] +
outB[base + 6]) >> 1) -
outB[base]);
dv = abs(((outB[base - (sx3<<1)] +
outB[base + (sx3<<1)]) >> 1) -
outB[base]);
tmp = (((outG[base - 3] + outG[base + 3]) >> 1) * (dh<=dv) +
((outG[base - sx3] + outG[base + sx3]) >> 1) * (dh>dv));
//tmp = (dh==dv) ? tmp>>1 : tmp;
CLIP(tmp, outG[base]);
}
}
for (i3=3*sx3; i3 < (sy - 3)*sx3; i3 += (sx3<<1)) {
for (j3=9; j3 < sx3 - 6; j3+=6) {
base=i3+j3;
dh = abs(((outR[base - 6] +
outR[base + 6]) >> 1) -
outR[base]);
dv = abs(((outR[base - (sx3<<1)] +
outR[base + (sx3<<1)]) >> 1) -
outR[base]);
tmp = (((outG[base - 3] + outG[base + 3]) >> 1) * (dh<=dv) +
((outG[base - sx3] + outG[base + sx3]) >> 1) * (dh>dv));
//tmp = (dh==dv) ? tmp>>1 : tmp;
CLIP(tmp, outG[base]);
}
}
// process RED channel
for (i3=sx3; i3 < (sy - 1)*sx3; i3 += (sx3<<1)) { // G-points (1/2)
for (j3=6; j3 < sx3 - 3; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outR[base - 3] -
outG[base - 3] +
outR[base + 3] -
outG[base + 3]) >>1);
CLIP(tmp, outR[base]);
}
}
for (i3=2*sx3; i3 < (sy - 2)*sx3; i3 += (sx3<<1)) {
for (j3=3; j3 < sx3; j3+=6) { // G-points (2/2)
base=i3+j3;
tmp = outG[base] +
((outR[base - sx3] -
outG[base - sx3] +
outR[base + sx3] -
outG[base + sx3]) >> 1);
CLIP(tmp, outR[base]);
}
for (j3=6; j3 < sx3 - 3; j3+=6) { // B-points
base=i3+j3;
tmp = outG[base] +
((outR[base - sx3 - 3] -
outG[base - sx3 - 3] +
outR[base - sx3 + 3] -
outG[base - sx3 + 3] +
outR[base + sx3 - 3] -
outG[base + sx3 - 3] +
outR[base + sx3 + 3] -
outG[base + sx3 + 3]) >> 2);
CLIP(tmp, outR[base]);
}
}
// process BLUE channel
for (i = 0,i3=0; i < sy*sx; i += (sx<<1), i3 += (sx3<<1)) {
for (j = 1, j3=3; j < sx - 2; j += 2, j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outB[base - 3] -
outG[base - 3] +
outB[base + 3] -
outG[base + 3]) >> 1);
CLIP(tmp, outB[base]);
}
}
for (i3=sx3; i3 < (sy - 1)*sx3; i3 += (sx3<<1)) {
for (j3=0; j3 < sx3 - 3; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outB[base - sx3] -
outG[base - sx3] +
outB[base + sx3] -
outG[base + sx3]) >> 1);
CLIP(tmp, outB[base]);
}
for (j3=3; j3 < sx3 - 6; j3+=6) {
base=i3+j3;
tmp = outG[base] +
((outB[base - sx3 - 3] -
outG[base - sx3 - 3] +
outB[base - sx3 + 3] -
outG[base - sx3 + 3] +
outB[base + sx3 - 3] -
outG[base + sx3 - 3] +
outB[base + sx3 + 3] -
outG[base + sx3 + 3]) >> 2);
CLIP(tmp, outB[base]);
}
}
break;
}
ClearBorders(rgb, sx, sy, 3);
return 0;
}