2024年2月21日发(作者:)
数字图像处理课程综合报告
学生姓名:xxx
学 号:2012xxxxxxxx
学 院:理学院
专业年级:2012级电子信息科学与技术
指导老师:桂进斌
目录
实验二:反色与二值化: ............................................................................................................. 33
实验三:灰度变换 ......................................................................................................................... 55
线性变化 ................................................................................................................................. 88
指数变化 ................................................................................................................................. 99
对数变换 ............................................................................................................................. 1111
实验四:图像几何变换 ............................................................................................................. 1212
图像平移 ............................................................................................................................. 1515
图像旋转 ............................................................................................................................. 1717
水平镜像 ............................................................................................................................. 2020
垂直镜像 ............................................................................................................................. 2121
实验五:直方图均衡化 ............................................................................................................. 2222
实验六:图像的平滑与锐化 ..................................................................................................... 2626
均值滤波 ............................................................................................................................. 2828
中值滤波 ............................................................................................................................. 2929
梯度锐化 ............................................................................................................................. 3232
Sobel算子锐化 ................................................................................................................... 3333
实验七:彩色图像处理 ............................................................................................................. 3434
读取R分量 ........................................................................................................................ 3434
读取G分量 ........................................................................................................................ 3636
读取B分量 ........................................................................................................................ 3838
实验八:图像频域高通和低通滤波变换 ................................................................................. 4040
低通滤波 ............................................................................................................................. 4141
高通滤波 ............................................................................................................................. 4444
实验二:反色与二值化:
图像的反色就是依次求出每个像素点的补色,由于用的是256位的图像,所以只需要使用255减去原本像素的色值即可。
图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
在实验前期开发环境框架的搭建中就已经拿到图像在内存中的首地址存于Imgdata指针中,并开辟了一个用于存放处理后数据的内存空间Imgdata_tmp。在以后的图像处理算法中只需要直接对Imgdata指向的数据进行处理,并把处理结果存放在Imgdata_tmp中即可。
实现代码:
void MyBmp::Binaryzation(CDC *pDC){//binaryzation二值化
if(m_DibHead==NULL)
MessageBox(NULL,"获取文件头失败!","错误",MB_OK);
if(m_hPalette!=NULL)
{
HDC hdc=pDC->GetSafeHdc();
::SelectPalette(hdc,m_hPalette,TRUE);
}
pDC->SetStretchBltMode(COLORONCOLOR);
int x = m_DibHead->biWidth;
int y = m_DibHead->biHeight;
TmpBmp = new unsigned char[m_ImageSize];
memset(TmpBmp,255,x*y);
char temp;
int ccc = 0;
for (int i = 0;i for (int j = 0;j { ccc++; temp = *(m_Image+i*x+j); if ((10*temp+10)>=255) { TmpBmp[i*x+j] = (char)255; } else TmpBmp[i*x+j] = 0; } //memcpy(m_Image,TmpBmp,x*y); ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, TmpBmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete[] TmpBmp; TmpBmp = NULL; } 二值化效果: void MyBmp::Inverse(CDC *pDC){//反色 if(m_DibHead==NULL) MessageBox(NULL,"获取文件头失败!","错误",MB_OK); if(m_hPalette!=NULL) { HDC hdc=pDC->GetSafeHdc(); ::SelectPalette(hdc,m_hPalette,TRUE); } pDC->SetStretchBltMode(COLORONCOLOR); int x = m_DibHead->biWidth; int y = m_DibHead->biHeight; TmpBmp = new unsigned char[m_ImageSize]; memset(TmpBmp,255,x*y); char temp; for (int i = 0;i for (int j = 0;j { temp = m_Image[i*x+j]; TmpBmp[i*x+j] = 255 - temp; } //memcpy(m_Image,TmpBmp,x*y); ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, TmpBmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete[] TmpBmp; TmpBmp = NULL; } 反色效果: 实验三:灰度变换 灰度线性变换是灰度变换的一种,图像的灰度变换通过建立灰度映射来调整源图像的灰度从而达到图像增强的目的。 灰度映射通常是用灰度变换曲线来表示的,如图 7所示。 灰度线性变换就是将图像的像素值通过指定的线性函 数进行变换,以此增强或者减弱图像的灰度。灰度线性变换的公式就是常见的一维线性函数: g(x, y)=kf(x, y)+d 设x为原始灰度值,则变换后的灰度 值y为: 也可以在坐标系中表示转化关系,如图 7所示。 图 7 灰度线性变换 图 7坐标中的横轴表示输入灰度值,范围是0至 255;纵坐标表示输出灰度值,范围同样是0至255;直线则为线性变换函数的图形。如果将输入灰度值作为自变量x,则输出的灰度值就是函数y=T(x) 的运算结果。对于线性变换而言,有T(x)=kx+d。例如图 7中的变换函数为T(x)=x, 即原公式中的k=1,d=0。 由数学知识可以知道k表示直线的斜 率,也就是倾斜程度;d为线性函数在y轴的斜率。下面通过讨论k的取值来分析灰度线性变换的效果。 1)当k>1时 此时可用 于增加图像的对比度。图像的像素值在变换后全部增大,整体显示效果被增强,如图 8所示。 图 8 变换后的图像、对应变换函数和直方图 可以看 到,图像经过变换后,其灰度分布被拉伸了。读者可以与图 1中的直方图进行比较。 2)当k=1时 这种情况 常用于调节图像亮度。亮度的调节就是让图像的各像素值都增加或者减少一定量。这种情况下可以通过改变d的值达到增 加或者减少图像亮度的目的,如图 9所示。 图 9 利用线性变换改变图像亮度 可以看 到,当d>0时图像亮度增加,反之则减少。对应直方图的显示效果是灰度分布整体向右或者向左平移。 3)当0 效果与k>1 时刚刚相反,图像的对比度和整体效果都被削弱。从图 10中的直方图可以看到,灰度分布被集中在一段区域上。k越小,图像的灰度分布越 窄,图像看起来也就越偏灰色。 图 10 利用线性变换改变图像对比度 4)当k<0时 在这种情 况下,源图像较亮的区域变暗,而较暗的区域会变亮。此时可以使函数中的k=-1,d=255让图像实现反色效果,如图 11所示。 图11 利用线性变换让图像反色 代码实现 线性变化 MyBmp::LinearTrans(CDC *pDC,int a,int b){//LinearTrans线性变化 if(m_DibHead==NULL) MessageBox(NULL,"获取文件头失败!","错误",MB_OK); if(m_hPalette!=NULL) { HDC hdc=pDC->GetSafeHdc(); ::SelectPalette(hdc,m_hPalette,TRUE); } pDC->SetStretchBltMode(COLORONCOLOR); int x = m_DibHead->biWidth; int y = m_DibHead->biHeight; TmpBmp = new unsigned char[m_ImageSize]; memset(TmpBmp,255,x*y); for (int i = 0;i for (int j = 0;j { if ((a*m_Image[i*x+j]+b)>=255) { TmpBmp[i*x+j] = 255; } else TmpBmp[i*x+j] = a*m_Image[i*x+j]+b; } //memcpy(m_Image,TmpBmp,x*y); ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, TmpBmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete[] TmpBmp; TmpBmp = NULL; } 线性变换效果: 指数变化 void MyBmp::Pow(CDC *pDC,int a) { if(m_DibHead==NULL) MessageBox(NULL,"获取文件头失败!","错误",MB_OK); if(m_hPalette!=NULL) { HDC hdc=pDC->GetSafeHdc(); ::SelectPalette(hdc,m_hPalette,TRUE); } pDC->SetStretchBltMode(COLORONCOLOR); int x = m_DibHead->biWidth; int y = m_DibHead->biHeight; TmpBmp = new unsigned char[m_ImageSize]; memset(TmpBmp,255,x*y); for (int i = 0;i for (int j = 0;j { double e = a; int m = m_Image[i*x+j]; if ( (pow( e,m ))>=255 ) { TmpBmp[i*x+j] = 255; } else TmpBmp[i*x+j] = 100*pow( 1.0,m); } //memcpy(m_Image,TmpBmp,x*y); ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, TmpBmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete[] TmpBmp; TmpBmp = NULL; } 指数变换效果: 对数变换 void MyBmp::Log10(CDC *pDC) { if(m_DibHead==NULL) MessageBox(NULL,"获取文件头失败!","错误",MB_OK); if(m_hPalette!=NULL) { HDC hdc=pDC->GetSafeHdc(); ::SelectPalette(hdc,m_hPalette,TRUE); } pDC->SetStretchBltMode(COLORONCOLOR); int x = m_DibHead->biWidth; int y = m_DibHead->biHeight; TmpBmp = new unsigned char[m_ImageSize]; memset(TmpBmp,255,x*y); for (int i = 0;i for (int j = 0;j { float m = m_Image[i*x+j]*1.0; TmpBmp[i*x+j] = 50*log( static_cast } //memcpy(m_Image,TmpBmp,x*y); ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, TmpBmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete[] TmpBmp; TmpBmp = NULL; } 对数变换效果: 实验四:图像几何变换 图像几何变换的一般表达式: [u,v]为变换后图像像素的笛卡尔坐标,[x,y]为原始图像中像素的笛卡尔坐标。这样就得到了原始图像与变换后图像的像素的对应关系。 如果 ,则有,即变换后图像仅是原图像简单拷贝。 平移原理:在图像平移是将一幅图像中所有的点都按照指定的平移量在水平、垂直方向移动,平移后的图像与原图像相同。 Tx =2 , Ty =1 平移的直角坐标公式:图像的平移非常简单,所用到的是中学学过的直角坐标系的平移变换公式: xx0xyy0y 平移的齐次坐标公式:变换前后图像上的点P0(x0, y0)和P(x1, y1) 之间的关系可以用如下的矩阵变换表示为: 图像的平移示意图 图像的镜像 镜像分为水平镜像和垂直镜像。 镜像原理: 水平镜像:以图像的垂直中轴线为中心交换图像的左右两部分。 垂直镜像:以图像的水平中轴线为中心交换图像的上下两部分。 水平镜像 设图像高度为Height,宽度为Width,原图中的(x0,y0)经过水平镜像后,坐标将变成(Width-x0,y0)。 数学表达式矩阵表达式 x1=Width-x0 10widthxx10 y010y0111001 y1=y0 垂直镜像 点(x0,y0)经过垂直镜像后,坐标将变成为(x0,Height-y0) 数学表达式 矩阵表达式 x1=x0 1xx100 0 y101heighty01y1=Height-y0 1001 图像的旋转理论基础 图像的旋转是指以图像中的某一点为原点以逆时针或顺时针的方向旋转一定的角度。 图像的旋转变换也可以用矩阵变换表示。设点P0(x0, y0) 旋转α角后的对应点为P(x, y)。 直角坐标系的图像旋转 旋转公式: 将输入图像绕笛卡尔坐标系的原点逆时针旋转 角度,则变换后图像的坐标为: x'xcosysiny'xsinycos 这个计算公式计算出的值为小数,而坐标值为正整数。 这个计算公式计算的结果值所在范围与原来的值所在的范围不同。 因此需要前期处理:扩大画布,取整处理(解决小数问题),平移处理(解决负数问题) 注意是逆时针转角 上式写成齐次坐标为: 其中,θ角度由正负之分,即点P在XY平面的内绕原点逆时针旋转所形成的角度为正,反之为负。 代码实现: 图像平移 void MyBmp::Smooth(CDC *pDC,int len) { if(m_DibHead==NULL) MessageBox(NULL,"获取文件头失败!","错误",MB_OK); if(m_hPalette!=NULL) { HDC hdc=pDC->GetSafeHdc(); ::SelectPalette(hdc,m_hPalette,TRUE); } pDC->SetStretchBltMode(COLORONCOLOR); int x = m_DibHead->biWidth; int y = m_DibHead->biHeight; ////---------------------- struct M_panning_length{ int delta_x; int delta_y; }; M_panning_length m_panning_length = {0,0}; if (len>5) { m_panning__x = (len-5)*30; m_panning__y = (len-5)*30; } long widthPix,heightPix; widthPix=m_DibHead->biWidth; heightPix=m_DibHead->biHeight; // float tmp; LPBYTE m_Image_temp=(LPBYTE) new char[m_ImageSize]; memset(m_Image_temp,255,m_ImageSize); //memcpy(m_Image,m_Image_backup,m_ImageSize); int count=0; cossin0xysincos01010x0y01 int old_y; int old_x; int old_position; int new_position; int ff = 0; if(len>5) ff = 2; if(len<=5) ff = 1; switch (ff) { case 1:{ for(int i=0;i for(int j=0;j { old_y=i; old_x=j; old_position=i*widthPix+j; int nxx; nxx=old_x-m_panning__x; if(nxx<0) continue; count++; new_position=i*widthPix+nxx; m_Image_temp[new_position]=m_Image[old_position]; } } break; case 2:{ for(int i=0;i for(int j=0;j { old_y=i; old_x=j; old_position=i*widthPix-1+j; int nxx; nxx=old_x+m_panning__x; if(nxx>widthPix-1) continue; count++; new_position=i*widthPix-1+nxx; m_Image_temp[new_position]=m_Image[old_position]; } } break; } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, m_Image_temp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); } 平移效果: 图像旋转 void MyBmp::Rotate(CDC *pDC,int angle) { if(m_DibHead==NULL) MessageBox(NULL,"获取文件头失败!","错误",MB_OK); if(m_hPalette!=NULL) { HDC hdc=pDC->GetSafeHdc(); ::SelectPalette(hdc,m_hPalette,TRUE); } pDC->SetStretchBltMode(COLORONCOLOR); int x = m_DibHead->biWidth; int y = m_DibHead->biHeight; //-------------------------- long widthPix,heightPix; widthPix=m_DibHead->biWidth; heightPix=m_DibHead->biHeight; // float tmp; LPBYTE m_Image_temp=(LPBYTE) new char[m_ImageSize]; memset(m_Image_temp,255,m_ImageSize); int count=0; int old_y; int old_x; int old_position; int new_position; float nxx; float new_x; float new_y; //nxx=(M_PI)*10/180; nxx=(M_PI)*angle/180; for(int i=0;i 为24位真彩色 512x3x512 for(int j=0;j { old_y=i; old_x=j; old_position=i*widthPix+j; //lene图 //old_position=3*i*widthPix+j*3;//真彩色 new_x=(old_x-widthPix/2)*cos(nxx)-(old_y-heightPix/2)*sin(nxx)+widthPix/2; new_y=(old_y-heightPix/2)*cos(nxx)+(old_x-widthPix/2)*sin(nxx)+heightPix/2; if(new_x<0||new_y<0||new_x>widthPix-1||new_y>heightPix-1) continue; new_position=((int)new_y)*widthPix+((int)new_x); m_Image_temp[old_position]=m_Image[new_position]; m_Image_temp[old_position+1]=m_Image[new_position+1]; m_Image_temp[old_position+2]=m_Image[new_position+2]; } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, m_Image_temp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); } 旋转效果: 水平镜像 void MyBmp::MirHor(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); for(i=0;i for(j=0;j { Imgdata_tmp[i*w+w-j-1]=Imgdata[i*w+j]; } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 水平镜像效果: 垂直镜像 void MyBmp::BmpMirVer(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); for(i=0;i for(j=0;j { Imgdata_tmp[(h-1-i)*w+j]=Imgdata[i*w+j]; } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 垂直镜像效果: 实验五:直方图均衡化 大多数原始的遥感图像由于其灰度分布集中在较窄的范围内,使图像的细节不够清晰,对比度较低。为了使图像的灰度范围拉开或使灰度均匀分布,从而增大反差,使图像细节清晰,以达到增强的目的,通常采用直方图均衡化及直方图规定化两种变换。 直方图均衡化(Histogram Equalization)又称直方图平坦化,实质上是对图像进行非线性拉伸,重新分配图像象元值,使一定灰度范围内象元值的数量大致相等。这样,原来直方图中间的峰顶部分对比度得到增强,而两侧的谷底部分对比度降低,输出图像的直方图是一个较平的分段直方图:如果输出数据分段值较小的话,会产生粗略分类的视觉效果。 假设灰度级为归一化至范围[0,1]内的连续量,并令Pr (r)表示某给定图像中的灰度级的概率密度函数(PDF),其下标用来区分输入图像和输出图像的PDF。假设我们对输入灰度级执行如下变换,得到(处理后的)输出灰度级s: S=T(r)=∫0 r Pr(w)dw 式中w 是积分的哑变量。可以看出,输出灰度级的概率密度函数是均匀的,即 a.当0≤s≤1 时,Ps(s)=1 b.当s 为其他时,Ps(s)=0 换言之,前述变换生成一幅图像,该图像的灰度级较为均衡化,且覆盖了整个范围[0,1]。灰度级均衡化处理的最终结果是一幅扩展了动态范围的图像,它具有较高的对比度。该变换函数只不过是一个累积分布函数(CDF)。 直方图均衡化算法 直方图均衡化算法将原图像的直方图改变为在整个灰度范围内基本均匀地分布的形式,由此扩大了像素灰度的动态范围,从而增强了图像的对比度。直方图均衡化算法步骤为: 1) 给出原始图像的所有灰度级Sk(k=0,1,…,L-1)。 2) 统计原始图像各灰度级的像素数nk。 3) 根据原图像,计算灰度直方图: P(Sk)nkn (k=0,1,…,L-1) 式中,n为总像素数,nk为灰度级Sk的像素数。 4) 计算原始图像的累积直方图: knitEEH(Sk)Ps(Si)i0ni0 (0Sk1,k=0,1,…,L-1) k5) 取整计算: Ukint[(N1)tkk]N 6) 确定映射关系: SkUk 7) 统计新直方图各灰度级Uk的像素数目nk。 8) 计算新的直方图: P(tk)nkn 实现代码: void MyBmp::zftjh(/*unsigned char *lpDib,long lWidth,long lWidth*/CDC *pDC) { long lWidth=m_DibHead->biWidth; long lHeight=m_DibHead->biHeight; LPBYTE m_Image_temp=(LPBYTE) new char[m_ImageSize]; memset(m_Image_temp,255,m_ImageSize); unsigned char *lpDib = m_Image; unsigned char *lpsrc; long lresult(0); long i,j; unsigned char bMap[256]; long lCount[256]; for(i=0;i<256;i++) lCount[i]=0; for(i=0;i for(j=0;j { lpsrc=lpDib+i*lWidth+j; lCount[*lpsrc]++; } for(i=0;i<256;i++) { lresult=0; for(j=0;j<=i;j++) lresult+=lCount[j]; bMap[i]=(lresult*255)/lHeight/lWidth; } for(i=0;i for(j=0;j { lpsrc=lpDib+i*lWidth+j; //*lpsrc=bMap[*lpsrc]; *(m_Image_temp + i*lWidth+j) = bMap[*lpsrc]; } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, m_Image_temp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); long w,h; long count[256]; long count1[256]; memset(count,0,sizeof(count)); memset(count1,0,sizeof(count1)); long mymax(0); long mymax1(0); long x,y; w=m_DibHead->biWidth; h=m_DibHead->biHeight; for(y=0;y for(x=0;x { count[*(m_Image+y*w+x)]++; } for(int i=0;i<256;i++) if(mymax mymax=count[i]; } for(y=0;y for(x=0;x { count1[*(m_Image_temp+y*w+x)]++; } for(int i=0;i<256;i++) if(mymax1 mymax1=count1[i]; zflags = 1; SHOW zft; zft.m_Max=mymax; zft.m_Max2=mymax1; zft.m_SetData(count,256); zft.m_SetData_2(count1,256); l(); 直方图均衡化效果: 实验六:图像的平滑与锐化 邻域平均法的思想是用像素及其指定邻域内像素的平均值或加权平均值作为该像素的新值,以便去除突变的像素点,从而滤除一定的噪声。邻域平均法的数学含义可用下式表示: mnwizi1g(x,y)imnwii1 (1) 上式中:zi是以(x,y)为中心的邻域像素值;wi是对每个邻域像素的加权系数或模板系数;mn是加权系数的个数或称为模板大小。邻域平均法中常用的模板是: 1111TBox1119111 (2) 为了解决邻域平均法造成的图像模糊问题,采用阈值法(又叫做超限邻域平均法,如果某个像素的灰度值大于其邻域像素的平均值,且达到一定水平,则判断该像素为噪声,继而用邻域像素的均值取代这一像素值;否则,认为该像素不是噪声点,不予取代),给定阈值T0: f(x,y)h(x,y)g(x,y)f(x,y)g(x,y)T0f(x,y)g(x,y)T0 (3) (3)式中,f(x,y)是原始含噪声图像,g(x,y)是由(1)式计算的平均值,h(x,y)滤波后的像素值。 中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是去某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维中值滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W为二维模板,通常为2*2,3*3区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。 通过变量轮换法、共轭方向法等的讨论,我们知道对多维无约束问题优化总是将其转化为在一系列选定方向进行一维搜索,使目标函数值步步降低直至逼近目标函数极小点,而方向的选择与迭代速度、计算效率关系很大。人们利用函数在其负梯度方向函数值下降最快这一局部性质,将n维无约束极小化问题转化为一系列沿目标函数负梯度方向一维搜索寻优,这就成为梯度法的基本构 想。据此我们将无约束优化迭代的通式中的搜索方向取为负梯度向量或单位负梯度向量,即可分别得到两种表达形式的梯度法迭代公式 (1) (2) 式中,两式中,分别为函数在迭代点处的梯度和梯度的模;均为最优步长因子,各自分别通过一维极小化和。 按照梯度法迭代公式(1)或(2)进行若干次一维搜索,每次迭代的初始点取上次迭代的终点,即可使迭代点逐步逼近目标函数的极小点。其迭代的终止条件可采用点距准则或梯度准则,即当或时终止迭代。 该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像,其公式如下: Sobel算子 图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。 然后可用以下公式计算梯度方向。 在以上例子中,如果以上的角度Θ等于零,即代表图像该处拥有纵向边缘,左方较右方暗。 代码实现: 均值滤波 void MyBmp::LinYu(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j; w=m_DibHead->biWidth; h=m_DibHead->biHeight; for(i=1;i { for(j=1;j { int temp=*(Imgdata+i*w-w+j-1)+*(Imgdata+i*w-w+j)+*(Imgdata+i*w-w+j+1)+ *(Imgdata+i*w+j-1)+*(Imgdata+i*w+j)+*(Imgdata+i*w+j+1)+ *(Imgdata+i*w+w+j-1)+*(Imgdata+i*w+w+j)+*(Imgdata+i*w+w+j+1); temp/=9; *(Imgdata_tmp+i*w+j)=(unsigned char)(temp); } } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 均值滤波效果: 中值滤波 void MyBmp::MidFilter(CDC *pDC)//中值滤波 { //统计中间值 double mid = 0.0; int tem_w = 3; int tem_h = 3; LPBYTE m_Image_temp=(LPBYTE) new char[m_ImageSize]; memset(m_Image_temp,255,m_ImageSize); BYTE *temp=(BYTE*)malloc(tem_w*tem_h*sizeof(BYTE)); //将指向图像象素起始位置的指针,赋值给指针变量 BYTE* oldbuf = m_Image; //循环变量 int i,j,m,n; int w, h, dw; //获取图像的宽度 w = m_DibHead->biWidth; //获取图像的高度 h = m_DibHead->biHeight; //计算图像每行的字节数 dw = (w+3)/4*4; //将指向新图像象素起始位置的指针,赋值给指针变量 BYTE *newbuf=m_Image_temp; //对图像进行扫描 //行 for(i=0;i { //列 for(j=0;j { //为统计变量赋初始值 //对于图像的4个边框的象素保持原灰度不变 if( j<((tem_w-1)/2) || j>(w-(tem_w+1)/2) || i<((tem_h-1)/2) || i>(h-(tem_h+1)/2) ) *(newbuf+i*dw+j)=*(oldbuf+i*dw+j); //对于其他的象素进行模板操作 else { //将点(i,j)点作为模板的中心 for(m=i-((tem_h-1)/2);m<=i+((tem_h-1)/2);m++) { for(n=j-((tem_w-1)/2);n<=j+((tem_w-1)/2);n++) //将以点(i,j)为中心,与模板大小相同的范围内的象素传递到模板矩阵中 temp[(m-i+((tem_h-1)/2))*tem_w+n-j+((tem_w-1)/2)]=*(oldbuf+m*dw+n); } //利用气泡法计算中值 for(m=0;m { } for(n=0;n { if(temp[n]>temp[n+1]) mid=temp[n]; temp[n]=temp[n+1]; temp[n+1]=mid; } //将计算的结果放到新的位图的相应位置 *(newbuf+i*dw+j)=temp[(tem_w*tem_h-1)/2]; } } } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, newbuf,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); } 中值滤波效果: 梯度锐化 void MyBmp::BmpGradient(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); for(i=0;i for(j=0;j { *(Imgdata_tmp+i*w+j)=3*(abs(*(Imgdata+i*w+j)-*(Imgdata+i*w+w+j+1))+ abs(*(Imgdata+i*w+w+j)-*(Imgdata+i*w+j+1))); } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 梯度锐化效果: Sobel算子锐化 void MyBmp::BmpSobel(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); int sx,sy; for(i=1;i for(j=1;j { sx=abs(*(Imgdata+i*w+w+j-1)-*(Imgdata+i*w-w+j-1)+ 2*(*(Imgdata+i*w+w+j)-*(Imgdata+i*w-w+j))+ *(Imgdata+i*w+w+j+1)-*(Imgdata+i*w-w+j+1)); sy=abs(*(Imgdata+i*w-w+j+1)-*(Imgdata+i*w-w+j-1)+ 2*(*(Imgdata+i*w+j+1)-*(Imgdata+i*w+j-1))+ *(Imgdata+i*w+w+j+1)-*(Imgdata+i*w+w+j-1)); *(Imgdata_tmp+i*w+j)=(sx+sy); } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } Sobel算子锐化效果: 实验七:彩色图像处理 通过前期环境搭建,我们可以拿到指向彩色图像图像数据的指针Imgdata。 代码实现: 读取R分量 void MyBmp::BmpGetR(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j,k; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); int Sign; if((3*w)%4==0) Sign=0; else Sign=4-((3*w)%4); double *R=new double [(w+Sign)*h]; double *G=new double [(w+Sign)*h]; double *B=new double [(w+Sign)*h]; for(j=0;j for(i=0;i { k=(h-1-j)*(w+Sign)+i; { B[k]=*(Imgdata+(w*3+Sign)*j+3*i)*1.0/255; G[k]=*(Imgdata+(w*3+Sign)*j+3*i+1)*1.0/255; R[k]=*(Imgdata+(w*3+Sign)*j+3*i+2)*1.0/255; } } memset(B,0,(w+Sign)*h*sizeof(double)); memset(G,0,(w+Sign)*h*sizeof(double)); for(j=0;j for(i=0;i<(w+Sign);i++) { k=(h-1-j)*(w+Sign)+i; { *(Imgdata_tmp+(w*3+Sign)*j+3*i)=(unsigned char)(B[k]*255); *(Imgdata_tmp+(w*3+Sign)*j+3*i+1)=(unsigned char)(G[k]*255); *(Imgdata_tmp+(w*3+Sign)*j+3*i+2)=(unsigned char)(R[k]*255); } } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 读取R分量效果: 读取G分量 void MyBmp::BmpGetG(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j,k; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); int Sign; if((3*w)%4==0) Sign=0; else Sign=4-((3*w)%4); double *R=new double [(w+Sign)*h]; double *G=new double [(w+Sign)*h]; double *B=new double [(w+Sign)*h]; for(j=0;j for(i=0;i { k=(h-1-j)*(w+Sign)+i; { B[k]=*(Imgdata+(w*3+Sign)*j+3*i)*1.0/255; G[k]=*(Imgdata+(w*3+Sign)*j+3*i+1)*1.0/255; R[k]=*(Imgdata+(w*3+Sign)*j+3*i+2)*1.0/255; } } memset(B,0,(w+Sign)*h*sizeof(double)); memset(R,0,(w+Sign)*h*sizeof(double)); for(j=0;j for(i=0;i<(w+Sign);i++) { k=(h-1-j)*(w+Sign)+i; { *(Imgdata_tmp+(w*3+Sign)*j+3*i)=(unsigned char)(B[k]*255); *(Imgdata_tmp+(w*3+Sign)*j+3*i+1)=(unsigned char)(G[k]*255); *(Imgdata_tmp+(w*3+Sign)*j+3*i+2)=(unsigned char)(R[k]*255); } } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 读取G分量效果: 读取B分量 void MyBmp::BmpGetB(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j,k; w=m_DibHead->biWidth; h=m_DibHead->biHeight; int Sign; if((3*w)%4==0) Sign=0; else Sign=4-((3*w)%4); double *R=new double [(w+Sign)*h]; double *G=new double [(w+Sign)*h]; double *B=new double [(w+Sign)*h]; for(j=0;j for(i=0;i { k=(h-1-j)*(w+Sign)+i; { B[k]=*(Imgdata+(w*3+Sign)*j+3*i)*1.0/255; G[k]=*(Imgdata+(w*3+Sign)*j+3*i+1)*1.0/255; R[k]=*(Imgdata+(w*3+Sign)*j+3*i+2)*1.0/255; } } memset(R,0,(w+Sign)*h*sizeof(double)); memset(G,0,(w+Sign)*h*sizeof(double)); for(j=0;j for(i=0;i<(w+Sign);i++) { k=(h-1-j)*(w+Sign)+i; { *(Imgdata_tmp+(w*3+Sign)*j+3*i)=(unsigned char)(B[k]*255); *(Imgdata_tmp+(w*3+Sign)*j+3*i+1)=(unsigned char)(G[k]*255); *(Imgdata_tmp+(w*3+Sign)*j+3*i+2)=(unsigned char)(R[k]*255); } } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 读取G分量效果: 实验八:图像频域高通和低通滤波变换 二维理想低通滤波器的传递函数为: D0是指定非负数值,D(u,v)是(u,v)点距频率中心的距离。如果要研究的图像尺寸为M X N,则它的变换也有相同的尺寸。在半径为D0的圆内,所有频率无衰减地通过滤波器,而在此半径之外的所有频率完全被衰减掉。 巴特沃斯高通滤波器的传递函数为: H(u,v)1D(u,v)2n1[]D01.D(u,v)D0H(u,v)0.D(u,v)D0 式中D0为截止频率距远点距离。一阶巴特沃斯滤波器没有振铃。在二阶中振铃通常很微小,但在阶数增高时振铃便成为一个重要因素。 高斯高通滤波器传递函数为: H(u,v)eD22(u,v)/2D0 D(u,v)是距傅立叶变换中心原点的距离。D0是截止频率。高斯低通滤波二维理想高通滤波器的传递函数为: 0.D(u,v)D0H(u,v)1.D(u,v)D0 器的傅立叶变换也是高斯的。 D0是从频率矩形中点测得的截止频率长度,它将以D0为半径的圆周内的所有频率置零,而毫不衰减地通过圆周外的任何频率。但其物理上是不可实现的。 巴特沃斯高通滤波器的传递函数为: H(u,v)1D02n1[]D(u,v) 式中D0为截止频率距远点距离。与低通滤波器的情况一样,可认为巴特沃斯高通型滤波器比IHPF更平滑。 高斯高通滤波器传递函数为: H(u,v)1eD22(u,v)/2D0 高通滤波器能够用高斯型低通滤波器的差构成。这些不同的滤波器有更多的参数,因此能够对滤波器的形状进行更多的控制。 代码实现: 低通滤波 void MyBmp::LowPass(CDC *pDC,int u,int v) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); complex complex int *lpsrc=new int [w*h]; for(i=0;i for(j=0;j { lpsrc[i*w+j]=*(Imgdata+i*w+j); } CImProc bh; (FD,lpsrc,w,h); (FD,w,h); int d0=20; for(i=0;i for(j=0;j { //if((i-h/2)*(i-h/2)+(j-w/2)*(j-w/2)>d0*d0)//理想低通 // FD[i*w+j]=0;//理想低通 if((i!=h/2)&&(j!=w/2)) FD[i*w+j]*=1.0/(1+(sqrt((double)((i-h/2)*(i-h/2)+(j-w/2)*(j-w/2)))) *(d0/sqrt((double)((i-h/2)*(i-h/2)+(j-w/2)*(j-w/2)))/d0)); } (FD,w,h); (TD,FD,w,h); for(i=0;i for(j=0;j { *(Imgdata_tmp+i*w+j)=unsigned char(abs(TD[i*w+j].real())); } u = v =100; BYTE* lpSrc; // 指向原图像当前点的指针 double max=0.0; //归一化因子 double *t; //空域数据指针 double *H; //传递函数指针 BYTE* lpDIBBits=Imgdata;//找到原图像的起始位置 LONG lWidth=m_DibHead->biWidth; //获得原图像的宽度 LONG lHeight=m_DibHead->biHeight; //获得原图像的高度 long lLineBytes=WIDTHBYTES(lWidth*8);//计算图象每行的字节数 t=new double [lHeight*lLineBytes*2+1]; //分配空域空间 H=new double [lHeight*lLineBytes*2+1]; //分配传递函数空间 d0=sqrt((float)(u*u+v*v)) ; //计算截止频率d0 //给空域赋值,并计算传递函数 for(j=0;j { for(i=0;i { lpSrc=lpDIBBits+lLineBytes*j+i;//指向第i行第j列象素 //给空域赋值 t[(2*lLineBytes)*j+2*i+1]=*lpSrc; t[(2*lLineBytes)*j+2*i+2]=0.0; //计算传递函数 if((sqrt((float)(i*i+j*j)))<=d0) H[2*i+(2*lLineBytes)*j+1]=1.0; else H[2*i+(2*lLineBytes)*j+1]=0.0; H[2*i+(2*lLineBytes)*j+2]=0.0; } } //进行傅立叶变换 fourier(t,lHeight,lLineBytes,1); //傅立叶变换结果与传递函数进行卷积运算 for(j=1;j { t[j]=t[j]*H[j]-t[j+1]*H[j+1]; t[j+1]=t[j]*H[j+1]+t[j+1]*H[j]; } //进行傅立叶逆变换 fourier(t,lHeight,lLineBytes,-1); //计算归一化因子 for(j=0;j { for(i=0;i { t[(2*lLineBytes)*j+2*i+1]=sqrt(t[(2*lLineBytes)*j+2*i+1]*t[(2*lLineBytes)*j+2*i+1]+t[(2*lLineBytes)*j+2*i+2]*t[(2*lLineBytes)*j+2*i+2]); if(max max=t[(2*lLineBytes)*j+2*i+1]; } } //计算结果图像,并保存到原图像数据区 for(j=0;j { for(i=0;i { lpSrc=lpDIBBits+lLineBytes*j+i; *Imgdata_tmp=(BYTE)(t[(2*lLineBytes)*j+2*i+1]*255.0/max); } } //释放内存空间 delete t; delete H; ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 低通滤波效果: 高通滤波 void MyBmp::BmpHighPass(CDC *pDC) { LPBYTE Imgdata_tmp = (LPBYTE) new char[m_ImageSize]; LPBYTE Imgdata = m_Image; long w,h; long i,j; w=m_DibHead->biWidth; h=m_DibHead->biHeight; //::MessageBox(NULL,"heooo","hshh",MB_OK); complex complex int *lpsrc=new int [w*h]; for(i=0;i for(j=0;j { lpsrc[i*w+j]=*(Imgdata+i*w+j); } CImProc bh; (FD,lpsrc,w,h); (FD,w,h); int d0=50; for(i=0;i for(j=0;j { if((i!=h/2)&&(j!=w/2))//巴特沃斯高通 FD[i*w+j]*=1.0/(1+(d0*1.0/sqrt((float)((i-h/2)*(i-h/2)+(j-w/2)*(j-w/2)))) *(d0/sqrt((float)((i-h/2)*(i-h/2)+(j-w/2)*(j-w/2))))); //if((i-h/2)*(i-h/2)+(j-w/2)*(j-w/2)<=d0*d0) //FD[i*w+j]=0; } (FD,w,h); (TD,FD,w,h); for(i=0;i for(j=0;j { *(Imgdata_tmp+i*w+j)=unsigned char(abs(TD[i*w+j].real())*6); } ::StretchDIBits(pDC->GetSafeHdc(),500,0,((400<=(m_DibHead->biWidth))?400:(m_DibHead->biWidth)) ,((400<=(m_DibHead->biHeight))?400:(m_DibHead->biHeight)),0,0,m_DibHead->biWidth,m_DibHead->biHeight, Imgdata_tmp,(LPBITMAPINFO)m_DibHead,DIB_RGB_COLORS,SRCCOPY); delete Imgdata_tmp; } 高通滤波效果:


发布评论