32x32热成像高斯滤波图像处理

高斯滤波图像处理

采集的是32x32 热成像数据,下面是原始数据

复制代码
3051  3045  3041  3041  3054  3029  3054  3033  3035  3034  3034  3035  3035  3038  3041  3026  3041  3034  3041  3025  3037  3018  3014  3002  3018  3025  3019  3002  3017  3008  3024  3018 
 3055  3041  3039  3043  3034  3023  3045  3035  3031  3034  3040  3022  3048  3041  3048  3058  3055  3056  3041  3044  3028  3022  3019  3023  3022  3015  3004  3032  3029  3009  3013  3023 
 3054  3041  3054  3041  3029  3054  3040  3041  3034  3050  3027  3048  3063  3062  3053  3056  3052  3050  3057  3051  3051  3033  3033  3031  3018  3004  3007  3021  3016  3016  3024  3039 
 3030  3044  3040  3042  3042  3033  3044  3047  3034  3039  3061  3061  3064  3071  3059  3056  3049  3050  3052  3056  3054  3032  3031  3022  3016  3013  3029  3021  3026  3030  3016  3005 
 2980  2982  2994  2997  2998  2991  3001  3001  2990  3009  3007  3010  3017  3018  3034  3032  3035  3036  3024  3027  3016  3004  3021  3001  3015  3012  3012  3020  3013  3011  3026  3021 
 2992  2983  2990  2989  3003  3007  3000  2997  2995  3009  3007  3012  3033  3032  3042  3043  3033  3027  3035  3035  3018  3008  3020  3007  3013  3020  3024  3024  3016  2999  3017  3029 
 2997  2989  2994  2997  2998  3000  3021  3015  3007  3024  3023  3039  3048  3057  3028  3044  3039  3041  3048  3031  3032  3040  3023  3037  3041  3041  3035  3038  3029  3031  3020  3029 
 2992  2999  3009  2982  3002  3007  3017  3023  3024  3033  3043  3043  3053  3052  3052  3053  3053  3057  3040  3035  3046  3028  3020  3019  3015  3027  3031  3024  3015  3022  3029  3030 
 3017  2994  2998  3009  3007  3008  3016  3023  3032  3043  3056  3071  3078  3086  3056  3065  3069  3068  3056  3044  3039  3033  3042  3022  3020  3024  3023  3016  3024  3020  3002  3020 
 3013  3011  3013  3009  3010  3009  3023  3026  3051  3048  3060  3083  3080  3090  3099  3093  3089  3092  3087  3050  3043  3055  3034  3036  3031  3023  3024  3009  3007  3001  3016  3007 
 3008  3008  3024  3027  3011  3010  3023  3041  3047  3052  3084  3071  3087  3095  3101  3104  3108  3106  3087  3057  3037  3034  3052  3054  3036  3014  3020  3016  3009  3003  3002  3031 
 3006  3012  3014  3006  3022  3010  3019  3035  3038  3060  3062  3095  3112  3104  3104  3091  3107  3099  3086  3050  3049  3040  3049  3046  3051  3030  3018  3010  3020  3017  3022  3029 
 3012  3015  3012  3014  3020  3010  3022  3034  3044  3053  3064  3097  3097  3101  3101  3095  3094  3098  3092  3073  3049  3046  3050  3058  3051  3040  3022  3022  3017  3023  3020  3029 
 3017  3017  3029  3011  3013  3009  3026  3036  3041  3048  3104  3099  3107  3102  3094  3106  3105  3103  3091  3088  3055  3055  3073  3059  3057  3024  3014  3018  3004  3017  3013  3005 
 3013  3028  3031  3018  3003  3018  3018  3036  3041  3056  3098  3094  3081  3107  3105  3114  3107  3103  3109  3093  3077  3084  3090  3086  3053  3038  3020  3027  3001  3025  3020  3009 
 3029  3016  3020  3019  3019  3002  3006  3013  3052  3081  3103  3093  3091  3094  3096  3115  3104  3099  3103  3093  3108  3101  3103  3094  3056  3026  3031  3032  3019  3032  3010  3017 
 3027  3024  3006  3007  3012  2997  3010  3004  3040  3076  3090  3097  3089  3094  3105  3103  3097  3112  3102  3095  3096  3085  3087  3086  3052  3022  3024  3012  3014  3024  3011  3023 
 3024  3029  3033  3037  3020  2994  2999  3009  3053  3080  3084  3095  3097  3088  3105  3104  3105  3100  3106  3104  3103  3101  3099  3097  3068  3031  3018  3016  3017  3025  3018  3016 
 3025  3018  3016  3025  3015  3015  3008  3011  3036  3071  3093  3092  3096  3092  3091  3100  3113  3103  3101  3100  3102  3101  3103  3089  3042  3026  3041  3018  3017  3021  3026  3009 
 3016  3024  3012  3015  3014  3001  2996  3004  3022  3075  3080  3095  3091  3095  3109  3100  3104  3099  3103  3105  3108  3103  3089  3089  3040  3019  3008  3012  3021  3012  3012  3023 
 3009  3021  3018  3024  3003  2998  2999  3009  2999  3069  3083  3086  3093  3095  3099  3090  3091  3108  3108  3099  3096  3087  3098  3056  3026  3029  3015  2998  3009  3014  3023  3017 
 3015  3017  3010  3002  3012  3008  3015  3010  3005  3036  3080  3097  3093  3101  3108  3096  3098  3108  3093  3106  3094  3097  3092  3035  3015  3019  3017  3010  3018  3019  3023  3011 
 3016  3006  3004  3003  3012  3011  3003  3003  3006  3018  3080  3079  3082  3087  3092  3091  3090  3100  3099  3092  3093  3086  3086  3026  3023  3017  3028  3037  3032  3007  3023  3034 
 3009  3006  3005  3013  2997  3005  2991  2996  2996  3010  3059  3086  3088  3099  3104  3107  3093  3102  3096  3091  3089  3094  3053  3016  3021  3012  3015  3033  3049  3029  3016  3033 
 2992  3023  3021  3002  3013  2991  2998  3002  2990  3010  3010  3076  3085  3092  3088  3095  3105  3102  3103  3095  3089  3088  3031  3019  3017  3015  3035  3035  3053  3031  3027  3030 
 2996  3027  3008  3005  3003  2999  2999  2998  3002  3014  3013  3051  3086  3094  3094  3096  3106  3102  3098  3082  3092  3061  3024  3015  3022  3014  3038  3041  3059  3041  3041  3022 
 3015  2996  3019  3006  3005  3003  3002  2990  2991  3004  3011  3050  3086  3091  3080  3089  3090  3107  3099  3092  3101  3067  3041  3021  3022  3034  3041  3033  3056  3052  3029  3067 
 2989  3006  2995  3001  2992  3005  2997  3006  3019  3009  3011  3040  3085  3093  3087  3093  3094  3096  3088  3089  3084  3076  3035  3020  3014  3031  3015  3023  3045  3062  3054  3047 
 3005  3018  3011  3023  3022  3031  3038  3048  3058  3065  3089  3093  3093  3103  3091  3088  3088  3104  3101  3097  3092  3101  3100  3076  3062  3072  3062  3058  3069  3060  3076  3060 
 3002  3025  3037  3056  3045  3052  3058  3065  3072  3080  3100  3090  3097  3097  3085  3083  3105  3102  3096  3097  3104  3101  3091  3081  3071  3069  3066  3068  3083  3071  3081  3064 
 3038  3043  3051  3054  3071  3078  3062  3061  3063  3086  3086  3090  3099  3096  3095  3089  3106  3097  3093  3087  3092  3084  3095  3071  3082  3083  3089  3085  3078  3083  3078  3075 
 3042  3071  3065  3064  3078  3073  3064  3064  3074  3075  3089  3076  3094  3107  3096  3089  3083  3092  3097  3092  3078  3096  3084  3079  3080  3086  3101  3080  3072  3098  3086  3082 
  • 上述中的数据复制粘贴到data.txt 注意格式32*32,每个数据之间空格
  • 读取data.txt数据,高斯滤波后的数据写入xlsx文件,使用色阶 红-黄-绿 即可看到滤波后的图像
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include "xlsxwriter.h"

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#define IMG_SIZE 32
#define KERNEL_SIZE 7

