C/C++ Sobel算子算法详解及源码 不掉库,对BMP图像进行处理28*28
时间: 2025-03-08 14:02:18 浏览: 30
### 实现Sobel算子算法
为了实现在不依赖外部库的情况下处理28x28大小的BMP图像,可以采用直接读取并解析BMP文件头的方式。以下是详细的实现方法:
#### 解析BMP文件结构
BMP文件由三部分组成:文件头、位图信息头以及实际的像素数据。
- 文件头(`BITMAPFILEHEADER`),长度为14字节;
- 位图信息头(`BITMAPINFOHEADER`),长度通常为40字节;
- 像素数组,存储着图像的颜色信息。
对于28×28尺寸的小型灰度图片来说,可以直接通过指针操作访问这些区域内的每一个像素值[^3]。
#### Sobel算子计算过程
Sobel算子用于获取数字图像的一阶梯度,基于加权模板卷积来增强边缘特征。具体而言,分别沿X轴方向和Y轴方向应用两个不同的核矩阵进行滤波运算,从而得到水平梯度分量Gx与垂直梯度分量Gy:
\[ G_x=\left[\begin{array}{ccc}
-1 & 0 & +1 \\
-2 & 0 & +2\\
-1& 0 &+1\end{array}\right]\ast I \]
\[ G_y=\left[\begin{array}{rrr}
-1 & -2 & -1 \\
0 & 0 & 0\\
+1& +2 &+1\end{array}\right]\ast I \]
其中\(I\)表示输入图像;符号"\(\ast\)"代表二维空间上的线性卷积操作。最终输出的结果可以通过组合这两个方向上的响应幅值得到完整的边界映射图象[^4]。
#### C/C++代码示例
下面给出一段简单的C语言程序片段,演示如何加载指定路径下的单通道(即灰度)BMP格式小图,并对其进行Sobel变换后保存新生成的目标文件。
```c
#include <stdio.h>
#include <stdlib.h>
#define WIDTH 28
#define HEIGHT 28
// 定义BMP文件头部结构体
#pragma pack(push, 1)
typedef struct tag_BITMAPFILEHEADER {
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} BITMAPFILEHEADER;
typedef struct tag_BITMAPINFOHEADER{
unsigned int biSize;
signed int biWidth;
signed int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
signed int biXPelsPerMeter;
signed int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BITMAPINFOHEADER;
#pragma pack(pop)
void sobel(unsigned char* imgData){
static const int kernel_x[] = {-1, 0, 1,
-2, 0, 2,
-1, 0, 1};
static const int kernel_y[] = {-1,-2,-1,
0, 0, 0,
+1,+2,+1};
for(int y=1;y<HEIGHT-1;++y){
for(int x=1;x<WIDTH-1;++x){
float sum_x = 0.0f,sum_y = 0.0f;
for (int ky=-1;ky<=1;++ky){
for (int kx=-1;kx<=1;++kx){
sum_x += ((float)(imgData[(y+ky)*WIDTH+(x+kx)])) * kernel_x[(ky+1)*3+(kx+1)];
sum_y += ((float)(imgData[(y+ky)*WIDTH+(x+kx)])) * kernel_y[(ky+1)*3+(kx+1)];
}
}
// 计算模长作为新的像素强度
float magnitude = sqrt(sum_x*sum_x + sum_y*sum_y);
if(magnitude>255)magnitude=255;
if(magnitude<0)magnitude=0;
imgData[y*WIDTH+x]=(unsigned char)magnitude;
}
}
}
int main(){
FILE *fp_in,*fp_out;
fp_in=fopen("input.bmp","rb");
if(!fp_in){printf("Failed to open input file.\n");return -1;}
BITMAPFILEHEADER bmfh;
fread(&bmfh,sizeof(BITMAPFILEHEADER),1,fp_in);
BITMAPINFOHEADER bmih;
fread(&bmih,sizeof(BITMAPINFOHEADER),1,fp_in);
fseek(fp_in,bmfh.bfOffBits,SEEK_SET);
unsigned char buffer[WIDTH*HEIGHT];
fread(buffer,sizeof(unsigned char),WIDTH*HEIGHT,fp_in);
fclose(fp_in);
sobel(buffer);
fp_out=fopen("output.bmp","wb+");
fwrite(&bmfh,sizeof(BITMAPFILEHEADER),1,fp_out);
fwrite(&bmih,sizeof(BITMAPINFOHEADER),1,fp_out);
fwrite(buffer,sizeof(unsigned char),WIDTH*HEIGHT,fp_out);
fclose(fp_out);
printf("Processing completed successfully!\n");
return 0;
}
```
该段代码实现了基本的功能需求,包括但不限于打开原始图像文件、提取必要的元数据信息、执行核心的Sobel过滤逻辑以及最后写出修改后的版本至磁盘中去[^1]。
阅读全文
相关推荐


















