%% 预处理
clc;clear;close all;
%%主程序包含三个函数,分别是XingTaiXue、DongTai_OTSU、Hough,
%%分别对应了三种细胞计数与面积计算方法
I = imread('Orig_Cell.JPG');
%% 在原图画框,展示三种算法结果。
counts=1;%第几次裁剪细胞图像
while(1)
? ? %原图裁剪
? ? figure('Name','请拖动鼠标左键选择裁剪区域,并双击鼠标左键确定'),imshow(I);
? ? fprintf(['\n%%%%%%%%%%%%%%%%%%%%%% ?我是分割线,这是你第%d次裁剪细胞 ?' ...
? ? ? ? '%%%%%%%%%%%%%%%%%%%%%\n'],counts);
? ? counts=counts+1;
? ? % 定义裁剪区域
? ? Xcropped = imcrop([I]); %加中括号的目的是不在CommendWindow显示裁剪矩阵
? ? subplot(221); imshow(Xcropped); title('裁剪原图');
? ? % 形态学处理
? ? subplot(222); imshow(Xcropped); title('形态学处理'); hold on
? ? [XingTai,Num_XingTai,Area_XingTai] = XingTaiXue(Xcropped,1);
? ? %动态阈值处理
? ? M=256;
? ? Xcropped = Xcropped(:,:,1);
? ? subplot(223); imshow(Xcropped); title('动态阈值(OTSU)'); hold on
? ? [YuZhi,Num_Yuzhi,Area_YuZhi] = DongTai_OTSU(Xcropped,M,1);
? ? % 霍夫圆变换处理
? ? subplot(224); imshow(Xcropped); title('霍夫圆变换'); hold on
? ? %为了让霍夫圆在原图圈出
? ? [HuoFu,Num_Hough,Average_Hough_area] = Hough(Xcropped,1);
? ? %% 血细胞计数与面积计算
? ? fprintf('\n基于形态学的细胞个数统计:%d个\n',Num_XingTai);
? ? fprintf('基于形态学的细胞平均面积计算:%2.2f(pixels)\n',Area_XingTai);
? ? fprintf('\n基于OTSU动态阈值分割的细胞个数统计:%d个\n',Num_Yuzhi);
? ? fprintf('基于OTSU动态阈值分割的细胞平均面积计算:%2.2f(pixels)\n',Area_YuZhi);
? ? fprintf('\n基于Hough圆检测的细胞个数统计:%d个\n',Num_Hough);
? ? fprintf('基于Hough圆检测的细胞平均面积计算:%2.2f(pixels)\n', ...
? ? ? ? Average_Hough_area);
? ? %% 询问是否继续裁剪
? ? h=questdlg('你还想进行下一次裁剪吗?','下次否? ','Yes !','No !','Yes !');
? ? if strcmp(h,'No !') ? ?%选Yes则默认继续下次分割
? ? ? ? break
? ? end
end
DongTai_OTSU:
function [bw1,n,average_cell] = DongTai_OTSU(im,M,temp)
[m,n] = size(im);
p=ceil(m/M);
q=ceil(n/M);
bw1=zeros(m,n);
for i=1:p
for j=1:q
x1=0;x2=0;
y1=0;y2=0;
if j<q&&i<p
tempI=im((i-1)*M+1:i*M,(j-1)*M+1:j*M);
x1=(i-1)*M+1;x2=i*M;
y1=(j-1)*M+1;y2=j*M;
else if j==q&&i<p
tempI=im((i-1)*M+1:i*M,(j-1)*M+1:end);
x1=(i-1)*M+1;x2=i*M;
y1=(j-1)*M+1;y2=n;
else if i==p&&j<q
tempI=im((i-1)*M+1:end,(j-1)*M+1:j*M);
x1=(i-1)*M+1;x2=m;
y1=(j-1)*M+1;y2=j*M;
else
tempI=im((i-1)*M+1:end,(j-1)*M+1:end);
x1=(i-1)*M+1;x2=m;
y1=(j-1)*M+1;y2=n;
end
end
end
T = graythresh(tempI); %OTSU阈值
tempBW=imbinarize(tempI,T);
bw1(x1:x2,y1:y2)=tempBW;
end
end
%%
OTSU_cell=not(bw1);
fill_image=imfill(OTSU_cell,'holes');%填充孔洞
% figure('Name','二值化填充后'),imshow(fill_image);
delete_image = imclearborder(fill_image,4);%删除和图像边界相连的色块。
% figure('Name','删除白色无关区域'),imshow(delete_image);
final_image = bwareaopen(delete_image,200);%删除噪点
% figure('Name','处理后图像'),imshow(final_image);
if temp~=0
hold on
[~,n]=bwlabel(final_image);%标签化并计算个数
t=1;
Area_lk=[];
%% 求平均面积
sum_cell=0;
[B,L] = bwboundaries(final_image,'noholes');
stats = regionprops(L,'Area','Centroid'); %计算图像区域中像素个数、中心
for k1 = 1:length(B) %B是轮廓,k1相当于label值
boundary = B{k1};
plot(boundary(:,2),boundary(:,1),'r','LineWidth',2)
area= stats(k1).Area; %求出每个区域的面积
Area_lk(t)=area;
sum_cell=sum_cell+area; %面积累加
%%设置图像中字符显示的属性
text(boundary(1,2)-5,boundary(1,1)+5,num2str(k1),'Color','w',...
'FontSize',9,'FontWeight','bold')
text(boundary(1,2)-15,boundary(1,1)+20,num2str(Area_lk(t),'%2.2f\n'),...
'Color','g','FontSize',10,'FontWeight','bold')
t=t+1;
end
average_cell=sum_cell/length(B);%求出平均面积
end
end
Hough
function [bw,n,average_cell] = Hough(im,temp)
%%
%形态学操作
se = strel('disk',2);
I_BW = im2bw(im,graythresh(im));
Ie = imerode(I_BW,se);
Iobr = imreconstruct(Ie,I_BW);
Iobrd = imdilate(Iobr,se);
bw = imreconstruct(imcomplement(Iobrd),imcomplement(Iobr));
%%
Rmin = 13;
Rmax = 50;
%centersBright是圆心;radiiBright是圆的半径
[centersBright, radiiBright] = imfindcircles(bw,[Rmin Rmax],'ObjectPolarity','bright');
viscircles(centersBright, radiiBright,'EdgeColor','b');
if temp~=0
hough_area=[]; %单个霍夫圆的面积
n= length(radiiBright);
for i=1:n %半径的个数,即统计出来有几个圆
plot(centersBright(i,1), centersBright(i,2), ...
'bo', 'MarkerSize',radiiBright(i),'MarkerFaceColor','y');
hough_area(i)=pi*(radiiBright(i)+0.01)^2;%计算霍夫单个圆面积,半径+1最匹配
% 将每个霍夫变换标准圆的面积展示在图中
text(centersBright(i,1),centersBright(i,2),num2str(i),'Color','r',...
'FontSize',9,'FontWeight','bold')
text(centersBright(i,1),centersBright(i,2)+15,num2str(hough_area(i),'%2.2f\n'),...
'Color','g','FontSize',9,'FontWeight','bold')
end
average_cell=sum(hough_area)/n;
end
end
XingTaiXue
function [cell_final,n,average_cell] = XingTaiXue(original_picture,temp)
gray_picture=im2gray(original_picture);
BW_image=imbinarize(gray_picture,graythresh(original_picture));%转换为二值图像
BW_image=imcomplement(BW_image);%翻转黑白
BW_fill_black=imfill(BW_image,'holes');%填补黑色洞
%初步开运算减少白色区域
se1=strel('disk',14);
BW_open=imopen(BW_fill_black,se1);
%对比开运算前后图像,找出被删除的细胞
BW_delete=BW_fill_black-BW_open;
%开运算对比后图像,消除因细胞大小改变产生的细胞轮廓
se2=strel('disk',6);
BW_comparison=imopen(BW_delete,se2);
%对图像进行彻底但不消失细胞的侵蚀,使细胞不再连接
se3=strel('disk',10);
BW_erode=imerode(BW_open,se3);
%与此前消失的细胞的图像合并,恢复他们
BW_combined=BW_comparison+BW_erode;
%删除和图像边界相连的对象。
cell_final = imclearborder(BW_combined,4);
%% 细胞计数
if temp~=0
hold on
[~,n]=bwlabel(cell_final);%标签化并计算个数
t=1;
Area_lk=[];
%求平均面积
sum_cell=0;
[B,L] = bwboundaries(cell_final,'noholes');
stats = regionprops(L,'Area','Centroid'); %计算图像区域中像素个数、中心
for k1 = 1:length(B) %B是轮廓,k1相当于label值
boundary = B{k1};
plot(boundary(:,2),boundary(:,1),'r','LineWidth',2)
area= stats(k1).Area; %求出每个区域的面积
Area_lk(t)=area;
sum_cell=sum_cell+area; %面积累加
text(boundary(1,2)-5,boundary(1,1)+5,num2str(k1),'Color','w',...
'FontSize',9,'FontWeight','bold')
text(boundary(1,2)-15,boundary(1,1)+20,num2str(Area_lk(t),'%2.2f\n'),'Color','g',...
'FontSize',10,'FontWeight','bold') %%设置图像中字符显示的属性
t=t+1;
end
average_cell=sum_cell/length(B);%求出平均面积
end
end