【开发日志】2023.05 ZENO----Image Processing----Blur、GaussianBlur、MedianBlur、BilateralBlur

Blur

 

 

 

 

 

GaussianBlur

 

 

 

 

 

 

 

// 高斯函数
double gaussian(double x, double sigma) {
    return exp(-(x * x) / (2 * sigma * sigma));
}
// 高斯滤波函数
void gaussian_filter(std::shared_ptr<PrimitiveObject> &image, std::shared_ptr<PrimitiveObject> &imagetmp, int width, int height, int sigma) {
    // 计算高斯核大小
    int size = (int)(2 * sigma + 1);
    if (size % 2 == 0) {
        size++;
    }
    // 创建高斯核
    float* kernel = new float[size];
    float sum = 0.0;
    int mid = size / 2;
    for (int i = 0; i < size; i++) {
        kernel[i] = gaussian(i - mid, sigma);
        sum += kernel[i];
    }
    for (int i = 0; i < size; i++) {
        kernel[i] /= sum;
    }
    // 对每个像素进行卷积操作
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            float sum0 = 0.0, sum1 = 0.0, sum2 = 0.0;
            for (int i = -mid; i <= mid; i++) {
                int nx = x + i;
                if (nx < 0 || nx >= width) {
                    continue;
                }
                sum0 += kernel[i + mid] * image->verts[y * width + nx][0];
                sum1 += kernel[i + mid] * image->verts[y * width + nx][1];
                sum2 += kernel[i + mid] * image->verts[y * width + nx][2];
            }
            imagetmp->verts[y * width + x] = {sum0,sum1,sum2};
        }
    }
    image = imagetmp;
    // 释放内存
    delete[] kernel;
}

#include <iostream>
#include <cmath>

using namespace std;

// 高斯函数
double gaussian(double x, double sigma) {
    return exp(-(x * x) / (2 * sigma * sigma));
}

// 高斯滤波函数
void gaussian_filter(unsigned char* image, int width, int height, int channel, double sigma) {
    // 定义一个和原图像相同大小的新图像
    unsigned char* new_image = new unsigned char[width * height * channel];
    memcpy(new_image, image, width * height * channel);

    // 计算高斯核大小
    int size = (int)(2 * sigma + 1);
    if (size % 2 == 0) {
        size++;
    }

    // 创建高斯核
    double* kernel = new double[size];
    double sum = 0.0;
    int mid = size / 2;
    for (int i = 0; i < size; i++) {
        kernel[i] = gaussian(i - mid, sigma);
        sum += kernel[i];
    }
    for (int i = 0; i < size; i++) {
        kernel[i] /= sum;
    }

    // 对每个像素进行卷积操作
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            for (int c = 0; c < channel; c++) {
                double sum = 0.0;
                for (int i = -mid; i <= mid; i++) {
                    int nx = x + i;
                    if (nx < 0 || nx >= width) {
                        continue;
                    }
                    sum += kernel[i + mid] * image[(y * width + nx) * channel + c];
                }
                new_image[(y * width + x) * channel + c] = (unsigned char)sum;
            }
        }
    }

    // 将新图像复制回原图像
    memcpy(image, new_image, width * height * channel);

    // 释放内存
    delete[] new_image;
    delete[] kernel;
}

int main() {
    // 读取图像
    Mat img = imread("test.jpg", IMREAD_COLOR);
    if (img.empty()) {
        cerr << "Failed to read image" << endl;
        return -1;
    }

    // 将图像转为灰度图像
    Mat gray_img;
    cvtColor(img, gray_img, COLOR_BGR2GRAY);

    // 将图像数据复制到一个数组中
    unsigned char* data = gray_img.data;
    int width = gray_img.cols;
    int height = gray_img.rows;
    int channel = gray_img.channels();

    // 进行高斯滤波
    gaussian_filter(data, width, height, channel, 1.0);

    // 将数组中的数据复制回图像
    memcpy(gray_img.data, data, width * height * channel);

    // 显示图像
    imshow("Gaussian filter", gray_img);
    waitKey(0);

    return 0;
}

MedianBlur

 

 

 

 

 ​​​​

