栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

高斯滤波和双边滤波

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

高斯滤波和双边滤波

原理:https://www.youtube.com/watch?v=7FP7ndMEfsc&t=5s

C语言实现24位bmp真彩图高斯滤波和双边滤波:

(从左到右分别是原图,高斯,双边,从上到下分别是sigma=2,4,8)

 

 高斯滤波代码:

void gauss_2(const char* filename)
{
    BITMAPFILEHEADER bmpFileHeader;
    BITMAPINFOHEADER bmpInfoHeader;
    FILE* fp;
    if ((fp = fopen(filename, "rb")) == NULL)
    {
        printf("打开失败n");
        exit(1);
    }
    //读取图像信息
    fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
    fread(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
    RGBDATA** grayValue;
    grayValue = new RGBDATA * [bmpInfoHeader.biHeight]; //声明一个指针数组
    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        grayValue[i] = new RGBDATA[(bmpInfoHeader.biWidth * 3 + 3) / 4 * 4];
    }//每个数组元素也是一个指针数组



    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            fread(&grayValue[i][j], sizeof(tagRGB), 1, fp);//存入数组
        }
    }
    fclose(fp);
    double sigma = 2.0;           //这里取size=sigma+1
    int size = 3;
    double w[3][3] = { 0 };
    double sum = 0.0;
    for (int i = 0; i < size; i++)        //高斯核
    {
        for (int j = 0; j < size; j++)
        {
            w[i][j] = exp(-(pow(i - size / 2, 2) + pow(j - size / 2, 2)) / (2 * sigma * sigma));
            sum += w[i][j];
        }
    }

    //零填充
    double** zero_fill_blue;
    double** zero_fill_green;
    double** zero_fill_red;
    zero_fill_blue = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    zero_fill_green = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    zero_fill_red = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    for (int i = 0; i < bmpInfoHeader.biHeight + (size - 1) * 2; i++)
    {
        zero_fill_blue[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        zero_fill_green[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        zero_fill_red[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
    }

    for (int i = 0; i < bmpInfoHeader.biHeight + 2 * (size - 1); i++)
    {
        for (int j = 0; j < ((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + 2 * (size - 1)); j++)
        {
            if (i - (size - 1) >= 0 && i < bmpInfoHeader.biHeight + (size - 1) && j - (size - 1)>0 && j < ((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1)))
            {
                zero_fill_blue[i][j] = grayValue[i - (size - 1)][j - (size - 1)].blue;
                zero_fill_green[i][j] = grayValue[i - (size - 1)][j - (size - 1)].green;
                zero_fill_red[i][j] = grayValue[i - (size - 1)][j - (size - 1)].red;
            }
            else
            {
                zero_fill_blue[i][j] = 0;
                zero_fill_green[i][j] = 0;
                zero_fill_red[i][j] = 0;
            }
        }
    }

    double** fill_blue;
    double** fill_green;
    double** fill_red;
    fill_blue = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    fill_green = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    fill_red = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    for (int i = 0; i < bmpInfoHeader.biHeight + (size - 1) * 2; i++)
    {
        fill_blue[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        fill_green[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        fill_red[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
    }

    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            fill_blue[i][j] = 0;
            fill_green[i][j] = 0;
            fill_red[i][j] = 0;
        }
    }
    //gauss滤波处理
    for (int i = size / 2; i < bmpInfoHeader.biHeight + size / 2; i++)
    {
        for (int j = size / 2; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + size / 2; j++)
        {
            for (int a = 0; a < size; a++)
            {
                for (int b = 0; b < size; b++)
                {
                    fill_blue[i - size / 2][j - size / 2] += zero_fill_blue[i + a - size / 2][j + b - size / 2] * w[a][b];
                    fill_green[i - size / 2][j - size / 2] += zero_fill_green[i + a - size / 2][j + b - size / 2] * w[a][b];
                    fill_red[i - size / 2][j - size / 2] += zero_fill_red[i + a - size / 2][j + b - size / 2] * w[a][b];
                }
            }
        }
    }

    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            grayValue[i][j].blue = round(fill_blue[i][j] / sum);
            grayValue[i][j].green = round(fill_green[i][j] / sum);
            grayValue[i][j].red = round(fill_red[i][j] / sum);
        }
    }
    //写入gauss核进行滤波后的新图像
    fp = fopen("gauss_2.bmp", "wb");
    if (fp == NULL)
    {
        printf("写入失败n");
        exit(1);
    }
    fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            fwrite(&grayValue[i][j], sizeof(tagRGB), 1, fp);
        }
    }
    fclose(fp);
}

 探究了下sigma_r与双边滤波结果的关系,这里取sigma=6,sigma_r分别取10,20,100

结果如图:

 双边滤波的代码如下:

