Matlab 大津';s的阈值化实现工作不正常
我已经实现了otsu的阈值实现,它将图像分为前景图像和背景图像。我的实现的输出似乎与期望的不一致。有什么想法吗?提前谢谢!如果有人能告诉我如何解决这个问题,我将不胜感激 我的输出: 对于图1- 对于图2- 我的代码:Matlab 大津';s的阈值化实现工作不正常,matlab,image-processing,computer-vision,Matlab,Image Processing,Computer Vision,我已经实现了otsu的阈值实现,它将图像分为前景图像和背景图像。我的实现的输出似乎与期望的不一致。有什么想法吗?提前谢谢!如果有人能告诉我如何解决这个问题,我将不胜感激 我的输出: 对于图1- 对于图2- 我的代码: im1=imread('D:\root-image.pgm'); % im1=rgb2gray(im1); [n,m]=size(im1); hst=imhist(im1); mu=zeros(255,1); N=0; for i=1:255 N=N+hst(i);
im1=imread('D:\root-image.pgm');
% im1=rgb2gray(im1);
[n,m]=size(im1);
hst=imhist(im1);
mu=zeros(255,1);
N=0;
for i=1:255
N=N+hst(i);
end
% The total mean level of the original image
for i=1:255
mu(i)=mu(i)+((i.*hst(i))./N);
end
for T=1:254
qb=0;
muT=0;
qo=0;
for i=1:T
qb=qb+(hst(i)./N); % probability of class occurence (background)
m=m+((i.*hst(i))./N);% probability of class mean (background)
end
for i=T+1:255
qo=qo+(hst(i)./N);% probability of class occurence (object)
end
sigma(T)=((mu(T)-(qb*muT))^2)/(qb*qo);
end
[Y,T] = max(sigma);
[n,m]=size(im1);
for i=1:n
for j=1:m
if im1(i,j)>T
im(i,j)=1;
else
im(i,j)=0;
end
end
end
figure(1);
subplot(1,2,1);
imshow(im1);
% subplot(1,3,2);
% imhist(im1);
subplot(1,2,2);
imshow(im);
您的代码存在一些问题,我将概述错误之处:
sigma
声明,以便有256个元素,而不是255个。请记住,图像中有256种可能的强度for
循环中,当计算类出现的概率时,还需要检查强度0。因为MATLAB从1开始索引数组,所以需要偏移访问索引,以便从1开始qb
和qo
,而不是N
m
计算平均值,然后将其存储在muT
中hst=imhist(im1);
sigma = zeros(256,1); %// Change
N = numel(im1); %// Change
for T=0:255 %// Change
qb=0;
muT=0;
qo=0;
muQ=0; %// Change
for i=0:T %// Change
qb=qb+(hst(i+1)./N); % probability of class occurence (background)
end
for i=T+1:255
qo=qo+(hst(i+1)./N);% probability of class occurence (object)
end
for i=0:T%// Change
muT=muT+((i.*hst(i+1))./qb);% probability of class mean (background)
end
for i=T+1:255 %// Change
muQ=muQ+((i.*hst(i+1))./qo);% probability of class mean (object)
end
sigma(T+1) = qb*qo*((muT-muQ)^2); %// Change
end
[Y,T] = max(sigma);
T = T-1; %// Change - For 0 to 255
这段代码现在应该可以工作了。我用自己的大津实现运行了这段代码,得到了相同的计算阈值。老实说,我发现这段代码效率很低,因为有许多
for
循环。我个人会做的是将其矢量化,但我将把它留给您作为一个学习练习:)
编辑 好吧,我会让步的。下面是我为大津编写的一些代码,这些代码更加矢量化。这基本上执行了上面所做的操作,但以更矢量化的方式执行。您完全可以出于自己的目的使用它,但如果您打算使用它,请务必引用我的话:)
Divakar编辑 Divakar(谢谢!)创建了矢量化代码来替换上述函数代码的循环部分,这基本上消除了
s_b
的预分配:
w_0 = cumsum(pdf);
w_1 = 1 - w_0;
u_0 = cumsum((0:L-1)'.*pdf)./w_0;
u_1 = flipud([0 ; cumsum((L-1:-1:1)'.*pdf((L:-1:2)))])./w_1;
s_b = w_0.*w_1.*((u_1 - u_0).^2);
@James你为什么想要递归实现?我想它会比上面的代码运行得快,而我的实际需求是写一个大津的递归代码。当然!这将是一个真正的挑战help@James-完成!去看看吧。请注意,您正在执行的许多操作都可以通过一两行代码来简化。无论我在哪里使用它,我都会引用您。
w_0 = cumsum(pdf);
w_1 = 1 - w_0;
u_0 = cumsum((0:L-1)'.*pdf)./w_0;
u_1 = flipud([0 ; cumsum((L-1:-1:1)'.*pdf((L:-1:2)))])./w_1;
s_b = w_0.*w_1.*((u_1 - u_0).^2);