// 生成高斯核,kernel 为 KERNEL_SIZE x KERNEL_SIZE 的二维数组,sigma 为标准差
void createGaussianKernel(float kernel[KERNEL_SIZE][KERNEL_SIZE], float sigma) {
    int i, j;
    int half = KERNEL_SIZE / 2;
    float sum = 0.0f;
    float s = 2.0f * sigma * sigma;
    
    for (i = 0; i < KERNEL_SIZE; i++) {
        for (j = 0; j < KERNEL_SIZE; j++) {
            int x = i - half;
            int y = j - half;
            kernel[i][j] = expf(-(x * x + y * y) / s) / (M_PI * s);
            sum += kernel[i][j];
        }
    }
    
    // 归一化高斯核
    for (i = 0; i < KERNEL_SIZE; i++) {
        for (j = 0; j < KERNEL_SIZE; j++) {
            kernel[i][j] /= sum;
        }
    }
}

// 对输入图像进行高斯滤波(数据以一维数组存储,长度为 IMG_SIZE*IMG_SIZE)
// 这里先将 uint16_t 数据转换为 float 进行计算,计算结果再转换回 uint16_t
void applyGaussianFilter(const uint16_t input_uint16[], uint16_t output_uint16[], float kernel[KERNEL_SIZE][KERNEL_SIZE]) {
    float input[IMG_SIZE * IMG_SIZE];
    float output[IMG_SIZE * IMG_SIZE];
    int i, j, m, n;
    int half = KERNEL_SIZE / 2;
    
    // 将输入数据转换为 float
    for (i = 0; i < IMG_SIZE * IMG_SIZE; i++) {
        input[i] = (float)input_uint16[i];
    }
    
    // 进行高斯滤波
    for (i = 0; i < IMG_SIZE; i++) {
        for (j = 0; j < IMG_SIZE; j++) {
            float sum = 0.0f;
            for (m = 0; m < KERNEL_SIZE; m++) {
                for (n = 0; n < KERNEL_SIZE; n++) {
                    int x = i + m - half;
                    int y = j + n - half;
                    if (x >= 0 && x < IMG_SIZE && y >= 0 && y < IMG_SIZE) {
                        sum += input[x * IMG_SIZE + y] * kernel[m][n];
                    }
                }
            }
            output[i * IMG_SIZE + j] = sum;
        }
    }
    
    // 将滤波结果转换回 uint16_t,并进行必要的截断处理(例如舍入到最近的整数)
    for (i = 0; i < IMG_SIZE * IMG_SIZE; i++) {
        if (output[i] < 0.0f)
            output_uint16[i] = 0;
        else if (output[i] > 65535.0f)
            output_uint16[i] = 65535;
        else
            output_uint16[i] = (uint16_t)(output[i] + 0.5f);  // 四舍五入
    }
}