void bilateral_2_10(const char* filename)
{
    BITMAPFILEHEADER bmpFileHeader;
    BITMAPINFOHEADER bmpInfoHeader;
    FILE* fp;
    if ((fp = fopen(filename, "rb")) == NULL)
    {
        printf("打开失败n");
        exit(1);
    }
    //读取图像信息
    fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
    fread(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
    RGBDATA** grayValue;
    grayValue = new RGBDATA * [bmpInfoHeader.biHeight]; //声明一个指针数组
    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        grayValue[i] = new RGBDATA[(bmpInfoHeader.biWidth * 3 + 3) / 4 * 4];
    }//每个数组元素也是一个指针数组
    

    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            fread(&grayValue[i][j], sizeof(tagRGB), 1, fp);//存入数组
        }
    }
    fclose(fp);

    double sigma = 2.0;
    int size = 3;
    double sigma_1 = 10.0;
    double w[3][3] = { 0 };
    for (int i = 0; i < size; i++)        //高斯核
    {
        for (int j = 0; j < size; j++)
        {
            w[i][j] = exp(-(pow(i - size / 2, 2) + pow(j - size / 2, 2)) / (2 * sigma * sigma));
        }
    }
    //零填充
    double** zero_fill_blue;
    double** zero_fill_green;
    double** zero_fill_red;
    zero_fill_blue = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    zero_fill_green = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    zero_fill_red = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    for (int i = 0; i < bmpInfoHeader.biHeight + (size - 1) * 2; i++)
    {
        zero_fill_blue[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        zero_fill_green[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        zero_fill_red[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
    }

    for (int i = 0; i < bmpInfoHeader.biHeight + 2 * (size - 1); i++)
    {
        for (int j = 0; j < ((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + 2 * (size - 1)); j++)
        {
            if (i - (size - 1) >= 0 && i < bmpInfoHeader.biHeight + (size - 1) && j - (size - 1)>0 && j < ((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1)))
            {
                zero_fill_blue[i][j] = grayValue[i - (size - 1)][j - (size - 1)].blue;
                zero_fill_green[i][j] = grayValue[i - (size - 1)][j - (size - 1)].green;
                zero_fill_red[i][j] = grayValue[i - (size - 1)][j - (size - 1)].red;
            }
            else
            {
                zero_fill_blue[i][j] = 0;
                zero_fill_green[i][j] = 0;
                zero_fill_red[i][j] = 0;
            }
        }
    }
    double** fill_blue;                              //double传BYTE会丢失数据,所以建double来存数据
    double** fill_green;
    double** fill_red;
    fill_blue = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    fill_green = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    fill_red = new double* [(bmpInfoHeader.biHeight + (size - 1) * 2)];
    for (int i = 0; i < bmpInfoHeader.biHeight + (size - 1) * 2; i++)
    {
        fill_blue[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        fill_green[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
        fill_red[i] = new double[((bmpInfoHeader.biWidth * 3 + 3) / 4 * 4 + (size - 1) * 2)];
    }
    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            fill_blue[i][j] = 0;
            fill_green[i][j] = 0;
            fill_red[i][j] = 0;
        }
    }
    double sum_blue = 0;
    double sum_green = 0;
    double sum_red = 0;
    for (int i = size/2; i < bmpInfoHeader.biHeight +size / 2; i++)
    {
        for (int j = size/2; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4+size/2; j++)
        {
            for (int a = 0; a < size; a++)
            {
                for (int b = 0; b < size; b++)
                {
                    fill_blue[i - size / 2][j - size / 2] += zero_fill_blue[i + a - size / 2][j + b - size / 2] * w[a][b] * exp(-pow(zero_fill_blue[i + a - size / 2][j + b - size / 2] - zero_fill_blue[i][j], 2) / (2 * sigma_1 * sigma_1));
                    sum_blue += w[a][b] * exp(-pow(zero_fill_blue[i + a - size / 2][j + b - size / 2] - zero_fill_blue[i][j], 2) / (2 * sigma_1 * sigma_1));
                    fill_green[i - size / 2][j - size / 2] += zero_fill_green[i + a - size / 2][j + b - size / 2] * w[a][b] * exp(-pow(zero_fill_green[i + a - size / 2][j + b - size / 2] - zero_fill_green[i][j], 2) / (2 * sigma_1 * sigma_1));
                    sum_green += w[a][b] * exp(-pow(zero_fill_green[i + a - size / 2][j + b - size / 2] - zero_fill_green[i][j], 2) / (2 * sigma_1 * sigma_1));
                    fill_red[i - size / 2][j - size / 2] += zero_fill_red[i + a - size / 2][j + b - size / 2] * w[a][b] * exp(-pow(zero_fill_red[i + a - size / 2][j + b - size / 2] - zero_fill_red[i][j], 2) / (2 * sigma_1 * sigma_1));
                    sum_red += w[a][b] * exp(-pow(zero_fill_red[i + a - size / 2][j + b - size / 2] - zero_fill_red[i][j], 2) / (2 * sigma_1 * sigma_1));
                }
            }
            fill_blue[i - size / 2][j - size / 2] = fill_blue[i - size / 2][j - size / 2] / sum_blue ;
            fill_green[i - size / 2][j - size / 2] = fill_green[i - size / 2][j - size / 2] / sum_green ;
            fill_red[i - size / 2][j - size / 2] = fill_red[i - size / 2][j - size / 2] / sum_red ;
            sum_blue = 0;
            sum_green = 0;
            sum_red = 0;
        }
    }
    

    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            grayValue[i][j].blue = fill_blue[i][j];
            grayValue[i][j].green = fill_green[i][j];
            grayValue[i][j].red = fill_red[i][j];
        }
    }



    //写入滤波后的新图像
    fp = fopen("bilateral _2.bmp", "wb");
    if (fp == NULL)
    {
        printf("写入失败n");
        exit(1);
    }
    fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
    for (int i = 0; i < bmpInfoHeader.biHeight; i++)
    {
        for (int j = 0; j < (bmpInfoHeader.biWidth * 3 + 3) / 4 * 4; j++)
        {
            fwrite(&grayValue[i][j], sizeof(tagRGB), 1, fp);
        }
    }
    fclose(fp);
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/847782.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号