数字图像处理课程设计报告

数字图像处理设计报告

【设计目的】

配合《数字图像处理》课程的教学,使学生能巩固和加深对数字图像处理基础理论和基本知识的理解;掌握使用图像处理软件处理图像基本思想和方法;提高学生对图像处理方面的实际问题的应对能力并将所学知识在实践中巩固。

【设计要求】

1. 按照题目的要求,简要介绍算法,并对算法进行分析;

2. 用MATLAB完成算法代码(不能利用MATLAB自身的图像处理函数完成具体算法,读写和显示可以利用MATLAB函数),注释要清晰;

3. 给出代码运行的结果,并对结论进行总结;

4. 每人可选一个给出的题目或自己感兴趣的题目,按照上面要求上交报告,内容不得少于5页A4纸。

【所选题目】

用直方图均衡化一幅8位的灰度图像

【设计环境】

MATLAB7.1,所选图片为彩色动画图片,大小为1024*666*24b

【算法介绍和分析】

1、算法概述:直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。

2、算法分析:

直方图均衡化的基本思想是把原始图的直方图变换为均匀分布的形式,这样就增加了象素灰度值的动态范围从而可达到增强图像整体对比度的效果。设原始图像在(x,y)处的灰度为f,而改变后的图像为g,则对图像增强的方法可表述为将在(x,y)处的灰度f映射为g。在灰度直方图均衡化处理中对图像的映射函数可定义为:g = EQ (f),这个映射函数EQ(f)必须满足两个条件(其中L为图像的灰度级数):

(1)EQ(f)在0≤f≤L-1范围内是一个单值单增函数。这是为了保证增强处理没有打乱原始图像的灰度排列次序,原图各灰度级在变换后仍保持从黑到白(或从白到黑)的排列。

(2)对于0≤f≤L-1有0≤g≤L-1,这个条件保证了变换前后灰度值动态范围的一致性。

累计分布函数(cumulative distribution function,CDF)即可以满足上述两个条件,并且通过该函数可以完成将原图像f的分布转换成g的均匀分布。此时的直方图均衡化映射函数为:

gk = EQ(fk) = (ni/n) = pf(fi) ,(k=0,1,2,……,L-1)

3、灰度直方图变换的步骤:

第一,统计每种灰度值出现的次数,记为Nk;

第二,计算概率Sk,Sk=Nk/N;

第三,求其密度分布函数Sk’=P(R0)+ P(R1)+ P(R2)……+ P(Rk),p 实际上是图像的直方图,归一化到 0——1;

第四,利用迭代方案对每一个sk值预计算值;

第五,对于原始图像的每个像素,若像素值为rk,将该值映射到其对应的灰度级sk,然后映射到最终灰度级zk。

在均衡化过程中可以对每一象素映射到新的实际灰度值sk*255,就实现了图像的变换(严格理论中应该是灰度正规化到[0,1]区间,然后均衡化后的sk还要量化到原始的正规灰度以实现灰度合并)

【实现代码】

sourcePic=imread('two.JPG'); %读取原图象 

 [m,n,o]=size(sourcePic);  %测量图像尺寸参数

 grayPic=rgb2gray(sourcePic);%将原来彩色图片转换为黑白图片,并将数据存入数组

 figure,imshow(sourcePic);%显示原来彩色图片

 figure,imshow(grayPic); %显示黑白图片

 gp=zeros(1,256); %计算各灰度出现的概率 

 for i=1:256 

     gp(i)=length(find(grayPic==(i-1)))/(m*n); 

 end  %计算每级灰度出现的概率,将其存入gp中相应位置

 figure,bar(0:255,gp);  %绘制直方图

 title('原图像直方图'); 

 xlabel('灰度值'); 

 ylabel('出现概率'); 

 newGp=zeros(1,256); %计算新的各灰度出现的概率 

 S1=zeros(1,256); 

 S2=zeros(1,256); 

 tmp=0; 

 for i=1:256 

     tmp=tmp+gp(i); 

     S1(i)=tmp;  %计算Sk

     S2(i)=round(S1(i)*256);  %将Sk规划到最近的灰度

 end

 for i=1:256 

     newGp(i)=sum(gp(find(S2==i))); %计算现有每个灰度级出现的概率

 end 

 figure,bar(0:255,newGp); 

 title('均衡化后的直方图'); 

 xlabel('灰度值'); 

 ylabel('出现概率'); 

 newGrayPic=grayPic; %填充各像素点新的灰度值 

 for i=1:256 

     newGrayPic(find(grayPic==(i-1)))=S2(i); %将各个像素归一化后的灰度值赋给这个像素

 end 

 figure,imshow(newGrayPic);

