数字图像处理课程设计报告目录一.实验目的 (3)二.实验内容............ ................... . (3)1.打开图像 (3)(1)、图像信息获取 (3)(2). RgbtoHsi(&rgb, &Hsi) (4)(3).OnMouseMove(UINT nFlags, CPoint point) (4)2.标记Mark点 (5)(1)标记可能的点 (5)(2)把可能标记的点变为标记点 (5)(3) EdgeIformation边缘标记 (6)(4)EdgeFilter边缘滤波 (6)3.二值化 (7)4.填洞 (8)5收缩 (10)6获取中心点 (11)三.学习心得1.错误总结 (16)2.心得体会 (17)一.实验目的:对血液细胞切片图片进行各种处理,最终得出细胞的数目、半径等信息基于vc的红细胞识别统计系统设计它主要以病人的血液样本为原始数据。
经过一系列的图像处理和分析,识别出血液中的红细胞,并能给出红细胞的个数。
而得到红细胞的个数以后,通过血液量的检测,就可以得出血液中红细胞的密度。
该系统可以很方便的利用在临床上,大大提高速度和效率。
二、实验内容基于VC++6.0软件下的细胞识别,通过细胞的标记、二值化、提取边缘、填洞、收缩、找中心点、计数等过程完成实验目的1 . 打开图像(1)图像信息获取该步骤实现的功能是打开bmp格式的图像文件,要对图像进行操作,系统必须能调用图像。
打开bmp图像的具体步骤为1.新建项目:--MFC AppWizard、工程名2.拷贝cdib.h,cdib.cpp到工程文件夹,再向工程里添加3.~Doc.h添加变量:m_pDib4.~doc.cpp:变量(m_pDib):new、delete5.~doc.cpp: Serialize()6.~View.cpp: OnDraw() m_pDib->Draw()2.RgbtoHsi(&rgb, &Hsi)RGB 向HSI 模型的转换是由一个基于笛卡尔直角坐标系的单位立方体向基于圆柱极坐标的双锥体的转换。
基本要求是将RGB 中的亮度因素分离,将色度分解为色调和饱和度,并用角向量表示色调。
如果直接对R 、G 、B 处理,其处理过程中很可能会引起三个量不同程度的变化,这样就会产生色差问题,甚至带来颜色上的失真。
HSI 模型的出现,使得在保持色彩无失真的情况下实现图像处理成为可能。
HSI 可以更好地区分细胞与非细胞,实现程序如,3. OnMouseMove(UINT nFlags, CPoint point) 当鼠标移动时调用此函数 。
point :鼠标的X,Y 坐标:该坐标为 鼠标距离截获该消息的窗口左上角的位置 是一个相对位置而不是在屏幕像素上的绝对位置。
在OnMouseMove函数里调用RgbtoHsi(&rgb, &Hsi)函数,可以在屏幕上显示鼠标所指点的坐标以及RGB、HSI和灰度值,通过HSI的可以选取合适的阈值来找到细胞以及边界。
2.标记Mark点(1)标记可能的点Mark点指的是我们要寻找的细胞内的点。
通过计算色调的平均值设置一个门限值,将色调与平均值差距在门限范围内的点设置为Mark点,同理通过计算色调的平均值设置一个MaybeMark的门限,将色调与平均值差距在门限范围内的点设置为MaybeMark点。
(2)把可能标记的点变为标记点;。
这一步是把可能的Mark点变成Mark点,因为在拍摄图片时由于光线等原因是本来的Mark点变暗,在进行Mark处理时被标记为Maybe Mark,所以需要把可能的Mark点还原Mark点。
mayMark变成Mark的思想是看mayMark周围有没有Mark点,若有,则变为Mark点。
一直做到一次遍历没有mayMark点变为Mark点。
(3)、EdgeIformation和EdgeFilterEdgeIformation是把边缘标记出来,方便后面的图像处理。
EdgeFilter是将提取出来的边缘进行滤波,即删除细胞内部不应该存在的小边缘。
提取边缘的过程是先开辟一块内存用于存放数据,通过设置的门限值来找到边缘点,在提取边缘时用到重要的sobel算子,sobel算子主要用作边缘检测。
在技术上,它是一离散性差分算子,用来运算图像亮度函数的梯度之近似值。
在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。
该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。
EdgeFilter是在边缘点上取个边长为M的矩形,在矩形上遍历一遍,若没碰到Mark点和边缘点,则删除该边缘。
实现是Mark点,,边界(edge)的标记,MayBeMark To Mark--RGB(128,0,0),将细胞、可能是细胞的区域、不可能是细胞的区域、细胞边界分别用红色、暗红、蓝色和绿色标记3、二值化从多值的数字图像中直接提取出目标物体,最常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。
这是研究灰度变换的最特殊的方法,称为图像的二值化。
二值化后更加有利于做图像处理判别。
将一副彩色图像二值化,首先要申请的8位数据缓存空间,用于存放处理后的数据,为了充分利用这8位的内存,将这8位分别用于不同的标志位,如最高位为是否为Mark标志位,接下来的三位为边缘标志位,最后一位为访问标志位等,实现程序如下,4、填洞孔洞填充的原理如下:在阈值处理时,如果像素在阈值范围内,则像素将被标志。
孔洞填充将先统计所有连通的非标志区域面积,总会有一个或者几个面积特别大的区域,其它的都是面积相对较小的区域。
较小或者很小的往往就是系统所要填充的孔洞了。
从一个为访问过的非MARK点开始,从该点开始向四周扩散找未被访问过的非MARK点。
将找到的符合条件的点同时压如堆栈和队列中。
之所以要同时在堆栈和队列中同时保存相同的点是因为堆栈中的点并没有保存,每次循环都会弹出一个点作为新的种子进行扩散,当堆栈中的数据全部弹出之后,即表示搜索到了洞内的所有点,而队列中则保存了洞内的所有点。
因此通过判断队列的大小可以知道洞的大小从而判断是否进行填充。
填充就是经洞内的非MARK点变换为MARK点在此函数中调用了一个函数ProcessFillHoles(j,i);这个函数的功能是实现填洞。
通过OnFillHoles()调用。
5、收缩扫描图像,对图像进行预先的3次腐蚀,判断所生成边界点,然后根据原理判定是否标注该点,存放所标志的中心点,便于统计细胞个数及计算细胞半径。
先去掉边缘点,然后将剩下的Mark点生成边缘点,再去掉在生成,直到去掉三次边缘,就这样收缩,如果收缩过程中有些Mark点收缩到很小,可以认为那不是细胞,那就可以直接去掉。
函数中调用了两个函数GenEdge8();和GenEdge4();这两个函数的功能分别为获得八方向的边界和获得四方向的边界。
6、获取中心点根据前面所作工作统计获得的中心点个数,去掉一系列不符合要求的点得出最终的细胞个数、细胞的平均半径和平均面积,用对话框输出统计结果中心点的获取就是通过不断地进行收缩直到最后一次收缩后会导致中心点消失时停止。
收缩算法的思想就是在识别出细胞和其边界的基础上,首先进行一次遍历将所有已标记为边界的点变为非MARK点,然后再通过genEdge()、genEdge4()从八方向和四方向进行交替生成边界。
生成边界的思想很简单,就是通过判断MARK点上下左右四个方向或者八个方向是否有非Mark点,如果有的话即认为是边界,将该点加上边界标志。
而中心点的获取就是在每一次的收缩之前先进性一次判断,如果该点是孤立点或者是全边界点则将该点保存起来。
因为对于孤立点和全边界点如果不进行保存的话在进行一次收缩之后该点就会消失,因此为了保存该点,就要在其消失前将其保存。
因此第一次获取的中心点个数会是真正中心点个数的三倍左右。
细胞半径大小的获取是通过判断该中心点是通过多少次收缩之后获得的近似等于细胞的半径。
<2>编写计数函数OnCount()说明:函数的功能是统计细胞的信息,包括细胞的个数,半径,平均面积等信息。
代码实现如下:函数体内调用了OnReload();函数。
此函数的功能为重新加载图像Blood。
便于人机交互。
<3>.对获取的细胞数据做进一步的处理,在这一步首先建立三个队列,用于储存每次处理后细胞的信息,即坐标半径。
第一步,取邻域(相连)中心点合并后,获得中心点数目368;第二步,相近的(不相连)中心点的处理(取半径大的),获得中心点数目219;第三步,去掉潜在的错误(圆r<9),获得中心点数目209;第四步,去掉潜在的错误(同两个圆相交,并且不相交的部分是噪声)即两个圆相交,相交部分过大,该圆不存在,获得中心点数目208。
第一步第二步第三四步三、学习心得一.错误总结:1..在填洞这步中,将EDGEPOINT定义为0xf0,结果出现黑屏,在和同学的讨论中发现的的问题2.同时运用到的函数有些没调用,需要自己添加#include <math.h> #include "MainFrm.h"#include <stack>#include <vector>等3.需要自己定义的参量,有些是在函数中的,只需要在函数中定义即可,若是全局变量可在最开始public里定义或在用到变量的函数中定义,4.编译没有出错但是连接运行时出错,之前运行时却没错,是因为之前运行过的窗口没关闭二.心得体会通过将近两个星期的学习使我对Vc++6.0的功能有了进一步的理解,对MFC(Microsoft Foundation Classes)有了初步的认识;亲身体验了一个实用程序开发的全过程。
对MFC和VC 6.0有了基本的了解。
同时也是程序编写细节上的注意。
这次课程设计有了老师给的参考资料与讲解,实验容易很多,虽然还是有很多问题需要自己查找和改错。
有些问题自己找不出来,但是通过同学的帮助与老师的指导,问题基本上都有解决。
出现最多的就是从PPT所写的程序有很多的参量都没有定义,这些都是会出错的,刚开始不知道是什么错误,但遇到的多了自己也知道是什么原因,自己也可以改正过来了。
经过这些天的努力,终于完成了这份课程设计任务。
当正真完成程序的时候感觉并不是很难,难是因为我们不懂程序的含义与思路,当明白这些时就不难了,剩下的就是自己编写程序的能力了。
希望自己以后可以掌握编写程序的能力,与思路的培养。