raw域上的去噪
2021-04-30 本文已影响0人
大梦一场三十一
一、基本概念
- raw域上的去噪会有一个好处,噪声形态没有被其他模块给破坏。具体的分析可以查看为什么在raw域降噪?
二、 一个简单的raw域去噪方法
- CN111784603A 上的去早方法
1. 获取y亮度值的图,YR,YGR,YGB,YB
1.1 中心值为R时,邻域3*3的像素中,Y=(4×R+2×∑G+∑B)/16
1.2 中心值为B时,Y=(4×B+2×∑G+∑R)/16
1.3 中心值为G时,Y=(4×G0+2×∑R+2×∑B)/8
2. 获取色度图,分别为R,GR,GB,B
3. 分别以亮度图为引导图,对于色度图来进行引导滤波来去除亮度上的噪声
3.1 在亮度图的9*9的区域中,对于以当前像素为中心的大小为3×3的匹配窗口进行匹配,搜索,按照绝对误差和(SAD算法)进行计算。即计算出差值的绝对值之和,不大于预设的亮度阈值,则为相似。
3.2 将亮度图所有相似的点进行累加取平均,获得初次去噪的亮度子图
3.3 将亮度图所有相似的点对应的色度图中的点进行累加取平均,获得初次去噪的色度子图
4. 将4张去噪色度图和4张去噪亮度图进行下采样获得第二色度图和亮度图
5. 将第二色度图和亮度图进行联合滤波
5.1 将第二亮度图进行SAD匹配
5.2 将第二色度图进行SAD匹配
5.3 如果亮度的差值的绝对值之和小于亮度阈值且色度的差值的绝对值之和小于色度阈值,则为相似。
5.4 将色度图上所有相似的点累加取平均,则可以获取当前色度图的去噪图。用来去除色度的噪声。
6. 通过上采样或者与采样前一样大的图,例如双线性插值、双三次插值、Cubic插值算法
(比较奇怪的是为什么要上下采样,加快速度吗?但是我看到了比较奇怪的条纹)
7. 应用上采样的二次去噪色度子图、初次去噪色度子图以及初始图像中各像素的色度值按照一定的权重进行融合计算,获取各像素的输出色度值。例如:
Pout=w2×Pfilt2+(1-w2)×(w1×Pfilt1+(1-w1)×Pori)
其中,Pout为像素的输出色度值,w1为初次去噪色度子图的权重,w2为二次去噪色度子图的权重,Pfilt1为初次去噪色度子图中该像素的色度值,Pfilt2为经过上采样的二次去噪色度子图中该像素的色度值,Pori为初始图像中该像素的色度值。
8. 恢复bayer的图。
其中上面的3.1步其实是计算时间消耗最长的,可以参看nlm的积分法进行加速(待实现,现在300w像素要跑20s)。目前是绝对差之和,即相当于nlm中使用了均值的方式来替代高斯权重。
可以调节搜索框,特征图半径,相似度阈值来确定过滤的效果,通过 w1,w2来保证保留的噪声
void xxx_cfa_lianyong_run(void* handle)
{
if (NULL == handle)
{
printf("xxx_dpc_chen_run handle is null! \n");
return;
}
xxx_isp_handle* isp_handle = (xxx_isp_handle*)handle;
u16 Width = isp_handle->raw_handle.raw_wide;
u16 Height = isp_handle->raw_handle.raw_high;
u16 Width_half = (u16)floor(Width / 2);
u16 Height_half = (u16)floor(Height / 2);
u16 w1 = 60; // 第一次去噪加回的权重
u16 w2 = 10; // 第二次去噪加回的权重
const u8 Green = 1 - ((isp_handle->demosaic_handle.red_x + \
isp_handle->demosaic_handle.red_y) & 1);
u16* first_data = isp_handle->raw_handle.data;
u16* img_r, * img_gr, * img_gb, * img_b, * y_data;
u16* y_r, *y_gr, *y_gb, *y_b;
u16* data;
u16* img_r_down, * img_gr_down, * img_gb_down, * img_b_down;
u16* y_r_down, * y_gr_down, * y_gb_down, * y_b_down;
u16* data_down;
data = (u16*)malloc(Width * Height * sizeof(u16));
img_r = (u16*)malloc(Width_half * Height_half * sizeof(u16));
img_gr = (u16*)malloc(Width_half * Height_half * sizeof(u16));
img_gb = (u16*)malloc(Width_half * Height_half * sizeof(u16));
img_b = (u16*)malloc(Width_half * Height_half * sizeof(u16));
y_r = (u16*)malloc(Width_half * Height_half * sizeof(u16));
y_gr = (u16*)malloc(Width_half * Height_half * sizeof(u16));
y_gb = (u16*)malloc(Width_half * Height_half * sizeof(u16));
y_b = (u16*)malloc(Width_half * Height_half * sizeof(u16));
if (img_r == NULL || img_gr == NULL || img_gb == NULL || img_b == NULL) return;
if (y_r == NULL || y_gr == NULL || y_gb == NULL || y_b == NULL) return;
if (data == NULL) return;
memcpy(data,first_data, Width * Height * sizeof(u16));
memset(img_r, 0, Width_half * Height_half * sizeof(u16));
memset(img_gr, 0, Width_half * Height_half * sizeof(u16));
memset(img_gb, 0, Width_half * Height_half * sizeof(u16));
memset(img_b, 0, Width_half * Height_half * sizeof(u16));
memset(y_r, 0, Width_half * Height_half * sizeof(u16));
memset(y_gr, 0, Width_half * Height_half * sizeof(u16));
memset(y_gb, 0, Width_half * Height_half * sizeof(u16));
memset(y_b, 0, Width_half * Height_half * sizeof(u16));
y_data = (u16*)malloc(Width * Height * sizeof(u16));// 全部按16位读出来
if (y_data == NULL) return;
memset(y_data, 0, Width * Height * sizeof(u16));
// 定义二次下采样的内存
u16 up_down_num = 2;
u16 Width_down = (u16)floor(Width_half / up_down_num);
u16 Height_down = (u16)floor(Height_half / up_down_num);
data_down = (u16*)malloc(Width * Height * sizeof(u16));
img_r_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
img_gr_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
img_gb_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
img_b_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
y_r_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
y_gr_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
y_gb_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
y_b_down = (u16*)malloc(Width_down * Height_down * sizeof(u16));
if (img_r_down == NULL || img_gr_down == NULL || img_gb_down == NULL || img_b_down == NULL) return;
if (y_r_down == NULL || y_gr_down == NULL || y_gb_down == NULL || y_b_down == NULL) return;
if (data_down == NULL) return;
memcpy(data_down, first_data, Width * Height * sizeof(u16));
memset(img_r_down, 0, Width_down * Height_down * sizeof(u16));
memset(img_gr_down, 0, Width_down * Height_down * sizeof(u16));
memset(img_gb_down, 0, Width_down * Height_down * sizeof(u16));
memset(img_b_down, 0, Width_down * Height_down * sizeof(u16));
memset(y_r_down, 0, Width_down * Height_down * sizeof(u16));
memset(y_gr_down, 0, Width_down * Height_down * sizeof(u16));
memset(y_gb_down, 0, Width_down * Height_down * sizeof(u16));
memset(y_b_down, 0, Width_down * Height_down * sizeof(u16));
u16 x, y, i, j;
int ii, jj;
u16 temp_y;
u16 search_win = 4;// 搜索区域的半径
u16 win = 1; // 取特征图的半径
u16 sad_thresh = 100; // 绝对差小于当前值时记为相似
u16 search_left, search_right, search_top, search_bottom;
u16 sim_hist_r, sad_r, sad_r_chroma;
u32 sim_sum_r, sim_sum_chroma_r;
u16 sim_hist_gr, sad_gr, sad_gr_chroma;
u32 sim_sum_gr, sim_sum_chroma_gr;
u16 sim_hist_gb, sad_gb, sad_gb_chroma;
u32 sim_sum_gb, sim_sum_chroma_gb;
u16 sim_hist_b, sad_b, sad_b_chroma;
u32 sim_sum_b, sim_sum_chroma_b;
// 获取亮度图
for (y = 0; y < Height; y++)
{
for (x = 0; x < Width; x++)
{
if (0 == y)
{
if (0 == x)
{
temp_y = (data[y * Width + x] + data[y * Width + x + 1] + \
data[(y + 1) * Width + x] + data[(y + 1) * Width + x + 1]) >> 2;
}
else if (x < Width - 1)
{
if (((x + y) & 1) == Green)
{
temp_y = ((data[y * Width + x - 1] + data[y * Width + x + 1]) + \
data[(y + 1) * Width + x] * 2 + data[y * Width + x] * 4) >> 3;
}
else
{
temp_y = (data[y * Width + x] * 4 + (data[(y + 1) * Width + x - 1] + \
data[(y + 1) * Width + x + 1]) * 2 + (data[y * Width + x - 1] + \
data[y * Width + x + 1] + data[(y + 1) * Width + x]) / 3 * 8) >> 4;
}
}
else
{
temp_y = (data[y * Width + x] + data[y * Width + x - 1] + \
data[(y + 1) * Width + x] + data[(y + 1) * Width + x - 1]) >> 2;
}
}
else if (y < Height - 1)
{
if (x == 0)
{
if (((x + y) & 1) == Green)
{
temp_y = ((data[(y - 1) * Width + x] + data[(y + 1) * Width + x]) + \
data[y * Width + x + 1] * 2 + data[y * Width + x] * 4) >> 3;
}
else
{
temp_y = (data[y * Width + x] * 4 + (data[(y + 1) * Width + x - 1] + \
data[(y - 1) * Width + x - 1]) * 2 + (data[(y - 1) * Width + x] + \
data[y * Width + x + 1] + data[(y + 1) * Width + x]) / 3 * 8) >> 4;
}
}
else if (x < Width - 1)
{
if (((x + y) & 1) == Green)
{
temp_y = ((data[(y - 1) * Width + x] + data[(y + 1) * Width + x]) + \
data[y * Width + x + 1] + data[y * Width + x - 1] + data[y * Width + x] * 4) >> 3;
}
else
{
temp_y = (data[y * Width + x] * 4 + data[(y + 1) * Width + x - 1] + \
data[(y - 1) * Width + x - 1] + data[(y + 1) * Width + x + 1] + \
data[(y - 1) * Width + x + 1] + (data[(y - 1) * Width + x] + \
data[y * Width + x + 1] + data[(y + 1) * Width + x] + \
data[y * Width + x - 1]) * 2) >> 4;
}
}
else
{
if (((x + y) & 1) == Green)
{
temp_y = ((data[(y - 1) * Width + x] + data[(y + 1) * Width + x]) + \
data[y * Width + x - 1] * 2 + data[y * Width + x] * 4) >> 3;
}
else
{
temp_y = (data[y * Width + x] * 4 + (data[(y + 1) * Width + x - 1] + \
data[(y - 1) * Width + x - 1]) * 2 + (data[(y - 1) * Width + x] + \
data[y * Width + x - 1] + data[(y + 1) * Width + x]) / 3 * 8) >> 4;
}
}
}
else
{
if (x == 0)
{
temp_y = (data[y * Width + x] + data[y * Width + x + 1] + \
data[(y - 1) * Width + x] + data[(y - 1) * Width + x + 1]) >> 2;
}
else if (x < Width - 1)
{
if (((x + y) & 1) == Green)
{
temp_y = ((data[y * Width + x - 1] + data[y * Width + x + 1]) + \
data[(y - 1) * Width + x] * 2 + data[y * Width + x] * 4) >> 3;
}
else
{
temp_y = (data[y * Width + x] * 4 + (data[(y - 1) * Width + x - 1] + \
data[(y - 1) * Width + x + 1]) * 2 + (data[y * Width + x - 1] + \
data[y * Width + x + 1] + data[(y - 1) * Width + x]) / 3 * 8) >> 4;
}
}
else
{
temp_y = (data[y * Width + x] + data[y * Width + x - 1] + \
data[(y - 1) * Width + x] + data[(y - 1) * Width + x - 1]) >> 2;
}
}
// y_data[y * Width + x] = temp_y;
*(y_data + y * Width + x) = temp_y;
}
}
//设置色度图
for (y = 0; y < Height_half; y++)
{
for (x = 0; x < Width_half; x++)
{
*(img_r + y * Width_half + x) = data[2 * y * Width + 2 * x];
// printf("%d,%d \n", *(img_r + y * Width_half + x), data[2 * y * Width + 2 * x]);
*(img_gr + y * Width_half + x) = data[2 * y * Width + 2 * x + 1];
*(img_gb + y * Width_half + x) = data[(2 * y +1) * Width + 2 * x];
*(img_b + y * Width_half + x) = data[(2 * y + 1) * Width + 2 * x + 1];
*(y_r + y * Width_half + x) = y_data[2 * y * Width + 2 * x];
*(y_gr + y * Width_half + x) = y_data[2 * y * Width + 2 * x + 1];
*(y_gb + y * Width_half + x) = y_data[(2 * y + 1) * Width + 2 * x];
*(y_b + y * Width_half + x) = y_data[(2 * y + 1) * Width + 2 * x + 1];
}
}
// 已亮度图对色度图进行引导滤波,去除亮度上的噪声
for (y = 0; y < Height_half; y++)
{
for (x = 0; x < Width_half; x++)
{
search_left = max(x - search_win, 0);
search_right = min(x + search_win , Width_half - 1);
search_top = max(y - search_win , 0);
search_bottom = min(y + search_win , Height_half - 1);
sim_hist_r = sim_sum_r = sim_sum_chroma_r = 0;
sim_hist_gr = sim_sum_gr = sim_sum_chroma_gr = 0;
sim_hist_gb = sim_sum_gb = sim_sum_chroma_gb = 0;
sim_hist_b = sim_sum_b = sim_sum_chroma_b = 0;
for (i = search_left; i <= search_right; i++)
{
for (j = search_top; j <= search_bottom; j++)
{
sad_r = sad_gr = sad_gb = sad_b = 0;
for (ii = -win; ii <= win; ii++)
{
for (jj = -win; jj <= win; jj++)
{
if ((y + jj) < 0 || (y + jj) >= Height_half || (x + ii) < 0 || (x + ii) >= Width_half || \
(j + jj) < 0 || (j + jj) >= Height_half || (i + ii) < 0 || (i + ii) >= Width_half)
{
continue;
}
sad_r += abs(y_r[(y + jj) * Width_half + x + ii] - y_r[(j + jj) * Width_half + i + ii]);
sad_gr += abs(y_gr[(y + jj) * Width_half + x + ii] - y_gr[(j + jj) * Width_half + i + ii]);
sad_gb += abs(y_gb[(y + jj) * Width_half + x + ii] - y_gb[(j + jj) * Width_half + i + ii]);
sad_b += abs(y_b[(y + jj) * Width_half + x + ii] - y_b[(j + jj) * Width_half + i + ii]);
}
}
if (sad_r < sad_thresh)
{
sim_hist_r++;
sim_sum_r += y_r[j * Width_half + i];
sim_sum_chroma_r += img_r[j * Width_half + i];
}
if (sad_gr < sad_thresh)
{
sim_hist_gr++;
sim_sum_gr += y_gr[j * Width_half + i];
sim_sum_chroma_gr += img_gr[j * Width_half + i];
}
if (sad_gb < sad_thresh)
{
sim_hist_gb++;
sim_sum_gb += y_gb[j * Width_half + i];
sim_sum_chroma_gb += img_gb[j * Width_half + i];
}
if (sad_b < sad_thresh)
{
sim_hist_b++;
sim_sum_b += y_b[j * Width_half + i];
sim_sum_chroma_b += img_b[j * Width_half + i];
}
}
}
*(y_r + y * Width_half + x) = sim_sum_r / sim_hist_r;
*(img_r + y * Width_half + x) = sim_sum_chroma_r / sim_hist_r;
*(y_gr + y * Width_half + x) = sim_sum_gr / sim_hist_gr;
*(img_gr + y * Width_half + x) = sim_sum_chroma_gr / sim_hist_gr;
*(y_gb + y * Width_half + x) = sim_sum_gb / sim_hist_gb;
*(img_gb + y * Width_half + x) = sim_sum_chroma_gb / sim_hist_gb;
*(y_b + y * Width_half + x) = sim_sum_b / sim_hist_b;
*(img_b + y * Width_half + x) = sim_sum_chroma_b / sim_hist_b;
}
}
//叠回第一次去噪图
for (y = 0; y < Height_half; y++)
{
for (x = 0; x < Width_half; x++)
{
// printf("%d,%d \n", *(img_r + y * Width_half + x), data[2 * y * Width + 2 * x]);
data[2 * y * Width + 2 * x] = *(img_r + y * Width_half + x);
// printf("%d,%d \n", *(img_r + y * Width_half + x), data[2 * y * Width + 2 * x]);
data[2 * y * Width + 2 * x + 1] = *(img_gr + y * Width_half + x);
data[(2 * y + 1) * Width + 2 * x] = *(img_gb + y * Width_half + x);
data[(2 * y + 1) * Width + 2 * x + 1] = *(img_b + y * Width_half + x);
}
}
// 下采样 取4个象限的的均值
for (y = 0; y < Height_down; y++)
{
for (x = 0; x < Width_down; x++)
{
*(img_r_down + y * Width_down + x) = (img_r[2 * y * Width_half + 2 * x] + img_r[2 * y * Width_half + 2 * x + 1] + \
img_r[(2 * y + 1) * Width_half + 2 * x] + img_r[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
// printf("%d,%d \n", *(img_r + y * Width_half + x), data[2 * y * Width + 2 * x]);
*(img_gr_down + y * Width_down + x) = (img_gr[2 * y * Width_half + 2 * x] + img_gr[2 * y * Width_half + 2 * x + 1] + \
img_gr[(2 * y + 1) * Width_half + 2 * x] + img_gr[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
*(img_gb_down + y * Width_down + x) = (img_gb[2 * y * Width_half + 2 * x] + img_gb[2 * y * Width_half + 2 * x + 1] + \
img_gb[(2 * y + 1) * Width_half + 2 * x] + img_gb[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
*(img_b_down + y * Width_down + x) = (img_b[2 * y * Width_half + 2 * x] + img_b[2 * y * Width_half + 2 * x + 1] + \
img_b[(2 * y + 1) * Width_half + 2 * x] + img_b[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
*(y_r_down + y * Width_down + x) = (y_r[2 * y * Width_half + 2 * x] + y_r[2 * y * Width_half + 2 * x + 1] + \
y_r[(2 * y + 1) * Width_half + 2 * x] + y_r[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
*(y_gr_down + y * Width_down + x) = (y_gr[2 * y * Width_half + 2 * x] + y_gr[2 * y * Width_half + 2 * x + 1] + \
y_gr[(2 * y + 1) * Width_half + 2 * x] + y_gr[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
*(y_gb_down + y * Width_down + x) = (y_gb[2 * y * Width_half + 2 * x] + y_gb[2 * y * Width_half + 2 * x + 1] + \
y_gb[(2 * y + 1) * Width_half + 2 * x] + y_gb[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
*(y_b_down + y * Width_down + x) = (y_b[2 * y * Width_half + 2 * x] + y_b[2 * y * Width_half + 2 * x + 1] + \
y_b[(2 * y + 1) * Width_half + 2 * x] + y_b[(2 * y + 1) * Width_half + 2 * x + 1]) >> 2;
}
}
free(y_r);
free(y_gr);
free(y_gb);
free(y_b);
// 进行第二次滤波
for (y = 0; y < Height_down; y++)
{
for (x = 0; x < Width_down; x++)
{
search_left = max(x - search_win, 0);
search_right = min(x + search_win, Width_down - 1);
search_top = max(y - search_win, 0);
search_bottom = min(y + search_win, Height_down - 1);
sim_hist_r = sim_sum_r = sim_sum_chroma_r = 0;
sim_hist_gr = sim_sum_gr = sim_sum_chroma_gr = 0;
sim_hist_gb = sim_sum_gb = sim_sum_chroma_gb = 0;
sim_hist_b = sim_sum_b = sim_sum_chroma_b = 0;
for (i = search_left; i <= search_right; i++)
{
for (j = search_top; j <= search_bottom; j++)
{
sad_r = sad_gr = sad_gb = sad_b = 0;
sad_r_chroma = sad_gr_chroma = sad_gb_chroma = sad_b_chroma = 0;
for (ii = -win; ii <= win; ii++)
{
for (jj = -win; jj <= win; jj++)
{
if ((y + jj) < 0 || (y + jj) >= Height_down || (x + ii) < 0 || (x + ii) >= Width_down || \
(j + jj) < 0 || (j + jj) >= Height_down || (i + ii) < 0 || (i + ii) >= Width_down)
{
continue;
}
sad_r += abs(y_r_down[(y + jj) * Width_down + x + ii] - y_r_down[(j + jj) * Width_down + i + ii]);
sad_gr += abs(y_gr_down[(y + jj) * Width_down + x + ii] - y_gr_down[(j + jj) * Width_down + i + ii]);
sad_gb += abs(y_gb_down[(y + jj) * Width_down + x + ii] - y_gb_down[(j + jj) * Width_down + i + ii]);
sad_b += abs(y_b_down[(y + jj) * Width_down + x + ii] - y_b_down[(j + jj) * Width_down + i + ii]);
sad_r_chroma += abs(img_r_down[(y + jj) * Width_down + x + ii] - img_r_down[(j + jj) * Width_down + i + ii]);
sad_gr_chroma += abs(img_gr_down[(y + jj) * Width_down + x + ii] - img_gr_down[(j + jj) * Width_down + i + ii]);
sad_gb_chroma += abs(img_gb_down[(y + jj) * Width_down + x + ii] - img_gb_down[(j + jj) * Width_down + i + ii]);
sad_b_chroma += abs(img_b_down[(y + jj) * Width_down + x + ii] - img_b_down[(j + jj) * Width_down + i + ii]);
}
}
if (sad_r < sad_thresh && sad_r_chroma < sad_thresh)
{
sim_hist_r++;
sim_sum_chroma_r += img_r_down[j * Width_down + i];
}
if (sad_gr < sad_thresh && sad_gr_chroma < sad_thresh)
{
sim_hist_gr++;
sim_sum_chroma_gr += img_gr_down[j * Width_down + i];
}
if (sad_gb < sad_thresh && sad_gb_chroma < sad_thresh)
{
sim_hist_gb++;
sim_sum_chroma_gb += img_gb_down[j * Width_down + i];
}
if (sad_b < sad_thresh && sad_b_chroma < sad_thresh)
{
sim_hist_b++;
sim_sum_chroma_b += img_b_down[j * Width_down + i];
}
}
}
*(img_r_down + y * Width_down + x) = sim_sum_chroma_r / sim_hist_r;
*(img_gr_down + y * Width_down + x) = sim_sum_chroma_gr / sim_hist_gr;
*(img_gb_down + y * Width_down + x) = sim_sum_chroma_gb / sim_hist_gb;
*(img_b_down + y * Width_down + x) = sim_sum_chroma_b / sim_hist_b;
}
}
free(y_r_down);
free(y_gr_down);
free(y_gb_down);
free(y_b_down);
// 上采样 向右插
#if 1
for (y = 0; y < Height_down; y += 2)
{
for (x = 0; x < Width_down - 1; x++)
{
*(img_r + 2 * y * Width_half + 2 * x) = *(img_r_down + y * Width_down + x);
*(img_r + 2 * y * Width_half + 2 * x + 1) = (*(img_r_down + y * Width_down + x) + *(img_r_down + y * Width_down + x + 1)) >> 1;
*(img_gr + 2 * y * Width_half + 2 * x) = *(img_gr_down + y * Width_down + x);
*(img_gr + 2 * y * Width_half + 2 * x + 1) = (*(img_gr_down + y * Width_down + x) + *(img_gr_down + y * Width_down + x + 1)) >> 1;
*(img_gb + 2 * y * Width_half + 2 * x) = *(img_gb_down + y * Width_down + x);
*(img_gb + 2 * y * Width_half + 2 * x + 1) = (*(img_gb_down + y * Width_down + x) + *(img_gb_down + y * Width_down + x + 1)) >> 1;
*(img_b + 2 * y * Width_half + 2 * x) = *(img_b_down + y * Width_down + x);
*(img_b + 2 * y * Width_half + 2 * x + 1) = (*(img_b_down + y * Width_down + x) + *(img_b_down + y * Width_down + x + 1)) >> 1;
}
*(img_r + 2 * y * Width_half + 2 * (Width_down - 1)) = *(img_r_down + y * Width_down + Width_down - 1);
*(img_r + 2 * y * Width_half + 2 * (Width_down - 1) + 1) = *(img_r_down + y * Width_down + Width_down - 1);
*(img_gr + 2 * y * Width_half + 2 * (Width_down - 1)) = *(img_gr_down + y * Width_down + Width_down - 1);
*(img_gr + 2 * y * Width_half + 2 * (Width_down - 1) + 1) = *(img_gr_down + y * Width_down + Width_down - 1);
*(img_gb + 2 * y * Width_half + 2 * (Width_down - 1)) = *(img_gb_down + y * Width_down + Width_down - 1);
*(img_gb + 2 * y * Width_half + 2 * (Width_down - 1) + 1) = *(img_gb_down + y * Width_down + Width_down - 1);
*(img_b + 2 * y * Width_half + 2 * (Width_down - 1)) = *(img_b_down + y * Width_down + Width_down - 1);
*(img_b + 2 * y * Width_half + 2 * (Width_down - 1) + 1) = *(img_b_down + y * Width_down + Width_down - 1);
}
free(img_r_down);
free(img_gr_down);
free(img_gb_down);
free(img_b_down);
#endif
#if 1
for (x = 0; x < Width_half; x++)
{
for (y = 0; y < Height_down - 1; y += 2)
{
*(img_r + (2 * y + 1) * Width_half + x) = (*(img_r + (2 * y) * Width_half + x) + *(img_r + (2 * y + 2) * Width_half + x)) >> 1;
*(img_gr + (2 * y + 1) * Width_half + x) = (*(img_gr + (2 * y) * Width_half + x) + *(img_gr + (2 * y + 2) * Width_half + x)) >> 1;
*(img_gb + (2 * y + 1) * Width_half + x) = (*(img_gb + (2 * y) * Width_half + x) + *(img_gb + (2 * y + 2) * Width_half + x)) >> 1;
*(img_b + (2 * y + 1) * Width_half + x) = (*(img_b + (2 * y) * Width_half + x) + *(img_b + (2 * y + 2) * Width_half + x)) >> 1;
}
*(img_r + (2 * (Height_down - 1) + 1) * Width_half + x) = *(img_r + (2 * (Height_down - 1)) * Width_half + x);
*(img_gr + (2 * (Height_down - 1) + 1) * Width_half + x) = *(img_gr + (2 * (Height_down - 1)) * Width_half + x);
*(img_gb + (2 * (Height_down - 1) + 1) * Width_half + x) = *(img_gb + (2 * (Height_down - 1)) * Width_half + x);
*(img_b + (2 * (Height_down - 1) + 1) * Width_half + x) = *(img_b + (2 * (Height_down - 1)) * Width_half + x);
}
#endif
//叠回第二次去噪图
for (y = 0; y < Height_half; y++)
{
for (x = 0; x < Width_half; x++)
{
// printf("%d,%d \n", *(img_r + y * Width_half + x), data[2 * y * Width + 2 * x]);
data_down[2 * y * Width + 2 * x] = *(img_r + y * Width_half + x);
// printf("%d,%d \n", *(img_r + y * Width_half + x), data[2 * y * Width + 2 * x]);
data_down[2 * y * Width + 2 * x + 1] = *(img_gr + y * Width_half + x);
data_down[(2 * y + 1) * Width + 2 * x] = *(img_gb + y * Width_half + x);
data_down[(2 * y + 1) * Width + 2 * x + 1] = *(img_b + y * Width_half + x);
}
}
free(img_r);
free(img_gr);
free(img_gb);
free(img_b);
if ((w1 + w2) > 100)
{
printf("w1 + w2 > 100!\n");
return;
}
// 叠回原图
for (y = 0; y < Height_half; y++)
{
for (x = 0; x < Width_half; x++)
{
first_data[y * Width + x] = (u16)(((u32)*(data + y * Width + x)* w1 + *(data_down + y * Width + x) * w2 + \
*(first_data + y * Width + x) * (100 - w1 - w2)) / 100);
}
}
// memcpy(first_data, data_down, Width* Height * sizeof(u16));
free(y_data);
free(data);
free(data_down);
}