title('均衡化后的图像 '); 

【说明】

所用函数:

1、ZEROS  Zeros array.零矩阵

   ZEROS(N) is an N-by-N matrix of zeros.N阶的全零矩阵

ZEROS(SIZE(A)) is the same size as A and all zeros.大小与矩阵A一样的全零矩阵

2、LENGTH(X) returns the length of vector X;返回向量X的长度

It is equivalent to MAX(SIZE(X)) for non-empty arrays and 0 for empty ones.相当于求非空数组的MAX(SIZE(X))和空数组的从0到MAX

3、FIND   Find indices of nonzero elements.查找非零元素指标

I = FIND(X) returns the linear indices of the array X that are nonzero.返回非零的线性阵列的X指数。

   X may be a logical expression,Use IND2SUB(I,SIZE(X)) to calculate multiple subscripts from the linear indices I.

X可能是一个逻辑表达式

4、RGB2GRAY Convert RGB image or colormap to grayscale.

将RGB格式的图片灰度化

5、ROUND  Round towards nearest integer.轮对最接近的整数

ROUND(X) rounds the elements of X to the nearest integers.

6、SUM Sum of elements.

S = SUM(X) is the sum of the elements of the vector X.

7、BAR Bar graph.条形化图

   BAR(X,Y) draws the columns of the M-by-N matrix Y as M groups of N vertical bars.  The vector X must not have duplicate values.

【运行结果】

【小结】

通过这次的课程设计,我首次通过编写代码来完成对图像的处理,这是一份难得的经验。在刚开始运用MATLAB时,由于长时间的搁置,对其操作可以说是非常的不熟练,但是,当我把以前做过的MATLAB实验的记录重新看过之后,开始慢慢的对MATLAB的操作熟练起来,并且在实践中找到了学习的乐趣。虽然在这短时间里需要不断查资料,然后对着电脑,把一个一个郁闷得问题解决,那过程真的是苦不堪言。但当自己把一个个的问题慢慢解决,运行成功的时候,那种快乐也是无可比拟的。

平时上课的时候只是对老师讲的图像处理的动手环节比较感兴趣,对其原理和基础知识不太刚兴趣,甚至可以说完全不明白。但是,通过向老师请教,上网查资料,我对直方图均衡化的基本原理了解的很清楚了,并且在调试代码和运用HELP中对其均衡化的过程有了进一步的了解。同时,也通过这次课程设计,对MATLAB中的一些常用函数有了一定的了解,对于以后对MATLAB的运用打下了良好的基础。总得来说,这次课程设计,我,受益匪浅。

计算机科学与技术学院

0703班 ***

 

第二篇:数字图像处理课程设计报告

一.   课程题目:Photoshop + 直方图均衡化

二.   设计目的:

数字图像处理课程设计是在完成数字图像处理的相关理论的学习后,进行的综合性训练课程,其目的主要包括:

1、使学生进一步巩固数字图像处理的基本概念、理论、分析方法和实现方法;

2、增强学生应用VC++编写数字图像处理的应用程序及分析、解决实际问题的能力;

       3、尝试将所学的内容解决实际工程问题,培养学生的工程实践能力,提高工科学生的就业能力