int main(void) {
    uint16_t pixelData[IMG_SIZE * IMG_SIZE];
    uint16_t filteredData[IMG_SIZE * IMG_SIZE];
    float kernel[KERNEL_SIZE][KERNEL_SIZE];
    float sigma = 1.0f;  // 根据需要调整 sigma 值

    // 打开 data.txt 文件读取原始数据
    FILE *inputFile = fopen("data.txt", "r");
    if (inputFile == NULL) {
        perror("无法打开 data.txt 文件");
        return EXIT_FAILURE;
    }
    
    // 读取 32×32 的数据(假设文件中数据以空白符分隔)
    for (int i = 0; i < IMG_SIZE * IMG_SIZE; i++) {
        if (fscanf(inputFile, "%hu", &pixelData[i]) != 1) {
            fprintf(stderr, "读取数据失败,数据数量不足\n");
            fclose(inputFile);
            return EXIT_FAILURE;
        }
    }
    fclose(inputFile);

    // 生成高斯核
    createGaussianKernel(kernel, sigma);
    
    // 对数据应用高斯滤波
    applyGaussianFilter(pixelData, filteredData, kernel);
    
    // 使用 libxlsxwriter 生成 XLSX 文件
    lxw_workbook  *workbook  = workbook_new("gaosi_output.xlsx");
    lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
    
    // 可选:设置行高、列宽
    for (int row = 0; row < IMG_SIZE; row++) {
        worksheet_set_row(worksheet, row, 30, NULL);
    }
    worksheet_set_column(worksheet, 0, IMG_SIZE - 1, 5, NULL);

    // 将滤波后的数据写入 XLSX 文件
    for (int i = 0; i < IMG_SIZE; i++) {
        for (int j = 0; j < IMG_SIZE; j++) {
            // 这里将 uint16_t 转为 double 写入单元格
            worksheet_write_number(worksheet, i, j, (double)filteredData[i * IMG_SIZE + j], NULL);
        }
    }
    
    workbook_close(workbook);
    
    printf("高斯滤波处理完成,结果已保存至 gaosi_output.xlsx\n");
    return EXIT_SUCCESS;
}

编译:

复制代码
 gcc -o gaosi_process gaosi_process.c -lm -lxlsxwriter -lz

滤波前的图像显示如下: (头的右边头发盖住了)

滤波后的图像显示如下:

  • 图像中可以看出滤波后的图像四个边角的数值最小偏差最大,以及边框的部分数值偏差也比较大

边缘和角落的数据偏差通常是由边缘处理方式造成的。在代码中,采用零填充(即超出图像范围的像素值视为 0)会导致在边缘和角落区域,卷积窗口内有效数据较少,从而使得滤波后的值偏小。

