You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <stdio.h>
#include <time.h>
// 应用优化后的可分离高斯模糊到给定的二维数组src上并将结果存到二维数组dst中
void applySeparableGaussianBlur(float src[][5], float dst[][5], int h, int w, float kx[3], float ky[3]) {
float buf[3][3]; // 提前声明buf数组符合C89要求
int i, j; // 提前声明循环中使用的变量符合C89要求
// 初始化buf数组为0
for (i = 0; i < 3; ++i) {
for (j = 0; j < 3; ++j) {
buf[i][j] = 0;
}
}
// 宏定义用于循环利用buf数组的3个行缓冲区通过模运算确保索引值在0~2之间
#define IDX(n) ((n) % 3)
// 循环计算前两行的行内卷积并存储在buf中
for (i = 0; i < 2; ++i) {
for (j = 1; j < w - 1; ++j) {
buf[i][j] = src[i][j - 1] * kx[0] + src[i][j] * kx[1] + src[i][j + 1] * kx[2];
}
}
// 开始进行可分离卷积
for (i = 1; i < h - 1; ++i) {
// 计算当前行的行内卷积
for (j = 1; j < w - 1; ++j) {
buf[IDX(i)][j] = src[i][j - 1] * kx[0] + src[i][j] * kx[1] + src[i][j + 1] * kx[2];
}
// 进行行间的卷积得到最终像素值
for (j = 1; j < w - 1; ++j) {
dst[i][j] = buf[IDX(i - 1)][j] * ky[0] + buf[IDX(i)][j] * ky[1] + buf[IDX(i + 1)][j] * ky[2];
}
}
#undef IDX
}
// 原始的应用3x3 GaussianBlur函数与之前代码中的类似方便对比用时
void applyGaussianBlur(float src[][5], float dst[][5], int h, int w, float kernel[3][3]) {
int i, j; // 提前声明循环变量符合C89要求
for (i = 1; i < h - 1; ++i) {
for (j = 1; j < w - 1; ++j) {
dst[i][j] =
src[i - 1][j - 1] * kernel[0][0] + src[i - 1][j] * kernel[0][1] + src[i - 1][j + 1] * kernel[0][2] +
src[i][j - 1] * kernel[1][0] + src[i][j] * kernel[1][1] + src[i][j + 1] * kernel[1][2] +
src[i + 1][j - 1] * kernel[2][0] + src[i + 1][j] * kernel[2][1] + src[i + 1][j + 1] * kernel[2][2];
}
}
}
int main() {
float inputImage[5][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15},
{16, 17, 18, 19, 20},
{21, 22, 23, 24, 25}
};
float kernel[3][3] = {
{1.0f / 16, 2.0f / 16, 1.0f / 16},
{2.0f / 16, 4.0f / 16, 2.0f / 16},
{1.0f / 16, 2.0f / 16, 1.0f / 16}
};
float kx[3] = { 0.25f, 0.5f, 0.25f };
float ky[3] = { 0.25f, 0.5f, 0.25f };
float outputImage1[5][5]; // 存放原始GaussianBlur结果
float outputImage2[5][5]; // 存放优化后的可分离GaussianBlur结果
int i, j; // 提前声明循环变量符合C89要求
// 原始GaussianBlur计时开始
clock_t start_time1 = clock();
applyGaussianBlur(inputImage, outputImage1, 5, 5, kernel);
clock_t end_time1 = clock();
double elapsed_time1 = ((double)(end_time1 - start_time1)) / CLOCKS_PER_SEC;
// 优化后的可分离GaussianBlur计时开始
clock_t start_time2 = clock();
applySeparableGaussianBlur(inputImage, outputImage2, 5, 5, kx, ky);
clock_t end_time2 = clock();
double elapsed_time2 = ((double)(end_time2 - start_time2)) / CLOCKS_PER_SEC;
// 输出原始GaussianBlur结果
printf("原始GaussianBlur后的图像矩阵\n");
for (i = 0; i < 5; ++i) {
for (j = 0; j < 5; ++j) {
printf("%.2f ", outputImage1[i][j]);
}
printf("\n");
}
printf("原始GaussianBlur运行时间%.6f 秒\n", elapsed_time1);
// 输出优化后的可分离GaussianBlur结果
printf("优化后的可分离GaussianBlur后的图像矩阵\n");
for (i = 0; i < 5; ++i) {
for (j = 0; j < 5; ++j) {
printf("%.2f ", outputImage2[i][j]);
}
printf("\n");
}
printf("优化后的可分离GaussianBlur运行时间%.6f 秒\n", elapsed_time2);
return 0;
}