三.   设计内容:

( 备注:该课程设计是基于之前数字图像处理实验,其中新加入的功能涉及到之前的基础,需要调用其处理函数,故保留其实验功能并进行扩展。设计中涉及的一些知识已经在实验时介绍过,此处只对新加入功能进行分析 )

打开图像—打开一幅BMP格式的图像,若打开的不是该格式,提示错误。代码略;

图像平滑—主要用来修饰边缘过于清晰,或者对比度过于强烈的图像,通过取平均值减少相邻像素间的差异,从而产生平滑的过渡效果。

作用:削弱相邻像素间颜色的差异,达到柔化图像的效果。代码略;

图像锐化—主要用来通过增强相邻像素间的对比度,使图像具有明显的轮廓,并变得更加清晰。效果与“图像平滑”的效果正好相反。代码略;

底片化---底片上的颜色与色彩鲜艳的照片的颜色是正好相反的,即反色。代码略;

二值化—主要是用来将整幅图像呈现出明显的黑白效果。代码略;

垂直翻转

垂直翻转是指把定义好的图像区域上下翻转地显示在屏幕上。器方法是保持每行像素信息不变,改变行的顺序,将第一行的像素与倒数第一行的像素进行互换,第二行的与倒数第二行的互换……依次类推,从而实现图像的垂直翻转。具体算法如下:

for(i=0;i<nh/2;i++)

            for(j=0;j<nw;j++)

            {

                   temp=m_dib.m_pdata[i*nh+j];

                   m_dib.m_pdata[i*nh+j]=m_dib.m_pdata[j+(nh-i-1)*nw];

                   m_dib.m_pdata[j+(nh-i-1)*nw]=temp;

            }

垂直翻转的效果图如下:

水平镜像

水平翻转是指将图像左右翻转地显示在屏幕上。其方法是保持行的顺序不变,改变列的顺序,将第一列的像素与倒数第一列的像素互换,第二列的像素与倒数第二列的像素互换……依次类推,从而实现图像的水平翻转。其具体算法如下:

for(j=0;j<nh;j++)

            for(i=0;i<nw/2;i++)

            {

                   temp=m_dib.m_pdata[j*nw+i];

                   m_dib.m_pdata[j*nw+i]=m_dib.m_pdata[j*nw+(nw-i-1)];

                   m_dib.m_pdata[j*nw+(nw-i-1)]=temp;

            }

水平镜像的效果图如下:

旋转90°

旋转90°是指把图像绕位把位图中心点以顺、逆时针方向旋转90°。其方法是计算旋转后像素的宽和高,生成新的位图像素缓冲区。基于旋转方向和旋转前像素的坐标,计算旋转后像素的坐标,将旋转前得像素复制到新的像素缓冲去的对应旋转后线索坐标的地方,依次类推,逐点交换,从而实现位图的旋转。其具体算法如下:

顺时针旋转90°

int nw=m_dib.GetDIBWidth();

     int nh=m_dib.GetDIBHeight();

     int i,j;

   BYTE *p=new BYTE[nw*nh];

     memcpy(p,m_dib.m_pdata,nw*nh);  /

     //像素距阵的转置实现图像的顺时针旋转(图像像素的x、y坐标互换)

     for(j=0;j<nh;j++)

            for(i=0;i<nw;i++)

p[(nh-j)*nw-i-1]=m_dib.m_pdata[(nh-1-i)*nw+j];      memcpy(m_dib.m_pdata,p,nw*nh);

     delete []p;


     逆时针旋转90°

BYTE *p=new BYTE[nw*nh];

     memcpy(p,m_dib.m_pdata,nw*nh);

     //像素距阵的转置实现图像的逆时针旋转

     for(j=0;j<nh;j++)

            for(i=0;i<nw;i++)

            p[j*nw+i]=m_dib.m_pdata[(nh-1-i)*nw+j];