解决方法

采用边缘复制(replicate padding)或镜像填充(mirrored padding)

这种方法可以使得当卷积窗口超出图像范围时,用最近的边缘像素值来填充,而不是简单地用 0 填充。这样可以较好地保持边缘的亮度和信息。

  • 更改函数applyGaussianFilter
c 复制代码
// 对输入图像进行高斯滤波(数据以一维数组存储,长度为 IMG_SIZE*IMG_SIZE)
// 这里先将 uint16_t 数据转换为 float 进行计算,计算结果再转换回 uint16_t
void applyGaussianFilter(const uint16_t input_uint16[], uint16_t output_uint16[], float kernel[KERNEL_SIZE][KERNEL_SIZE]) {
    float input[IMG_SIZE * IMG_SIZE];
    float output[IMG_SIZE * IMG_SIZE];
    int i, j, m, n;
    int half = KERNEL_SIZE / 2;
    
    // 将输入数据转换为 float
    for (i = 0; i < IMG_SIZE * IMG_SIZE; i++) {
        input[i] = (float)input_uint16[i];
    }
    
    // 进行高斯滤波
    for (i = 0; i < IMG_SIZE; i++) {
        for (j = 0; j < IMG_SIZE; j++) {
            float sum = 0.0f;
            for (m = 0; m < KERNEL_SIZE; m++) {
                for (n = 0; n < KERNEL_SIZE; n++) {
                    int x = i + m - half;
                    int y = j + n - half;
                    
                    // 复制边缘像素处理
                    if (x < 0)
                        x = 0;
                    else if (x >= IMG_SIZE)
                        x = IMG_SIZE - 1;
                    
                    if (y < 0)
                        y = 0;
                    else if (y >= IMG_SIZE)
                        y = IMG_SIZE - 1;
                    
                    sum += input[x * IMG_SIZE + y] * kernel[m][n];
                }
            }
            output[i * IMG_SIZE + j] = sum;
        }
    }
    
    // 将滤波结果转换回 uint16_t,并进行必要的截断处理(例如舍入到最近的整数)
    for (i = 0; i < IMG_SIZE * IMG_SIZE; i++) {
        if (output[i] < 0.0f)
            output_uint16[i] = 0;
        else if (output[i] > 65535.0f)
            output_uint16[i] = 65535;
        else
            output_uint16[i] = (uint16_t)(output[i] + 0.5f);  // 四舍五入
    }
}

滤波后的图像显示,这时候边框部分没有明显的偏差了

滤波前后图像对比

原始图像下载 https://newbie-typora.oss-cn-shenzhen.aliyuncs.com/zhongke/output.xlsx

高斯图像下载 https://newbie-typora.oss-cn-shenzhen.aliyuncs.com/zhongke/gaosi_output.xlsx

高斯滤波参数调整影响:

高斯滤波在图像处理中是非常常见的平滑方法,它的"可调参数"会直接影响图像平滑的效果、边缘保留程度、噪声抑制能力等。以下是高斯滤波可调整的主要参数,以及每个参数调整后对结果的影响:

1. 高斯核大小(Kernel Size)

含义:卷积核的尺寸,比如 3×3、5×5、7×7、9×9 等。

  • 小核(如 3×3)
    • 平滑效果较弱;
    • 能保留更多细节;
    • 抗噪能力较弱;
    • 计算速度快。
  • 大核(如 7×7 或 9×9)
    • 平滑效果更强;
    • 会模糊细节(特别是边缘);
    • 抗噪能力强;
    • 计算开销更大。

通常建议:核大小设为奇数(如 3、5、7、9),并满足经验公式:

复制代码
kernel_size ≈ 6 × sigma + 1

2. σ(Sigma,标准差)

含义:控制高斯函数的"扩散程度",影响核中每个像素的权重分布。

  • 小 σ(如 0.5 ~ 1.0)
    • 高斯核权重集中在中心;
    • 仅平滑邻近像素;
    • 更好保留细节,模糊程度小。
  • 大 σ(如 2.0 ~ 3.0)
    • 权重分布更宽;
    • 模糊半径大;
    • 更强的去噪效果,但可能过度模糊。

注意:即使核尺寸一样,调整 sigma 也能控制模糊程度。


3. 边缘处理方式(Padding Mode)

含义:当卷积窗口超出图像边界时如何处理:

  • 零填充(Zero Padding)
    • 边缘可能变暗或失真;
    • 快速简便,但对边缘不友好。
  • 边缘复制(Replicate Padding)
    • 使用边界上的值填充;
    • 可有效缓解边缘模糊变暗的问题。
  • 镜像填充(Reflect Padding)
    • 像镜子一样反射边缘;
    • 更自然的边界过渡,常用于图像处理。

