C语言boxblur算法如何高效实现?

99ANYc3cd6
预计阅读时长 20 分钟
位置: 首页 C语言 正文

C语言实现Box Blur算法

Box Blur(盒式模糊)是一种简单的图像模糊算法,它通过计算像素周围邻域内像素的平均值来实现模糊效果,下面我将提供一个完整的C语言实现。

c语言 boxblur
(图片来源网络,侵删)

算法原理

Box Blur的核心思想是用一个固定大小的矩形窗口(称为"盒子")在图像上滑动,对每个像素,将其值替换为窗口内所有像素的平均值。

C语言实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 图像结构体
typedef struct {
    int width;
    int height;
    unsigned char *data; // 假设是灰度图像,每个像素1字节
} Image;
// 创建新图像
Image* create_image(int width, int height) {
    Image *img = (Image*)malloc(sizeof(Image));
    img->width = width;
    img->height = height;
    img->data = (unsigned char*)malloc(width * height * sizeof(unsigned char));
    return img;
}
// 释放图像内存
void free_image(Image *img) {
    free(img->data);
    free(img);
}
// Box Blur函数
Image* box_blur(Image *input, int radius) {
    int width = input->width;
    int height = input->height;
    Image *output = create_image(width, height);
    // 计算盒子大小 (2*radius + 1)
    int box_size = 2 * radius + 1;
    int box_area = box_size * box_size;
    // 遍历图像每个像素
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            unsigned long sum = 0;
            int count = 0;
            // 遍历盒子内的像素
            for (int dy = -radius; dy <= radius; dy++) {
                for (int dx = -radius; dx <= radius; dx++) {
                    int nx = x + dx;
                    int ny = y + dy;
                    // 检查边界
                    if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                        sum += input->data[ny * width + nx];
                        count++;
                    }
                }
            }
            // 计算平均值并存储
            output->data[y * width + x] = (unsigned char)(sum / count);
        }
    }
    return output;
}
// 示例使用
int main() {
    // 创建一个简单的测试图像 (5x5)
    int width = 5, height = 5;
    Image *test_img = create_image(width, height);
    // 填充测试数据 (简单模式)
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            test_img->data[y * width + x] = (x + y) % 256;
        }
    }
    printf("Original image:\n");
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            printf("%3d ", test_img->data[y * width + x]);
        }
        printf("\n");
    }
    // 应用Box Blur,半径为1
    Image *blurred = box_blur(test_img, 1);
    printf("\nBlurred image (radius=1):\n");
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            printf("%3d ", blurred->data[y * width + x]);
        }
        printf("\n");
    }
    // 释放内存
    free_image(test_img);
    free_image(blurred);
    return 0;
}

优化版本

上面的实现是基础版本,效率不高,以下是优化后的版本,使用积分图像(Integral Image)来加速计算:

// 计算积分图像
void compute_integral_image(Image *input, unsigned long *integral) {
    int width = input->width;
    int height = input->height;
    // 第一行
    integral[0] = input->data[0];
    for (int x = 1; x < width; x++) {
        integral[x] = integral[x-1] + input->data[x];
    }
    // 剩余行
    for (int y = 1; y < height; y++) {
        integral[y * width] = integral[(y-1) * width] + input->data[y * width];
        for (int x = 1; x < width; x++) {
            integral[y * width + x] = integral[y * width + x - 1] + 
                                     integral[(y-1) * width + x] - 
                                     integral[(y-1) * width + x - 1] + 
                                     input->data[y * width + x];
        }
    }
}
// 使用积分图像的Box Blur
Image* box_blur_integral(Image *input, int radius) {
    int width = input->width;
    int height = input->height;
    Image *output = create_image(width, height);
    // 计算积分图像
    unsigned long *integral = (unsigned long*)malloc(width * height * sizeof(unsigned long));
    compute_integral_image(input, integral);
    int box_size = 2 * radius + 1;
    int box_area = box_size * box_size;
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            // 计算盒子区域的边界
            int x1 = (x - radius) < 0 ? 0 : (x - radius);
            int y1 = (y - radius) < 0 ? 0 : (y - radius);
            int x2 = (x + radius) >= width ? (width - 1) : (x + radius);
            int y2 = (y + radius) >= height ? (height - 1) : (y + radius);
            // 计算区域面积
            int area = (x2 - x1 + 1) * (y2 - y1 + 1);
            // 使用积分图像计算区域和
            unsigned long sum = integral[y2 * width + x2];
            if (x1 > 0) sum -= integral[y2 * width + (x1 - 1)];
            if (y1 > 0) sum -= integral[(y1 - 1) * width + x2];
            if (x1 > 0 && y1 > 0) sum += integral[(y1 - 1) * width + (x1 - 1)];
            // 计算平均值
            output->data[y * width + x] = (unsigned char)(sum / area);
        }
    }
    free(integral);
    return output;
}

注意事项

  1. 边界处理:上述实现已经考虑了边界情况,当盒子超出图像边界时会自动调整。
  2. 性能:优化版本使用积分图像,时间复杂度从O(n²r²)降低到O(n²),其中n是图像像素数,r是半径。
  3. 扩展:对于彩色图像,可以分别对R、G、B三个通道应用Box Blur。
  4. 多次模糊:Box Blur多次应用(通常3次)可以近似高斯模糊的效果。

这个实现可以很容易地扩展到处理彩色图像(如RGB或RGBA格式),只需要对每个颜色通道分别应用Box Blur即可。

c语言 boxblur
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
dede定时自动发布
« 上一篇 04-21
织梦模板上传文件夹路径在哪?
下一篇 » 04-21

相关文章

取消
微信二维码
支付宝二维码

目录[+]