memcpy(m_dib.m_pdata,p,nw*nh);

     delete []p;

顺旋转90°效果图


素描风格化

素描风格化是指模拟铅笔作画,手工速写等艺术效果,实现素描效果的关键是轮廓的勾勒,轮廓也就是灰度的一个跳变。其方式是:将彩色图像转换成灰度图像,然后.求当前像素与周围像素的灰度的差值(与当前像素点右下角的像素进行比较),如果差值大于指定的阈值(此处假设为10),则颜色跳变严重,可以判断出该点是轮廓。这时就用黑点把它描绘出来,否则将它置为白色(用底片化进行处理)。其具体算法如下:


for(j=0;j<nh;j++)

            for(i=0;i<nw;i++)

            {

                   int k;

//当前像素点与右下角像素点的差值

                   k=m_dib.m_pdata[j*nw+i]-m_dib.m_pdata[(j+1)*nw+i+1];

                   if(k<10)

                          m_dib.m_pdata[j*nw+i]=0;

//对每一个象素进行底片化处理

     for(j=0;j<nh;j++)

            for(i=0;i<nw;i++)

            {

            //对图像的第j行、第i列的象素的

灰度信息进行判断,修改

                   int gray=m_dib.m_pdata[j*nw+i];

                   m_dib.m_pdata[j*nw+i]=255-gray;

            }

 

素描风格化的效果图如左边所示。


浮雕效果

浮雕效果是指通过勾画图象轮廓和降低周围像素色值,从而生成具有凹凸感的浮雕效果。其方法是生成一缓冲区,计算当前像素的左上角与右下角的像素值之差,再加上一个补值。将其存储到缓冲区。再将缓冲区的数据逐点替换到图像中并显示出来。其具体算法如下:

int i,j,w=3;     //w为模板宽度

    BYTE *p=new BYTE[nw*nh];

     memcpy(p,m_dib.m_pdata,nw*nh);

    for(j=w/2;j<nh-w/2;j++)

              for(i= w/2;i<nw-w/2;i++)

{    p[j*nw+i]=m_dib.m_pdata[(j-1)*nw+i-1]*(1)+m_dib.m_pdata[(j+1)*nw+i+1]*(-1)+120;

              }

    memcpy(m_dib.m_pdata,p,nw*nh);

     delete []p;

 

      浮雕效果                                  彩图反转效果

补光灯

补光灯是为了提高图像的亮度。实现方法是将图像中每个像素点的值加上一个常数。具体算法省略。

彩图反转

彩图反转与底片化很相似,不同之处在于彩图反转是对每个像素中的R、G、B三个字节的值进行操作。具体算法如下:

int lenght=3*nw;

       while(lenght%4!=0)lenght++;

       lenght=lenght-3*nw;//一个扫描行所占的字节数

    int i,j;

       int tempR=0,tempG=0,tempB=0;//定义三个临时颜色变量

       for(i=0;i<nh;i++)

       {            for(j=0;j<nw;j++)

              {

                     tempR=m_dib.m_pDIBData[i*(3*nw+lenght)+j*3];

                     tempG=m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+1];

                     tempB=m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+2];          

                     tempR=255-tempR;//真彩反色

                     tempG=255-tempG;

                     tempB=255-tempB;

            m_dib.m_pDIBData[i*(3*nw+lenght)+j*3]=tempR;

                     m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+1]=tempG;

                     m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+2]=tempB;          

              }

       }

老照片

一般用在一些相片处理上,使整张相片呈棕褐色,好像已经保存了很久。实现方法是对图像中的每一个像素点,按特定的颜色变换公式求出新的颜色值并替换到图像中。具体算法如下:

