数字图像处理课程设计报告.docx
《数字图像处理课程设计报告.docx》由会员分享,可在线阅读,更多相关《数字图像处理课程设计报告.docx(15页珍藏版)》请在冰点文库上搜索。
![数字图像处理课程设计报告.docx](https://file1.bingdoc.com/fileroot1/2023-5/23/a14c474e-74f5-47c6-8665-f5f93c3dae1a/a14c474e-74f5-47c6-8665-f5f93c3dae1a1.gif)
数字图像处理课程设计报告
一.课程题目:
Photoshop+直方图均衡化
二.设计目的:
数字图像处理课程设计是在完成数字图像处理的相关理论的学习后,进行的综合性训练课程,其目的主要包括:
1、使学生进一步巩固数字图像处理的基本概念、理论、分析方法和实现方法;
2、增强学生应用VC++编写数字图像处理的应用程序及分析、解决实际问题的能力;
3、尝试将所学的内容解决实际工程问题,培养学生的工程实践能力,提高工科学生的就业能力
三.设计内容:
(备注:
该课程设计是基于之前数字图像处理实验,其中新加入的功能涉及到之前的基础,需要调用其处理函数,故保留其实验功能并进行扩展。
设计中涉及的一些知识已经在实验时介绍过,此处只对新加入功能进行分析)
打开图像—打开一幅BMP格式的图像,若打开的不是该格式,提示错误。
代码略;
图像平滑—主要用来修饰边缘过于清晰,或者对比度过于强烈的图像,通过取平均值减少相邻像素间的差异,从而产生平滑的过渡效果。
作用:
削弱相邻像素间颜色的差异,达到柔化图像的效果。
代码略;
图像锐化—主要用来通过增强相邻像素间的对比度,使图像具有明显的轮廓,并变得更加清晰。
效果与“图像平滑”的效果正好相反。
代码略;
底片化---底片上的颜色与色彩鲜艳的照片的颜色是正好相反的,即反色。
代码略;
二值化—主要是用来将整幅图像呈现出明显的黑白效果。
代码略;
垂直翻转
垂直翻转是指把定义好的图像区域上下翻转地显示在屏幕上。
器方法是保持每行像素信息不变,改变行的顺序,将第一行的像素与倒数第一行的像素进行互换,第二行的与倒数第二行的互换……依次类推,从而实现图像的垂直翻转。
具体算法如下:
for(i=0;ifor(j=0;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;jfor(i=0;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°
intnw=m_dib.GetDIBWidth();
intnh=m_dib.GetDIBHeight();
inti,j;
BYTE*p=newBYTE[nw*nh];
memcpy(p,m_dib.m_pdata,nw*nh);/
//像素距阵的转置实现图像的顺时针旋转(图像像素的x、y坐标互换)
for(j=0;jfor(i=0;ip[(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=newBYTE[nw*nh];
memcpy(p,m_dib.m_pdata,nw*nh);
//像素距阵的转置实现图像的逆时针旋转
for(j=0;jfor(i=0;ip[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;jfor(i=0;i{
intk;
//当前像素点与右下角像素点的差值
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;jfor(i=0;i{
//对图像的第j行、第i列的象素的
灰度信息进行判断,修改
intgray=m_dib.m_pdata[j*nw+i];
m_dib.m_pdata[j*nw+i]=255-gray;
}
素描风格化的效果图如左边所示。
浮雕效果
浮雕效果是指通过勾画图象轮廓和降低周围像素色值,从而生成具有凹凸感的浮雕效果。
其方法是生成一缓冲区,计算当前像素的左上角与右下角的像素值之差,再加上一个补值。
将其存储到缓冲区。
再将缓冲区的数据逐点替换到图像中并显示出来。
其具体算法如下:
inti,j,w=3;//w为模板宽度
BYTE*p=newBYTE[nw*nh];
memcpy(p,m_dib.m_pdata,nw*nh);
for(j=w/2;jfor(i=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三个字节的值进行操作。
具体算法如下:
intlenght=3*nw;
while(lenght%4!
=0)lenght++;
lenght=lenght-3*nw;//一个扫描行所占的字节数
inti,j;
inttempR=0,tempG=0,tempB=0;//定义三个临时颜色变量
for(i=0;i{for(j=0;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;
}
}
老照片
一般用在一些相片处理上,使整张相片呈棕褐色,好像已经保存了很久。
实现方法是对图像中的每一个像素点,按特定的颜色变换公式求出新的颜色值并替换到图像中。
具体算法如下:
intlenght=3*nw;
while(lenght%4!
=0)lenght++;
lenght=lenght-3*nw;//一个扫描行所占的字节数
inti,j;
intR1=0,G1=0,B1=0,R2,G2,B2;//定义三个临时颜色变量
for(i=0;i{
for(j=0;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;
}
}
特殊功能—直方图均衡化
直方图均衡化处理的关键就是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。
直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。
直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。
本次的设计思想主要是来自何家峰老师的数字图像处理理论教学,具体方法是:
程序算法(主要代码):
intn[256],g[256];//定义频数数组n,均衡化每个像素的灰度级的数组g
doublef[256],t[256];//定义频率数组f,累加的频率数组t
intg_max=0,g_mim=255;
for(j=0;jfor(i=0;i{intz=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;jfor(i=0;i{BYTEw=m_dib.m_pdata[j*nw+i];
g_max=w>g_max?
w:
g_max;//得到最大值
g_mim=ww:
g_mim;//得到最小值
}
for(k=0;k<=255;k++)//利用公式求每个像素均衡化后的灰度级
g[k]=(int)((g_max-g_mim)*t[k]+g_mim+0.5);
for(j=0;jfor(i=0;im_dib.m_pdata[j*nw+i]=g[m_dib.m_pdata[j*nw+i]];
for(j=0;jfor(i=0;i{BYTEtemp=m_dib.m_pdata[j*nw+i];
m_hist[temp]++;
}
m_dib.UpdateData();
m_flag=true;
m_dib.UpdateData();
Invalidate();
在屏幕上“画出”归一化直方图(主要代码):
if(m_flag==true)
{//绘制原图像的直方图
CStringstr;
//画坐标轴//绘制坐标轴从(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);
intmax=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++图像处理设计》(第二版)杨淑莹主编
《VisualC++项目开发实用案例》刘瑞、吴跃进、王宗跃主编
《风格化的一些算法》(PPT)耿蕊2007年12月23日