数字图像处理(西安电子科技大学出版社)第三版 的C语言实现
序言:本学期学校开设了数字图像处理课程,老师布置了作业,让我们编程实现教材第三章中的各种图像处理算法。(可以选用OpenCV,VC++,Matlab)
下面我会用C语言实现如下算法:
1. 均值滤波
2. 中值滤波
3. Sobel算子滤波
4. Prewitt算子滤波
5. Krisch算子滤波
6. Roberts算子滤波
7. 灰度线性变换
8. 直方图均衡化
我使用Dev C++进行C语言编程,遵循以下步骤:
1.将需要处理的256灰度图像用Img2LCD 软件转换为十六进制数组(256灰度图)。
2.在C开发环境中对图像数组进行处理,将处理完的数组以符合MATLAB矩阵输入语法的格式输出。
3.将输出的数组粘贴到MATLAB矩阵中显示出来(直方图同上)。
废话不多说,直接贴代码:
main函数
// An highlighted block
//****************Author:cmoswolf****************//
//*************Email:cmoswolf@163.com************//
//************Last edited:2021.04.23*************//
#include <stdio.h>
#include <math.h>
#include <string.h>
void InitMatrix(void); //存档输入矩阵
int SiSheWuRu(float num); //四舍五入函数
void Linearization(float a,float b,float c,float d); //分段线性化
void ImageIntensify(void); //图像增强
void OutputHistogram(void); //输出直方图
void OutputMatrix(int *p); //输出滤波后的矩阵
void AverageFilter(void); //均值滤波函数
void MiddleFilter(void); //中值滤波函数
void RobertsFilter(void); //Roberts梯度滤波函数
void PrewittFilter(void); //Prewitt梯度滤波函数
void SobelFilter(void); //Sobel梯度滤波函数
void KrischFilter(void); //Krisch梯度滤波函数
void IsoSobelFilter(void); //IsoSobel梯度滤波函数
void ClearMatrix(void); //清除矩阵缓存
int main(void)
{
int flag=1;
int OperationNum=0;
float a,b,c,d;
InitMatrix();
while(flag)
{
printf("Enter operation number: \n 1.AverageFilter 2.MiddleFilter 3.RobertsGradFilter\
4.PrewittFilter \n 5.SobelFilter 6.KrischFilter 7.output original Matrix 8.quit\n \
9.Linearization 10.ImageIntensify 11.Output Histogram\n\n");
scanf("%d",&OperationNum);
if(OperationNum==10)
{
printf("Enter 'a','b','c','d'.\n:");
scanf("%f%f%f%f",&a,&b,&c,&d);
}
switch(OperationNum)
{
case 1: OperationNum=0; AverageFilter(); OutputMatrix(image[0]); break;
case 2: OperationNum=0; MiddleFilter(); OutputMatrix(image[0]); break;
case 3: OperationNum=0; RobertsFilter(); OutputMatrix(image[0]); break;
case 4: OperationNum=0; PrewittFilter(); OutputMatrix(image[0]); break;
case 5: OperationNum=0; SobelFilter(); OutputMatrix(image[0]); break;
case 6: OperationNum=0; KrischFilter(); OutputMatrix(image[0]); break;
case 7: OperationNum=0; ClearMatrix(); OutputMatrix(image[0]); break;
case 8: OperationNum=0; flag=0; break;
case 9: OperationNum=0; Linearization(a,b,c,d); OutputMatrix(image[0]); break;
case 11:OperationNum=0; OutputHistogram(); break;
case 10:OperationNum=0; ImageIntensify(); OutputMatrix(image[0]); break;
}
ClearMatrix();
}
return 0;
}
void MiddleFilter(void)
{
int I,J,i,j,Compare[9],temp;
for(i=1;i<N-1;i++)
{
for(j=1;j<M-1;j++)
{
Compare[0]=image[i-1][j-1];
Compare[1]=image[i-1][j];
Compare[2]=image[i-1][j+1];
Compare[3]=image[i][j-1];
Compare[4]=image[i][j];
Compare[5]=image[i][j+1];
Compare[6]=image[i+1][j-1];
Compare[7]=image[i+1][j];
Compare[8]=image[i+1][j+1];
for(I=0;I<8;I++)
{
for(J=0;J<8-I;J++)
{
if(Compare[J]>Compare[J+1])
{
temp=Compare[J];
Compare[J]=Compare[J+1];
Compare[J+1]=temp;
}
}
}
imageT[i][j]=Compare[4];
}
}
for(i=1;i<N-1;i++)
for(j=1;j<M-1;j++)
image[i][j]=imageT[i][j];
}
int SiSheWuRu(float num)
{
int temp=0,result;
temp=num*10;
result=temp/10;
temp=temp%10;
if(temp>=5)
result++;
return result;
}
void OutputMatrix(int *p)
{
long k=0;
for(k=0;k<N*M;k++)
{
if((k+1)%M==0)
printf("%d; \n",*(p+k));
else
printf("%d,",*(p+k));
}
}
void AverageFilter(void)
{
int i,j;
for(i=1;i<N-1;i++)
{
for(j=1;j<M-1;j++)
{
imageT[i][j]=(image[i-1][j-1]+image[i-1][j]+image[i-1][j+1]+
image[i][j-1]+image[i][j]+image[i][j+1]+
image[i+1][j-1]+image[i+1][j]+image[i+1][j+1])/(9.0);
image[i][j]=SiSheWuRu(imageT[i][j]);
}
}
}
void RobertsFilter(void)
{
int i,j;
for(i=0;i<N-1;i++)
{
for(j=0;j<M-1;j++)
{
imageT[i][j]=sqrt(pow(image[i][j]-image[i+1][j],2)+pow(image[i][j]-image[i][j+1],2));
if(imageT[i][j]>255)
imageT[i][j]=255;
imageT[i][j]=SiSheWuRu(imageT[i][j]);
}
}
for(i=0;i<N-1;i++)
for(j=0;j<M-1;j++)
image[i][j]=imageT[i][j];
}
void PrewittFilter(void)
{
int i,j;
int Sx=0,Sy=0;
for(i=1;i<N-1;i++)
{
for(j=1;j<M-1;j++)
{
Sx=image[i+1][j-1]+image[i+1][j]+image[i+1][j+1]-
(image[i-1][j-1]+image[i-1][j]+image[i-1][j+1]);
Sy=image[i-1][j+1]+image[i][j+1]+image[i+1][j+1]-
(image[i-1][j-1]+image[i][j-1]+image[i+1][j-1]);
imageT[i][j]=sqrt(pow(Sx,2)+pow(Sy,2));
if(imageT[i][j]>255)
imageT[i][j]=255;
imageT[i][j]=SiSheWuRu(imageT[i][j]);
}
}
for(i=1;i<N-1;i++)
for(j=1;j<M-1;j++)
image[i][j]=imageT[i][j];
}
void SobelFilter(void)
{
int i,j;
int Sx=0,Sy=0;
for(i=1;i<N-1;i++)
{
for(j=1;j<M-1;j++)
{
Sx=image[i+1][j-1]+2*image[i+1][j]+image[i+1][j+1]-
(image[i-1][j-1]+2*image[i-1][j]+image[i-1][j+1]);
Sy=image[i-1][j+1]+2*image[i][j+1]+image[i+1][j+1]-
(image[i-1][j-1]+2*image[i][j-1]+image[i+1][j-1]);
imageT[i][j]=sqrt(pow(Sx,2)+pow(Sy,2));
if(imageT[i][j]>255)
imageT[i][j]=255;
imageT[i][j]=SiSheWuRu(imageT[i][j]);
}
}
for(i=1;i<N-1;i++)
for(j=1;j<M-1;j++)
image[i][j]=imageT[i][j];
}
void KrischFilter(void)
{
float r[8]={0},temp=0;
int i,j,I,J;
for(i=1;i<N-1;i++)
{
for(j=1;j<M-1;j++)
{
r[0]=0.625*(image[i-1][j-1]+image[i-1][j]+image[i-1][j+1])
-0.375*(image[i][j+1]+image[i+1][j+1]+image[i+1][j]+image[i+1][j-1]+image[i][j-1]);
r[1]=r[0]+image[i][j-1]-image[i-1][j+1];
r[2]=r[1]+image[i+1][j-1]-image[i-1][j];
r[3]=r[2]+image[i+1][j]-image[i-1][j-1];
r[4]=r[3]+image[i+1][j+1]-image[i][j-1];
r[5]=r[4]+image[i][j+1]-image[i+1][j-1];
r[6]=r[5]+image[i-1][j+1]-image[i+1][j];
r[7]=r[6]+image[i-1][j]-image[i+1][j+1];
for(I=0;I<7;I++)
{
for(J=0;J<7-I;J++)
{
if(r[J]>r[J+1])
{
temp=r[J];
r[J]=r[J+1];
r[J+1]=temp;
}
}
}
imageT[i][j]=8*r[7];
if(imageT[i][j]>255)
imageT[i][j]=255;
imageT[i][j]=SiSheWuRu(imageT[i][j]);
}
}
for(i=1;i<N-1;i++)
for(j=1;j<M-1;j++)
image[i][j]=imageT[i][j];
}
void IsoSobelFilter(void)
{
}
void ClearMatrix(void)
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
image[i][j]=imageR[i][j];
}
void InitMatrix(void)
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<M;j++)
imageR[i][j]=image[i][j];
}
void Linearization(float a,float b,float c,float d)
{
int i,j;
for(i=0;i<N;i++)
{
for(j=0;j<M;j++)
{
imageT[i][j]=((image[i][j]-a))*(d-c)/(b-a)+d;
if(imageT[i][j]>255)
imageT[i][j]=255;
imageT[i][j]=SiSheWuRu(imageT[i][j]);
}
}
for(i=1;i<N-1;i++)
for(j=1;j<M-1;j++)
image[i][j]=imageT[i][j];
}
void ImageIntensify(void)
{
}
void OutputHistogram()
{
double Prk[256]={0},Pk[256]={0},
Srk[256]={0},SkB[256]={0};
long nk[256]={0};
int i,j,n=1;
/*统计每级灰度频数*/
for(i=0;i<N;i++)
{
for(j=0;j<M;j++)
{
nk[image[i][j]-1]++;
}
}
/*获取频率Prk*/
for(i=0;i<256;i++)
{
Prk[i]=nk[i]/(M*N*1.0);
}
/*计算Srk*/
for(i=0;i<256;i++)
{
for(j=0;j<=i;j++)
{
Srk[i]+=Prk[j];
}
}
/*计算归一化后的SkB*/
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
{
if((Srk[i]>=(j/255.0))&&(Srk[i]<((j+1)/255.0)))
{
SkB[i]=j/255.0;
}
}
}
/*合并SkB得到最终的Pk*/
for(i=0;i<256;i+=n)//跳过赋过值的Pk[i]
{
n=0;
for(j=0;j<256;j++)
{
if(SkB[j]==(i/255.0))
{
Pk[i]+=Prk[j];
n++;
}
}
if(n==0)//保证循环不中断
{
n=1;
}
}
printf("Sk:\n");
for(i=0;i<256;i++)
{
if(i==255)
{
printf("%lf ",i/255.0);
}
else
printf("%lf ,",i/255.0);
}
printf("\n\n");
printf("Prk:\n");
for(i=0;i<256;i++)
{
if(i==255)
{
printf("%lf ",Prk[i]);
}
else
printf("%lf ,",Prk[i]);
}
printf("\n\n");
printf("Pk:\n");
for(i=0;i<256;i++)
{
if(i==255)
{
printf("%lf ",Pk[i]);
}
else
printf("%lf ,",Pk[i]);
}
}
/*reference:*/
/*数字图像处理第三版/何东健/西安电子科技大学出版社*/
/*https://blog.csdn.net/u010350978/article/details/44874063/?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242*/
bmp.h
#include "bmp.h"
#define N 280//图像大小
#define M 500
float imageT[N][M]={0};
int imageR[N][M]={0};
int image[N][M]={0}//放入需要处理的图像
代码实测无误,下面展示部分滤波效果
- 均值滤波:
上图为原图,下图为均值滤波后的图片
2.直方图均值化:
毕竟在下水平有限,有什么错误欢迎各位大佬指正!