int lenght=3*nw;

       while(lenght%4!=0)lenght++;

       lenght=lenght-3*nw;//一个扫描行所占的字节数

    int i,j;

       int R1=0,G1=0,B1=0,R2,G2,B2;//定义三个临时颜色变量

       for(i=0;i<nh;i++)

       {

              for(j=0;j<nw;j++)

              {            R1=m_dib.m_pDIBData[i*(3*nw+lenght)+j*3];

                         G1=m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+1];

                            B1=m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+2];                  

                            R2=(int)(0.393*R1+0.769*G1+0.189*B1);  //R、G、B的替换公式

                            G2=(int)(0.349*R1+0.686*G1+0.168*B1);

                            B2=(int)(0.272*R1+0.534*G1+0.131*B1);               

                 m_dib.m_pDIBData[i*(3*nw+lenght)+j*3]=R2;

                            m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+1]=G2;

                            m_dib.m_pDIBData[i*(3*nw+lenght)+j*3+2]=B2;         

              }

       }

特殊功能直方图均衡化

直方图均衡化处理的关键就是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。本次的设计思想主要是来自何家峰老师的数字图像处理理论教学,具体方法是:

程序算法(主要代码):

int n[256],g[256];  //定义频数数组n,均衡化每个像素的灰度级的数组g

       double f[256],t[256];  //定义频率数组f,累加的频率数组t

int g_max=0,g_mim=255;       

    for(j=0;j<nh;j++)    //统计灰度级的频数n

               for(i=0;i<nw;i++)

               {    int z=m_dib.m_pdata[j*nw+i];

             n[z]++;

               }   

       for(k=0;k<=255;k++)     //统计每个灰度级出现的频率

              f[k]=n[k]/(nw*nh*1.0); 

       //累计灰度级的频率

    t[0]=f[0];

       for(k=1;k<=255;k++)

           t[k]=t[k-1]+f[k];       

    for(j=0;j<nh;j++)      

           for(i=0;i<nw;i++)

              {     BYTE w=m_dib.m_pdata[j*nw+i];

                     g_max=w>g_max?w:g_max; //得到最大值

                     g_mim=w<g_mim?w:g_mim;       //得到最小值 

              }        

       for(k=0;k<=255;k++)   //利用公式求每个像素均衡化后的灰度级

              g[k]=(int)((g_max-g_mim)*t[k]+g_mim+0.5);       

    for(j=0;j<nh;j++)       //逐个替换

           for(i=0;i<nw;i++)

            m_dib.m_pdata[j*nw+i]=g[m_dib.m_pdata[j*nw+i]];   

    for(j=0;j<nh;j++)      //计算均衡化的直方图

           for(i=0;i<nw;i++)

                     {     BYTE temp=m_dib.m_pdata[j*nw+i];

                      m_hist[temp]++;

                     }

    m_dib.UpdateData();

       m_flag=true;

       m_dib.UpdateData();

       Invalidate();   

在屏幕上“画出”归一化直方图(主要代码):