// 定义一个结构体,用于存储像素点的信息
struct Pixel {
    int x;
    int y;
    int value;
};
// MedianBlur函数,实现中值滤波操作
void MedianBlur(std::shared_ptr<PrimitiveObject> &image, std::shared_ptr<PrimitiveObject> &imagetmp, int width, int height, int kernel_size) {
    // 定义一个vector,用于存储周围像素的值
    using kernel = std::tuple<float, float, float>;
    kernel n = {0, 0, 0};
    std::vector<kernel> kernel_values(kernel_size * kernel_size);
    // 遍历图像中的每个像素点
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            // 获取当前像素点的值
            int current_value0 = image->verts[y * width + x][0];
            int current_value1 = image->verts[y * width + x][1];
            int current_value2 = image->verts[y * width + x][2];
            // 遍历周围像素,获取像素值和坐标信息
            for (int ky = 0; ky < kernel_size; ++ky) {
                for (int kx = 0; kx < kernel_size; ++kx) {
                    int px = x - kernel_size / 2 + kx;
                    int py = y - kernel_size / 2 + ky;
                    // 判断像素是否越界,如果越界则使用当前像素值作为周围像素值
                    if (px < 0 || px >= width || py < 0 || py >= height) {
                        kernel_values[ky * kernel_size + kx] = {current_value0,current_value1,current_value2};
                    }
                    else {
                        kernel_values[ky * kernel_size + kx] = {image->verts[py * width + px][0],image->verts[py * width + px][1],image->verts[py * width + px][2]};
                    }
                }
            }
            // 对周围像素的值进行排序,并取中间值作为新的像素值
            std::sort(kernel_values.begin(), kernel_values.end());
            float new_value0 = std::get<0>(kernel_values[kernel_size * kernel_size / 2]);
            float new_value1 = std::get<1>(kernel_values[kernel_size * kernel_size / 2]);
            float new_value2 = std::get<2>(kernel_values[kernel_size * kernel_size / 2]);
            // 将新的像素值赋值给输出图像
            imagetmp->verts[y * width + x] = {new_value0,new_value1,new_value2};
        }
    }
    image = imagetmp;
}
#include <iostream>
#include <vector>
#include <algorithm>

// 定义一个结构体,用于存储像素点的信息
struct Pixel {
    int x;
    int y;
    int value;
};

// MedianBlur函数,实现中值滤波操作
void MedianBlur(const unsigned char* input_image, unsigned char* output_image, int width, int height, int kernel_size) {
    // 定义一个vector,用于存储周围像素的值
    std::vector<int> kernel_values(kernel_size * kernel_size);

    // 遍历图像中的每个像素点
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            // 获取当前像素点的值
            int current_value = input_image[y * width + x];

            // 定义一个vector,用于存储周围像素的信息
            std::vector<Pixel> kernel_pixels(kernel_size * kernel_size);

            // 遍历周围像素,获取像素值和坐标信息
            for (int ky = 0; ky < kernel_size; ++ky) {
                for (int kx = 0; kx < kernel_size; ++kx) {
                    int px = x - kernel_size / 2 + kx;
                    int py = y - kernel_size / 2 + ky;

                    // 判断像素是否越界,如果越界则使用当前像素值作为周围像素值
                    if (px < 0 || px >= width || py < 0 || py >= height) {
                        kernel_values[ky * kernel_size + kx] = current_value;
                    }
                    else {
                        kernel_values[ky * kernel_size + kx] = input_image[py * width + px];
                    }

                    // 将像素信息存储到vector中
                    kernel_pixels[ky * kernel_size + kx] = { px, py, kernel_values[ky * kernel_size + kx] };
                }
            }

            // 对周围像素的值进行排序,并取中间值作为新的像素值
            std::sort(kernel_values.begin(), kernel_values.end());
            int new_value = kernel_values[kernel_size * kernel_size / 2];

            // 将新的像素值赋值给输出图像
            output_image[y * width + x] = new_value;
        }
    }
}

