我已经实现了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);
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);
答案 0 :(得分:3)
您的代码存在一些问题,我将概述它的错误:
numel
来计算像素总数(N
)...它只是更清洁:)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
此代码现在应该可以使用了。我使用自己的Otsu实现运行此代码,并获得相同的计算阈值。说实话,由于许多for
循环,我觉得这段代码效率很低。我个人会做的是对它进行矢量化,但我会把它作为一个学习练习留给你:)
好的,我会放弃。这是我为Otsu写的一些代码,它更加向量化。这基本上执行了您正在执行的操作,但是以更加矢量化的方式执行。非常欢迎您将它用于您自己的目的,但如果您打算使用它,请引用我:)
%// Function that performs Otsu's adaptive bimodal thresholding
%// Written by Raymond Phan - Version 1.0
%// Input - im - Grayscale image
%// Output - out - Thresholded image via Otsu
function [out] = otsu(im)
%// Compute histogram
J = imhist(im);
%// Total number of intensities
L = length(J);
%// Some pre-processing stuff
%// Determine total number of pixels
num_pixels = sum(J(:));
%// Determine PDF
pdf = J / num_pixels;
%// Storing between-class variances for each intensity
s_b = zeros(1,L);
for idx = 1 : L
%// Calculate w_0
w_0 = sum(pdf(1:idx));
%// Calculate w_1
w_1 = 1 - w_0;
%// Calculate u_0
u_0 = sum((0:idx-1)'.*pdf(1:idx)) / w_0;
%// Calculate u_1
u_1 = sum((idx:L-1)'.*pdf(idx+1:L)) / w_1;
% // Calculate \sigma_b^{2}
s_b(idx) = w_0*w_1*((u_1 - u_0)^2);
end
%// Find intensity that provided the biggest variance
[max_s_b T] = max(s_b);
T = T - 1; %// Must subtract by 1, since the index starts from 1
%// Now create an output image that thresholds the input image
out = im >= T;
end
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);