if(m_flag==true)

       {     //绘制原图像的直方图

              CString str;

              //     画坐标轴// 绘制坐标轴从(410,nh+20)到(410,nh+200)画直线       

              pDC->MoveTo(400,nh+20);  //左上角坐标

              pDC->LineTo(400,nh+200);//左下角坐标

              pDC->LineTo(690,nh+200);//右下角坐标

              // 写X轴刻度值//在(x,y)处写字符串str          

              str.Format("0");            pDC->TextOut(400, nh+200+10, str);

              str.Format("50");           pDC->TextOut(450, nh+200+10, str);

              str.Format("100");         pDC->TextOut(500, nh+200+10, str);

              str.Format("150");         pDC->TextOut(550, nh+200+10, str);

              str.Format("200");         pDC->TextOut(600, nh+200+10, str);

              str.Format("255");         pDC->TextOut(650, nh+200+10, str);

              // 绘制X轴刻度

              for ( i = 0; i < 256; i += 25)

              {     pDC->MoveTo(i+9,nh+200-4);

                     pDC->LineTo(i+9,nh+200+4);

                     pDC->MoveTo(i+10,nh+200-4);

                     pDC->LineTo(i+10,nh+200+4);

                     pDC->MoveTo(i+11,nh+200-4);

                     pDC->LineTo(i+11,nh+200+4);

              }

              // 绘制Y轴刻度

              for (i=0,j=0;i<4;i++,j+=40)

              {     pDC->MoveTo(400-4,nh+20+20+j);

                     pDC->LineTo(400+4,nh+20+20+j);     

              }

//标志y轴坐标

              str.Format("1");           pDC->TextOut(400-20, nh+20+20, str);

              str.Format("0.5");          pDC->TextOut(400-20, nh+20+100, str);

              // 绘制X轴箭头

              pDC->MoveTo(685,nh+200-5);

              pDC->LineTo(690,nh+200);

              pDC->LineTo(685,nh+200+5);

              // 绘制y轴箭头

              pDC->MoveTo(395,nh+20+5);

              pDC->LineTo(400,nh+20);

              pDC->LineTo(405,nh+20+5);

//写标题

              str.Format("原始直方图");

              pDC->TextOut(480, nh+20, str);

              int max=0;

              for(i=0;i<256;i++)

                     max=m_source[i]>max?m_source[i]:max;          

              for(i=0;i<256;i++)

              {     pDC->MoveTo(400+i,nh+200);

                     pDC->LineTo(400+i,nh+200-(m_source[i]*160/max))

;//除以max是归一化,*160是因为我y轴范围是180,方便观看

              }

       }    

四.   设计心得体会:

   该课程设计是在之前的数字图像处理实验的基础上进行深入学习,我一开始选择的是数字水印题目,经过2天的研究,虽然对数字水印的实现原理和算法有了一定的了解,网上也有相关的关键算法代码,然而看似简单,自己做起来确实很艰难,加上时间紧迫,最终放弃数字水印课题。我选择了较为简单的PHOTOSHOP课题,通过查找相关算法(主要是耿蕊的PPT报告--《风格化的一些算法》),最终实现了一个个功能:浮雕、老照片、镜像处理、旋转处理、素描风格、彩图反转,但是耿蕊的PPT中有关的连环画、油画算法,我始终不能实现,这也是很遗憾。

整个PHOTOSHOP工具花了5天时间,最后剩下的一周我决定再做一个课题—直方图均衡化。直方图均衡化是我认为比较容易实现的,因为在数字图像处理理论课中,何老师很详细地讲解了其算法的实现,并且给出了相应的框图例子,只要一步步按照何老师讲诉的算法,并且用程序替换,就可实现。直方图均衡化课题中的难点是“画坐标图”。通过上网查找知道涉及的相关函数MoveTo()、LineTo()、Format()、TextOut(),虽知道其函数效果,也看过相关例子,但将其实际应用到自己的显示屏幕确实出现诸多问题,首先坐标的原点位置只能不断试验以找到合适位置。箭头、坐标刻度、刻度值等相关算法的程序实现更是难上加难。因为绘制新直方图的坐标图时没考虑到刻度值的问题,在后面的标刻度时没空间,只能中断Y轴以显示刻度值,结果看图。整个直方图均衡化,2/3的时间花在绘制坐标图。 

通过对以上两个课题的设计和实现,我深入理解了photoshop部分工具的实现原理和实现方法,增加了对VC++ MFC单文本框的应用。同时,数字图像处理理论知识的实践,激发了我对图像处理领域的兴趣,希望能通过此次图像处理的练习,在暑假实现视频的压缩处理,运用到高清数字电视领域。

参考文献:

《数字图像处理》 ——电子工业出版社

《vc++数字图像处理实验指导书》   曹老师、何家峰主编

《VC++图像处理设计》 (第二版) 杨淑莹主编

《Visual C++项目开发实用案例》 刘瑞、吴跃进、王宗跃主编

《风格化的一些算法》(PPT)  耿蕊  20##年12月23日  

相关推荐