raw域上的去噪

一、基本概念

  1. raw域上的去噪会有一个好处,噪声形态没有被其他模块给破坏。具体的分析可以查看为什么在raw域降噪?

二、 一个简单的raw域去噪方法

  1. 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);
}

你可能感兴趣的:(raw域上的去噪)