这是我第一次做数字图像处理实验,所以在实验过程中遇到很多问题。每一个问题的解决也花费了大量时间。发在这里本来不妥,但希望在这里能遇到这方面的高手指点,碰碰运气。
下面我就本次实验报告贴上来,希望各位高手给点指点,谢谢~~
------------------------------------------------------------------------------------------------------------
数字图像处理实验报告:
对Blood图进行细胞个数统计
1. 实验图片:
2. 实验分析(技术难点):
图片中含有很多噪声,在图片二值化后应该进行图片的去噪。怎样获得良好的去噪效果,选取适合的去噪方法是本实验的难点所在。同时该图中有部分细胞相连程度较深,运用“开运算”或者“腐蚀”可能很难将细胞分开,影响“贴标签”对细胞的个数统计,应该找到一个更适合的方法来获取较准确的细胞个数。
3. 实验过程分析:
(1) 图像的二值化
这一步比较简单,具体代码如下:
Theshold = graythresh(Image);%取得图象的全局域值
Image_BW = im2bw(Image,Theshold);%二值化图象
figure,imshow(Image_BW);
title('初次二值化图像');
|
程序运行结果:
(2) 图像去噪
从二值化后的图象中可以看出,图片中有很多小黑点,属于“椒盐噪声”,我们这里采用一种较为简单的去噪方法——“中值滤波”,因为在一些小黑点附近是大量的白色背景,只要选取适当大的模版,就可以滤掉小黑点。
同时如果模版选取过大,可能会造成图像边缘太模糊,在二值图像中可能会扩大细胞边缘,不过在这里暂不考虑,因为下面一步我们将选取一个比较简单方法处理。
程序代码:
Image_BW_medfilt = medfilt2(Image_BW,[13 13]);
figure,imshow(Image_BW_medfilt);
title('中值滤波后的二值化图像');
|
运行结果如下:
(3) 二值图像逻辑运算
由于二值化图形的性质,我们完全可以通过逻辑运算来获得效果较好的图像效果。这也是为什么我们刚一开始就进行图像的二值化而不是图像的去噪的原因。通过对中值滤波后的图像可以看出,细胞边缘扩大,特别是图片边界的细胞。
细胞边缘扩大,黑色增多(二值图像“0”增多),所以我们将通过初次二值化图像与中值滤波后的二值化图像进行“或”运算将优化图像效果。
程序代码:
Optimized_Image_BW = Image_BW_medfilt|Image_BW;
figure,imshow(Optimized_Image_BW);
title('进行“或”运算优化图像效果');
|
运行结果如下:
(4) 图像取反
由于以下步骤操作是对二值化图像的“1”进行操作,本图队细胞进行操作。
所以进行图像取反,让细胞变为白色“1”。
程序代码:
Reverse_Image_BW = ~Optimized_Image_BW;
figure,imshow(Reverse_Image_BW);
title('优化后二值化图象取反');
|
运行结果如下:
(5) 填充细胞中心黑色的部分
利用bwfill函数填充二进制图像的背景色
程序代码:
Filled_Image_BW = bwfill(Reverse_Image_BW,'holes');
figure, imshow(Filled_Image_BW);
title('已填充背景色的二进制图像');
|
运行结果如下:
(6) 二值图像“开运算”
尽管运用“开运算”对该图粘连细胞的分离效果不好,但是我们这里仍要进行一次“开运算”,主要使图像的边缘细胞得到较好的分离。其实与上面图像相比较,本步骤也取得了一定的效果。
程序代码:
SE = strel('disk',4);
Open_Image_BW = imopen(Filled_Image_BW,SE);
figure, imshow(Open_Image_BW);
title('开运算后的图像');
|
运行结果如下:
(7) 统计细胞个数
图像中有部分细胞出现大面积重复,我们将采取特殊步骤进行统计。
注:图像边缘不完全的细胞也将作为整个细胞进行统计。
A. 利用贴标签初步计算出细胞的个数;
B.对不同标签号计算像素点个数;
C. 在计算出的一组像素数数据中,统计像素数数据特别大的标签个数,将此看作两个细胞的重合,同时重新对A步骤所得的数据统计。
D. 获得相对较准确的细胞个数。
程序代码:
[Label Number]=bwlabel(Open_Image_BW,8)%初步取得细胞个数
Array = bwlabel(Open_Image_BW,8);%取得贴标签处理后的图像
Sum = [];
%依次统计贴标签后数组
for i=1:Number
[r,c] = find(Array==i);%获取相同标签号的位置,将位置信息存入[r,c]
rc = [r c];
Num = length(rc);%取得vc数组的元素的个数
Sum([i])=Num;%将元素个数存入Sum数组
end
Sum
N = 0;
%假如Sum数组中的元素大于了1500,表示有两个细胞相连,像素点较多,即分为两个细胞数
for i=1:length(Sum)
if(Sum([i])) > 1500
N = N+1;
end
end
%-------------------------------------------
%------------------统计最终细胞数-----------
%-------------------------------------------
Number = Number+N
|
4. 详细程序清单如下:
%工作前准备
clear;
close all;
%------------------
%程序中定义图像变量说明
%Image->原图变量;
%Image_BW->二值化图象;
%Image_BW_medfilt->中值滤波后的二值化图像;
%Optimized_Image_BW-〉通过“初次二值化图像”与“中值滤波后的二值化图像”进行“或”运算优化图像效果;
%Reverse_Image_BW-〉优化后二值化图象取反;
%Filled_Image_BW-〉已填充背景色的二进制图像;
%Open_Image_BW-〉开运算后的图像。
%------------------
%--------------------------------------
%-------图片前期处理-------------------
%--------------------------------------
%第一步:读取原图,并显示
Image = imread('blood1.tif');
figure,imshow(Image);
title('原图');
%第二步:进行二值化
Theshold = graythresh(Image);%取得图象的全局域值
Image_BW = im2bw(Image,Theshold);%二值化图象
figure,imshow(Image_BW);
title('初次二值化图像');
%第三步二值化图像进行
Image_BW_medfilt= medfilt2(Image_BW,[13 13]);
figure,imshow(Image_BW_medfilt);
title('中值滤波后的二值化图像');
%第四步:通过“初次二值化图像”与“中值滤波后的二值化图像”进行“或”运算优化图像效果
Optimized_Image_BW = Image_BW_medfilt|Image_BW;
figure,imshow(Optimized_Image_BW);
title('进行“或”运算优化图像效果');
%第五步:优化后二值化图象取反,保证:‘
%方便下面的操作
Reverse_Image_BW = ~Optimized_Image_BW;
figure,imshow(Reverse_Image_BW);
title('优化后二值化图象取反');
%第六步:填充二进制图像的背景色,去掉细胞内的黑色空隙
Filled_Image_BW = bwfill(Reverse_Image_BW,'holes');
figure, imshow(Filled_Image_BW);
title('已填充背景色的二进制图像');
%第七步:对图像进行开运算,去掉细胞与细胞之间相粘连的部分
SE = strel('disk',4);
Open_Image_BW = imopen(Filled_Image_BW,SE);
figure, imshow(Open_Image_BW);
title('开运算后的图像');
%-----------------------------------------------
%-------------开始计算细胞数--------------------
%-----------------------------------------------
[Label Number]=bwlabel(Open_Image_BW,8)%初步取得细胞个数
Array = bwlabel(Open_Image_BW,8);%取得贴标签处理后的图像
Sum = [];
%依次统计贴标签后数组
for i=1:Number
[r,c] = find(Array==i);%获取相同标签号的位置,将位置信息存入[r,c]
rc = [r c];
Num = length(rc);%取得vc数组的元素的个数
Sum([i])=Num;%将元素个数存入Sum数组
end
Sum
N = 0;
%假如Sum数组中的元素大于了1500,表示有两个细胞相连,像素点较多,即分为两个细胞数
for i=1:length(Sum)
if(Sum([i])) > 1500
N = N+1;
end
end
%-------------------------------------------
%------------------统计最终细胞数-----------
%-------------------------------------------
Number = Number+N
|
实验结果:
细胞个数:30个
----------------------------------------------------------------------------------------------------------
希望大家指点,谢谢。