《数字图像处理》冈萨雷斯,图像增强基础——平滑与锐化,C语言实现
平滑(低通)空间滤波,测试像素为500*500
平滑代码如下:
void smooth(const char* filename)
{
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
RGBQUAD bmpColorTable[256];
BYTE bmpValue[500 ][500];
FILE* fp;
if ((fp = fopen(filename, "rb")) == NULL)
{
printf("打开失败\n");
exit(1);
}
//读取图像信息
fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fread(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fread(bmpColorTable, sizeof(RGBQUAD), 256, fp);
fread(bmpValue, 1, 500 * 500, fp);
//将图像灰度值存入二维数组中
int grayValue_three[500][500] = {0};
int grayValue_eleven[500][500] = { 0 };
int grayValue_twentyone[500][500] = { 0 };
for (int i = 0; i < 500; i++)
{
for (int j = 0; j < 500; j++)
{
grayValue_three[i][j] = bmpColorTable[bmpValue[i][j]].rgbBlue;
grayValue_eleven[i][j] = bmpColorTable[bmpValue[i][j]].rgbBlue;
grayValue_twentyone[i][j] = bmpColorTable[bmpValue[i][j]].rgbBlue;
}
}
fclose(fp);
//3*3,11*11,21*21盒式核对图像进行低通滤波
int zero_fill_three[504][504] = { 0 }; // 零填充
int zero_fill_eleven[520][520] = { 0 };
int zero_fill_twentyone[540][540] = { 0 };
for (int i = 2; i < 502; i++)
{
for (int j = 2; j < 502; j++)
{
zero_fill_three[i][j] = grayValue_three[i-2][j-2];
}
}
for (int i = 10; i < 510; i++)
{
for (int j = 10; j < 510; j++)
{
zero_fill_eleven[i][j] = grayValue_eleven[i - 10][j - 10];
}
}
for (int i = 20; i < 520; i++)
{
for (int j = 20; j < 520; j++)
{
zero_fill_twentyone[i][j] = grayValue_twentyone[i - 20][j - 20];
}
}
for (int i = 0; i < 500; i++)
{
for (int j = 0; j < 500; j++)
{
grayValue_three[i][j] =0;
grayValue_eleven[i][j] = 0;
grayValue_twentyone[i][j] = 0;
}
}
for (int i = 2; i < 502; i++) //进行卷积
{
for (int j = 2; j < 502; j++)
{
for (int a = 0; a < 3; a++)
{
for (int b = 0; b < 3; b++)
{
grayValue_three[i-2][j-2] +=(double)(zero_fill_three[i-a][j-b]);
}
}
grayValue_three[i - 2][j - 2] = round(grayValue_three[i - 2][j - 2] / (3.0 * 3.0));
}
}
for (int i = 10; i < 510; i++)
{
for (int j = 10; j < 510; j++)
{
for (int a = 0; a < 11; a++)
{
for (int b = 0; b < 11; b++)
{
grayValue_eleven[i - 10][j - 10] += (double)(zero_fill_eleven[i - a][j - b]);
}
}
grayValue_eleven[i - 10][j - 10] = round(grayValue_eleven[i - 10][j - 10] / (11.0 * 11.0));
}
}
for (int i = 20; i < 520; i++)
{
for (int j = 20; j < 520; j++)
{
for (int a = 0; a < 21; a++)
{
for (int b = 0; b < 21; b++)
{
grayValue_twentyone[i - 20][j - 20] += (double)(zero_fill_twentyone[i - a][j - b]);
}
}
grayValue_twentyone[i - 20][j - 20] = round(grayValue_twentyone[i - 20][j - 20] / (21.0 * 21.0));
}
}
//写入3*3盒式核进行低通滤波后的新图像
fp = fopen("smooth_3.bmp", "wb");
if (fp == NULL)
{
printf("写入失败\n");
exit(1);
}
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmpColorTable, sizeof(RGBQUAD), 256, fp);
for (int i = 0; i < 500 ; i++)
{
for (int j = 0; j < 500; j++)
{
fwrite(&grayValue_three[i][j], 1, 1, fp);
}
}
fclose(fp);
//写入11*11盒式核进行低通滤波后的新图像
fp = fopen("smooth_11.bmp", "wb");
if (fp == NULL)
{
printf("写入失败\n");
exit(1);
}
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmpColorTable, sizeof(RGBQUAD), 256, fp);
for (int i = 0; i < 500; i++)
{
for (int j = 0; j < 500; j++)
{
fwrite(&grayValue_eleven[i][j], 1, 1, fp);
}
}
fclose(fp);
//写入21*21盒式核进行低通滤波后的新图像
fp = fopen("smooth_21.bmp", "wb");
if (fp == NULL)
{
printf("写入失败\n");
exit(1);
}
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmpColorTable, sizeof(RGBQUAD), 256, fp);
for (int i = 0; i < 500; i++)
{
for (int j = 0; j < 500; j++)
{
fwrite(&grayValue_twentyone[i][j], 1, 1, fp);
}
}
fclose(fp);
}
结果如下:
分别是原图,3*3盒式核滤波,11*11盒式核滤波,21*21盒式核滤波的结果
锐化(高通)滤波器,其实就是核的系数不同而已,原理和平滑挺类似的。
拉普拉斯算子:
void laplace_sharpen(const char* filename)
{
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
RGBQUAD bmpColorTable[256];
BYTE bmpValue[540][468];
FILE* fp;
if ((fp = fopen(filename, "rb")) == NULL)
{
printf("打开失败\n");
exit(1);
}
//读取图像信息
fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fread(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fread(bmpColorTable, sizeof(RGBQUAD), 256, fp);
fread(bmpValue, 1, 540 * 468, fp);
//将图像灰度值存入二维数组中,g(x,y)=f(x,y)-[▽^2 f(x,y)]
int grayValue1[540][468] = { 0 };
for (int i = 0; i < 540; i++)
{
for (int j = 0; j < 468; j++)
{
grayValue1[i][j] = bmpColorTable[bmpValue[i][j]].rgbBlue;
}
}
fclose(fp);
int zero_fill[544][472] = { 0 }; // 零填充
for (int i = 2; i < 542; i++)
{
for (int j = 2; j < 470; j++)
{
zero_fill[i][j] = grayValue1[i - 2][j - 2];
}
}
for (int i = 2; i < 542; i++) //进行卷积
{
for (int j = 2; j < 470; j++)
{
grayValue1[i - 2][j - 2] = zero_fill[i - 1][j] + zero_fill[i - 1][j - 2] + zero_fill[i - 2][j - 1] + zero_fill[i][j - 1] - 4* zero_fill[i - 1][j - 1];
if (grayValue1[i-2][j-2] < 0)
{
grayValue1[i-2][j-2] = 0;
}
}
}
//写入laplace算子进行高通滤波后的新图像
fp = fopen("laplace_sharpen.bmp", "wb");
if (fp == NULL)
{
printf("写入失败\n");
exit(1);
}
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmpColorTable, sizeof(RGBQUAD), 256, fp);
for (int i = 0; i < 540; i++)
{
for (int j = 0; j < 468; j++)
{
fwrite(&grayValue1[i][j], 1, 1, fp);
}
}
fclose(fp);
}
结果如图:
梯度算子:我这里用到的是Sobel算子,很奇怪,用matlab就和书上的图一样,用C语言写,左边和下面会出现白色边边。然后我加了个阈值,效果会好一点。
void sobel_sharpen(const char* filename)
{
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
RGBQUAD bmpColorTable[256];
BYTE bmpValue[932][940];
FILE* fp;
if ((fp = fopen(filename, "rb")) == NULL)
{
printf("打开失败\n");
exit(1);
}
//读取图像信息
fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fread(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fread(bmpColorTable, sizeof(RGBQUAD), 256, fp);
fread(bmpValue, 1, 940 *932, fp);
//将图像灰度值存入二维数组中
int grayValue[932][940] = { 0 };
for (int i = 0; i < 932; i++)
{
for (int j = 0; j < 940; j++)
{
grayValue[i][j] = bmpColorTable[bmpValue[i][j]].rgbBlue;
}
}
fclose(fp);
int sum, avg;
sum = 0;
for (int i = 0; i < 932; i++)
{
for (int j = 0; j < 940; j++)
{
sum += grayValue[i][j];
}
}
avg = sum / (940 * 932);
int zero_fill[936][944] = { 0 }; // 零填充
for (int i = 2; i < 934; i++)
{
for (int j = 2; j < 942; j++)
{
zero_fill[i][j] = grayValue[i - 2][j - 2];
}
}
int grayValue_x[932][940] = { 0 };
int grayValue_y[932][940] = { 0 };
for (int i = 2; i < 934; i++) //进行卷积
{
for (int j = 2; j < 942; j++)
{
grayValue_y[i - 2][j - 2] = zero_fill[i][j] + 2 * zero_fill[i - 1][j] + zero_fill[i - 2][j] - zero_fill[i - 2][j - 2] - zero_fill[i][j - 2] - 2 * zero_fill[i - 1][j - 2];
grayValue_x[i - 2][j - 2] = zero_fill[i][j] + 2 * zero_fill[i][j - 1] + zero_fill[i][j - 2] - zero_fill[i - 2][j - 2] - zero_fill[i - 2][j] - 2 * zero_fill[i - 2][j - 1];
if (grayValue_y[i - 2][j - 2] > avg || grayValue_x[i - 2][j - 2] > avg) //阈值
{
grayValue_y[i - 2][j - 2] = 0;
grayValue_x[i - 2][j - 2] = 0;
}
}
}
for (int i = 0; i < 932; i++)
{
for (int j = 0; j < 940; j++)
{
grayValue[i][j] = sqrt(grayValue_x[i][j] * grayValue_x[i][j]+ grayValue_y[i][j] * grayValue_y[i][j]);
}
}
//写入sobel算子进行高通滤波后的新图像
fp = fopen("sobel_sharpen.bmp", "wb");
if (fp == NULL)
{
printf("写入失败\n");
exit(1);
}
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmpColorTable, sizeof(RGBQUAD), 256, fp);
for (int i = 0; i < 932; i++)
{
for (int j = 0; j < 940; j++)
{
fwrite(&grayValue[i][j], 1, 1, fp);
}
}
fclose(fp);
}
结果如图: