C语言实现图像中值滤波
时间: 2023-05-31 12:04:51 浏览: 61
中值滤波是一种常用的图像处理技术,可以去除图像噪声并平滑图像。以下是C语言实现图像中值滤波的示例代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BMP_HEADER_SIZE 54
#pragma pack(push, 1)
typedef struct
{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} BMPFileHeader;
typedef struct
{
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BMPInfoHeader;
#pragma pack(pop)
// 读取BMP文件
unsigned char* readBMP(const char* filename, BMPFileHeader* fileHeader, BMPInfoHeader* infoHeader)
{
FILE* fp = fopen(filename, "rb");
if (!fp)
{
printf("读取BMP文件失败: %s\n", filename);
return NULL;
}
fread(fileHeader, sizeof(BMPFileHeader), 1, fp);
fread(infoHeader, sizeof(BMPInfoHeader), 1, fp);
int width = infoHeader->biWidth;
int height = infoHeader->biHeight;
int bitCount = infoHeader->biBitCount;
if (bitCount != 24)
{
printf("只支持24位色的BMP文件\n");
fclose(fp);
return NULL;
}
int rowSize = (width * 3 + 3) & ~3;
int imageSize = rowSize * height;
unsigned char* imageData = (unsigned char*)malloc(imageSize);
fseek(fp, fileHeader->bfOffBits, SEEK_SET);
for (int i = 0; i < height; i++)
{
fread(imageData + i * rowSize, rowSize, 1, fp);
}
fclose(fp);
return imageData;
}
// 写入BMP文件
void writeBMP(const char* filename, BMPFileHeader* fileHeader, BMPInfoHeader* infoHeader, unsigned char* imageData)
{
FILE* fp = fopen(filename, "wb");
if (!fp)
{
printf("写入BMP文件失败: %s\n", filename);
return;
}
fwrite(fileHeader, sizeof(BMPFileHeader), 1, fp);
fwrite(infoHeader, sizeof(BMPInfoHeader), 1, fp);
int width = infoHeader->biWidth;
int height = infoHeader->biHeight;
int bitCount = infoHeader->biBitCount;
int rowSize = (width * 3 + 3) & ~3;
int imageSize = rowSize * height;
fseek(fp, fileHeader->bfOffBits, SEEK_SET);
for (int i = 0; i < height; i++)
{
fwrite(imageData + i * rowSize, rowSize, 1, fp);
}
fclose(fp);
}
// 对一组像素进行中值滤波
void medianFilter(unsigned char* imageData, int width, int height, int x, int y)
{
int size = 3; // 滤波器大小
int halfSize = size / 2; // 半径
unsigned char* buffer = (unsigned char*)malloc(size * size * sizeof(unsigned char));
int index = 0;
// 读取周围像素的值
for (int i = -halfSize; i <= halfSize; i++)
{
for (int j = -halfSize; j <= halfSize; j++)
{
int px = x + j;
int py = y + i;
if (px < 0) px = 0;
if (py < 0) py = 0;
if (px >= width) px = width - 1;
if (py >= height) py = height - 1;
buffer[index++] = imageData[py * width * 3 + px * 3];
}
}
// 对像素值进行排序
for (int i = 0; i < size * size - 1; i++)
{
for (int j = i + 1; j < size * size; j++)
{
if (buffer[i] > buffer[j])
{
unsigned char temp = buffer[i];
buffer[i] = buffer[j];
buffer[j] = temp;
}
}
}
// 取中值
imageData[y * width * 3 + x * 3] = buffer[size * size / 2];
imageData[y * width * 3 + x * 3 + 1] = buffer[size * size / 2];
imageData[y * width * 3 + x * 3 + 2] = buffer[size * size / 2];
free(buffer);
}
int main()
{
const char* filename = "lena.bmp";
BMPFileHeader fileHeader;
BMPInfoHeader infoHeader;
unsigned char* imageData = readBMP(filename, &fileHeader, &infoHeader);
if (!imageData)
{
return 1;
}
int width = infoHeader.biWidth;
int height = infoHeader.biHeight;
int bitCount = infoHeader.biBitCount;
// 对每个像素进行中值滤波
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
medianFilter(imageData, width, height, j, i);
}
}
// 保存结果
writeBMP("lena_median.bmp", &fileHeader, &infoHeader, imageData);
free(imageData);
return 0;
}
```
代码中使用了读取和写入BMP文件的函数,这里不再赘述。`medianFilter`函数实现了对一个像素的中值滤波,对于每个像素,都调用该函数进行处理。最终结果保存在`lena_median.bmp`文件中。