4. 数据类型和精度

  • 使用 uint8_tuint16_t 会丢失小数部分;
  • 使用 floatdouble 可以更高精度地表达滤波结果;
  • 最终输出再根据需求量化为整数类型。

5. 滤波方式(单通道 / 多通道)

  • 彩色图像需对每个通道分别滤波(RGB 分别处理);
  • 可以选用更高级的颜色感知高斯滤波,如 bilateral filter(双边滤波)避免颜色混淆。

📝 可视化示例对比(描述性)

参数组合 效果说明
核 3×3,σ = 0.5 稍微平滑,细节清晰
核 7×7,σ = 1.5 明显平滑,小物体边界模糊
核 9×9,σ = 3.0 强烈模糊,细节丢失但噪声干净
零填充 边缘明显偏暗
复制边缘填充 边缘平滑,自然过渡

✅ 推荐的调参策略

目标 推荐参数设置
轻度降噪,细节保留 核 3×3 或 5×5,σ = 0.8 ~ 1.0
中度去噪 核 5×5 或 7×7,σ = 1.0 ~ 1.5
强烈平滑(模糊) 核 7×7 或 9×9,σ = 2.0 ~ 3.0
避免边缘异常 使用"复制边缘"或"镜像填充"

在处理低分辨率(32×32)的热成像数据时,目标通常是降低噪声的同时保留温度的梯度和局部特征。这里有一些调参建议:

  1. 核大小
    • 推荐使用 3×3 或 5×5 核
    • 对于 32×32 的数据来说,过大的核(如 7×7 或更大)可能导致过度平滑,使得温度梯度模糊,降低局部细节的辨识度。
  2. σ(标准差)
    • 建议选择较小到中等的 σ 值,比如 0.8~1.5
    • 较小的 σ 值可以减少模糊效应,保留更多的细节;若噪声较大,可适当增大 σ 值,但不要超过 1.5,否则可能丢失局部温差信息。
  3. 边缘处理
    • 建议使用边缘复制或镜像填充而不是零填充。
    • 32×32 图像中,边缘数据占比相对较大,复制边缘可以避免边界区域温度值明显偏低的问题。
  4. 噪声与细节权衡
    • 由于热成像数据往往本身噪声较多,可适当进行平滑处理,但过度平滑可能掩盖真实温差。
    • 可尝试先对比 3×3、σ=1.0 和 5×5、σ=1.0~1.5 的效果,再根据实际情况调整。
  5. 实验和反馈
    • 对于热成像显示,建议进行几组参数试验:
      • 3×3核、σ=0.8:保留细节但噪声可能较明显。
      • 5×5核、σ=1.0:平滑效果较好且能保留温度梯度。
      • 5×5核、σ=1.5:更强的平滑,但可能使局部温差减弱。
    • 根据视觉显示效果选择最佳组合。

在 32×32 的低分辨率热成像中,推荐从 5×5 核和 σ 在 1.0 左右开始,配合边缘复制处理,然后根据图像噪声水平和温差细节适当微调参数。这样既能降低噪声,又能尽量保持温度变化信息,获得更自然的视觉显示效果。

相关推荐
振鹏Dong10 分钟前
超大规模数据场景(思路)——面试高频算法题目
算法·面试
uhakadotcom11 分钟前
Python 与 ClickHouse Connect 集成:基础知识和实践
算法·面试·github
uhakadotcom12 分钟前
Python 量化计算入门:基础库和实用案例
后端·算法·面试
uhakadotcom1 小时前
使用 Python 与 BigQuery 进行交互:基础知识与实践
算法·面试
uhakadotcom1 小时前
使用 Hadoop MapReduce 和 Bigtable 进行单词统计
算法·面试·github
XYY3691 小时前
前缀和 一维差分和二维差分 差分&差分矩阵
数据结构·c++·算法·前缀和·差分
longlong int1 小时前
【每日算法】Day 16-1:跳表(Skip List)——Redis有序集合的核心实现原理(C++手写实现)
数据库·c++·redis·算法·缓存
24白菜头1 小时前
C和C++(list)的链表初步
c语言·数据结构·c++·笔记·算法·链表
刺客-Andy2 小时前
前端加密方式 AES对称加密 RSA非对称加密 以及 MD5哈希算法详解
前端·javascript·算法·哈希算法
记得早睡~2 小时前
leetcode122-买卖股票的最佳时机II
javascript·数据结构·算法·leetcode