int main() {
    // 定义图像的宽度和高度
    int width = 640;
    int height = 480;

    // 定义一个用于存储图像数据的数组
    unsigned char* input_image = new unsigned char[width

BilateralBlur

 

 

// 定义一个函数,用于计算双边权重
float bilateral(float src, float dst, float sigma_s, float sigma_r) {
    return gaussian(src - dst, sigma_s) * gaussian(abs(src - dst), sigma_r);
}

// 定义一个函数,用于对图像进行双边滤波
void bilateralFilter(std::shared_ptr<PrimitiveObject> &image, std::shared_ptr<PrimitiveObject> &imagetmp, int width, int height, float sigma_s, float sigma_r) {
    // 计算卷积核的半径
    int k = ceil(3 * sigma_s);
    // 定义一个临时数组,用于存储每个像素点的中间值
    float* tmp = new float[width * height];
    for (int i = k; i < height-k; i++) {
        for (int j = k; j < width-k; j++) {
            // 定义变量,用于存储像素值的加权平均值
            float sum0 = 0, sum1 = 0, sum2 = 0;
            // 定义变量,用于存储权重的和
            float wsum0 = 0,wsum1 = 0,wsum2 = 0;
            for (int m = -k; m <= k; m++) {
                for (int n = -k; n <= k; n++) {
                    // 计算双边权重
                    float w0 = bilateral(image->verts[i*width+j][0],image->verts[(i+m)*width+j+n][0], sigma_s, sigma_r);
                    float w1 = bilateral(image->verts[i*width+j][1],image->verts[(i+m)*width+j+n][1], sigma_s, sigma_r);
                    float w2 = bilateral(image->verts[i*width+j][2],image->verts[(i+m)*width+j+n][2], sigma_s, sigma_r);
                    // 计算加权平均值
                    sum0 += w0 * image->verts[(i+m)*width+j+n][0];
                    sum1 += w1 * image->verts[(i+m)*width+j+n][1];
                    sum2 += w2 * image->verts[(i+m)*width+j+n][2];
                    // 计算权重的和
                    wsum0 += w0;
                    wsum1 += w1;
                    wsum2 += w2;
                }
            }
            imagetmp->verts[i*width+j] = {sum0 / wsum0,sum1/ wsum1, sum2 / wsum2};   // 计算每个像素点的中间值,并将结果存储到临时数组中
        }
    }
    image = imagetmp;
}
#include <iostream>
#include <cmath>

using namespace std;

// 定义一个函数,用于计算高斯权重
float gaussian(float x, float sigma) {
    return exp(-(x*x) / (2*sigma*sigma));
}

// 定义一个函数,用于计算双边权重
float bilateral(float src, float dst, float sigma_s, float sigma_r) {
    return gaussian(src - dst, sigma_s) * gaussian(abs(src - dst), sigma_r);
}

// 定义一个函数,用于对图像进行双边滤波
void bilateralFilter(float* src, float* dst, int width, int height, float sigma_s, float sigma_r) {
    int k = ceil(3 * sigma_s);   // 计算卷积核的半径
    float* tmp = new float[width * height];   // 定义一个临时数组,用于存储每个像素点的中间值
    for (int i = k; i < height-k; i++) {
        for (int j = k; j < width-k; j++) {
            float sum = 0;   // 定义一个变量,用于存储像素值的加权平均值
            float wsum = 0;   // 定义一个变量,用于存储权重的和
            for (int m = -k; m <= k; m++) {
                for (int n = -k; n <= k; n++) {
                    float w = bilateral(src[i*width+j], src[(i+m)*width+j+n], sigma_s, sigma_r);   // 计算双边权重
                    sum += w * src[(i+m)*width+j+n];   // 计算加权平均值
                    wsum += w;   // 计算权重的和
                }
            }
            tmp[i*width+j] = sum / wsum;   // 计算每个像素点的中间值,并将结果存储到临时数组中
        }
    }
    memcpy(dst, tmp, sizeof(float) * width * height);   // 将临时数组中的数据拷贝到输出数组中
    delete[] tmp;   // 释放临时数组
}

int main() {
    float src[] = {1, 5, 3, 6, 9, 2, 8, 7, 4};   // 输入数组
    float dst[9];   // 输出数组
    float sigma_s = 1.0f;   // 空间域标准差
    float sigma_r = 1.0f;   // 灰度值域标准差

    bilateralFilter(src, dst, 3, 3, sigma_s, sigma_r);   // 对输入数组进行双边滤波

   
#include <iostream>
#include <cmath>

using namespace std;

// 定义一个函数,用于计算两个像素之间的距离
float distance(int x1, int y1, int x2, int y2) {
    return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
}

// 定义一个函数,用于计算双边滤波中的权重
float weight(float distance, float sigma_d, float sigma_r) {
    return exp(-pow(distance, 2) / (2 * pow(sigma_d, 2))) * exp(-pow(distance, 2) / (2 * pow(sigma_r, 2)));
}

// 定义一个函数,用于对图像进行双边滤波
void bilateralFilter(int* src, int* dst, int width, int height, float sigma_d, float sigma_r) {
    int k = 2 * ceil(sigma_d) + 1;   // 计算卷积核的大小
    float w_sum = 0;   // 定义一个变量,用于存储权重的和
    for (int i = k/2; i < height-k/2; i++) {
        for (int j = k/2; j < width-k/2; j++) {
            float sum = 0;   // 定义一个变量,用于存储加权平均值
            w_sum = 0;   // 重置权重的和
            for (int m = -k/2; m <= k/2; m++) {
                for (int n = -k/2; n <= k/2; n++) {
                    int x = i + m;
                    int y = j + n;
                    if (x >= 0 && x < height && y >= 0 && y < width) {   // 如果像素在图像范围内
                        float d = distance(i, j, x, y);   // 计算像素之间的距离
                        float w = weight(d, sigma_d, sigma_r);   // 计算像素之间的权重
                        sum += w * src[x*width+y];   // 将加权像素值相加
                        w_sum += w;   // 将权重相加
                    }
                }
            }
            dst[i*width+j] = round(sum / w_sum);   // 计算加权平均值,并将结果存储到输出图像中
        }
    }
}

int main() {
    int src[] = {1, 5, 3, 6, 9, 2, 8, 7, 4};   // 输入数组
    int dst[9];   // 输出数组
    float sigma_d = 1;   // 空间域标准差
    float sigma_r = 1

猜你喜欢

转载自blog.csdn.net/Angelloveyatou/article/details/130501373