河南理工大学测绘与国土信息工程学院《数字图像处理》课程设计报告( 2018 - 2019 学年第 2 学期)班级:学号:姓名:指导教师:评语:成绩:批阅签字:批阅日期:年月日课程设计项目:灰度图像对比度增强一、课程设计项目说明在图像处理中,点运算是一种简单而又很重要的技术。
对于一幅输入图像,经过点运算将产生一幅输出图像,输出图像上每个像素的灰度值仅由相应输入原像素的值决定。
对比度增强,对比度拉伸或灰度变换都属于点运算。
点运算是图像数字化软件和图像显示软件的重要组成部分。
熟悉图像增强点运算方法,编程实现图像对比度增强算法,掌握灰度图像基本处理技术。
我们在此选取属于点运算的灰度变换来对图像进行对比度增强处理:灰度变换可使图像动态范围增大,图像对比度扩展,图像变清晰,特征明显,是图像增强的重要手段之一。
1.线性变换若原图像f(i,j)的灰度范围为[a,b],线性变换后图像g(i,j)的范围为[a′,b′],则g(i,j)与f(i,j)之间的关系式可以用下式来表示:(f(i,j)−a)①g(i,j)=a′+b′−a′b−a当b−a<b′−a′时,图像亮度范围扩大,图像被拉伸;当b−a>b′−a′时,图像亮度范围缩小,图像被压缩;2.对数变换对数变换的一般表达式为:g(i,j)=a+ln[f(i,j)+1]②b∙lnc这里a,b,c是为了调整曲线的位置和形状而引入的参数。
当希望对图像的低灰度区进行较大的拉伸而对高灰度区压缩时,可以采用这种变换,它能够使图像灰度分布与人的视觉特性相匹配。
并且当c越大时,压缩程度越大。
二、算法实现的主要内容//线性灰度变换void CLiView::OnBinary1(){ //获取文档指针CLiDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);//确保有BMP图像打开,否则弹出"Error!"对话框if(pDoc->m_pDib == NULL){AfxMessageBox("Error!");return;}//开始进行图像的灰度变换处理lxk:Cxxbh dlginputxxbh;//定义线性变换对话框类对象dlginputxxbh.DoModal();//弹出对话框UpdateData(TRUE);//将编辑框内的值赋给对应成员函数if (dlginputxxbh.m_u<dlginputxxbh.m_d)//判断所给数据是否规范{AfxMessageBox("Error!\n请勿颠倒上下限!");goto lxk;}/*当操作者所给上限小于下限时弹出错误提示对话框,关闭该对话框后,系统自动将编辑框内数据清零,此时可重新输入数据*/int mcols = pDoc->m_pDib->m_nCols,jcols;int mrows = pDoc->m_pDib->m_nRows,irows;unsigned char* m_pData=NULL;m_pData = pDoc->m_pDib->pImgData;unsigned char* m_pDataOldPos = m_pData;for(irows = 0; irows < mrows; irows++){for(jcols = 0; jcols < mcols; jcols++){m_pData += irows * mcols + jcols;//计算当前位图数据位置*m_pData = dlginputxxbh.m_d+(dlginputxxbh.m_u-dlginputxxbh.m_d)**m_pData/255;/*根据式①计算灰度变换后灰度值并替换当前灰度值*/ m_pData = m_pDataOldPos;//重置m_pData}}pDoc->UpdateAllViews(NULL);//刷新视图}//对数变换void CLiView::OnBinary()2{//获取文档指针CLiDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);//确保有BMP图像打开,否则弹出"Error!"对话框if(pDoc->m_pDib == NULL){AfxMessageBox("Error!");return;}//开始进行图像的对数变换处理Cdsbh dlginputds;//定义对数变换对话框类对象dlginputds.DoModal();//弹出对话框UpdateData(TRUE); //将编辑框内的值赋给对应成员函数int mcols = pDoc->m_pDib->m_nCols,jcols;int mrows = pDoc->m_pDib->m_nRows,irows;unsigned char* m_pData=NULL;m_pData = pDoc->m_pDib->pImgData;unsigned char* m_pDataOldPos = m_pData;for(irows = 0; irows < mrows; irows++){for(jcols = 0; jcols < mcols; jcols++){m_pData += irows * mcols + jcols;*m_pData = (log10(*m_pData+1))/( dlginputds.b*log10(dlginputds.c))+ dlginputds.a; /*根据式②计算灰度变换后灰度值并替换当前灰度值*///在此取a=2,b=1,c=0.233作为实验结果m_pData = m_pDataOldPos; //重置m_pData}}pDoc->UpdateAllViews(NULL); //刷新视图}三、图像处理结果图一操作界面图二原图1 图三线性灰度变换1 (阈值[0-255]) (阈值[0−300])图四原图2 图五线性灰度变换2 (阈值[2−250])图七对数灰度变换图六原图3 ( a=2,b=1,c=0.233)四、课程设计体会通过对这两周数字图像处理课程设计的学习,我们学会了很多以东西:第一,将程序做成软件。
之前编写的各种程序什么的,都是依赖于Windows命令提示窗口运行的,实在没办法跟软件联系起来;但我们这次学习的是基于VC++的MFC平台,第一次将代码放到了一个可运行的程序里面。
第二,自己动手编写程序对位图数据进行处理,加深对数字图像处理的理解。
我们的课本上虽然交代了各种图像处理的方法,当然也给出了计算公式,但用C++语言处理这些图像并不是一项简单的事情:诸如位图数据的读取,存放,赋值。
尽管在二值化处理中有相应代码,但对于我而言,也是在跟室友的谈论中意识到了数据的读取,存放规律,这才让后面的问题变得简单了很多。
第三,独自的收集资料和热情的交流。
在我们可以通过自身收集数据并解决问题时来解决绝大多数问题,固然很重要,但当我们遇到瓶颈时,交流则是必要的,你或许可以在交流中解决一些困扰你许久的问题。
另外在这次查找相关资料的同时,,偶尔又get到了些许技能。
第四,学习到了一些编程者的基本修养。
在一开始实习的时候,会因为不熟悉而导致一些错误,但这导致了整个项目的失败,只能重新来过,非常浪费时间。
但错误是难以避免的,程序是可以存档的,我们可以做一步,运行一次并保留副本,这样能节省不少时间,并且出问题的地方也显而易见。
在调试程序的时候,先从第一个问题开始,逐一查找逐一解决。
此外,对代码有很好的理解能力也是快速找到问题所在并解决的捷径之一。
第五,虽然这次课程设计时间安排有点儿长,内容上有些轻松,主要是有提供了图像二值化处理的样代码,但我现在仍然存在未解决的问题:1.未考虑图像处理的颜色失真在对原图像1进行线性灰度变换时,由于该图像仅由灰度值组成,未涉及到彩色,用线性灰度变换代码处理时,压缩图像时表现为画布变暗;拉伸图像时效果如图三所示,有不错的效果。
但是针对原图2,线性灰度变换程序就变的不太适合,在对原图进行压缩的时候出现了颜色上的较大失真(如图四所示),此时图像变得模糊不清。
同样的情况还出现在用对数变换函数处理原彩色图像3,不过此时的图像变得更像是一副淡色的素描一样(如图七所示)。
2.MFC框架问题在制作的测试过程中,发现在弹出对话框后,不论是点击“确认”或者是“取消”按钮,程序都将以赋予变量(如果有的话)的初始值继续运行下去,且不论是否为“取消”按钮添加响应程序。
虽然在我所能查阅到的资料里找到了MFC中ID_OK函数和ID_CANCEL 函数的响应机制,但最后还是没有解决掉此类问题3.处理效果问题在进行边缘检测处理时,对图像先进行线性灰度压缩(只针对原图1,因为其他彩色图像处理过后存在彩色失真,反而增大了噪声,边缘变得不明显),再进行边缘检测处理,会得到比直接进行边缘检测更好的效果。
最后,在这里要感谢老师在这两礼拜实习中的耐心讲解,陪我们一起度过这充实的午后时间。