我正在尝试实现使用以下公式的 niblack 阈值算法:
pixel = ( pixel > mean + k * standard_deviation ) ? object : background
其中k的标准值为0。有人可以告诉我如何在matlab中实现这个吗?我不知道该怎么做
我正在尝试实现使用以下公式的 niblack 阈值算法:
pixel = ( pixel > mean + k * standard_deviation ) ? object : background
其中k的标准值为0。有人可以告诉我如何在matlab中实现这个吗?我不知道该怎么做
Matlab 的强大之处在于矩阵运算,因此您可以在没有单个 for 循环的情况下做很多事情。下面的代码可以满足您的需要。
% define parameters
imgname = 'rice.png'; % matlab's image
filt_radius = 25; % filter radius [pixels]
k_threshold = 0.2; % std threshold parameter
%% load the image
X = double(imread(imgname));
X = X / max(X(:)); % normalyze to [0, 1] range
%% build filter
fgrid = -filt_radius : filt_radius;
[x, y] = meshgrid(fgrid);
filt = sqrt(x .^ 2 + y .^ 2) <= filt_radius;
filt = filt / sum(filt(:));
%% calculate mean, and std
local_mean = imfilter(X, filt, 'symmetric');
local_std = sqrt(imfilter(X .^ 2, filt, 'symmetric'));
%% calculate binary image
X_bin = X >= (local_mean + k_threshold * local_std);
%% plot
figure; ax = zeros(4,1);
ax(1) = subplot(2,2,1); imshow(X); title('original image');
ax(2) = subplot(2,2,2); imshow(X_bin); title('binary image');
ax(3) = subplot(2,2,3); imshow(local_mean); title('local mean');
ax(4) = subplot(2,2,4); imshow(local_std); title('local std');
linkaxes(ax, 'xy');
我想说的是,它不是 Niblack 算法,而是一种能够提供更好结果的实现。我不知道这个实现会在哪里失败,但我尝试对上面的图像进行二值化,结果如下。
我将图像分成 25*25 像素块,然后使用 90 的全局设置平均值和 20 的全局设置平均值。然后在小窗口上应用 Otsu 的二值化。
set_mean = 90
set_sd = 20
mean_block = np.mean(block)
sd_block = np.std(block)
if sd_block > set_sd:
ret, block = cv2.threshold(block, 0, 255, cv2.THRESH_OTSU)
elif sd_block < set_sd:
if mean_block > set_mean:
block[:] = 255 #white
else:
block[:] = 0 #black
return block
如果小窗口的标准差(SD)大于设定的标准差,则使用 otsu 的阈值,否则根据均值是否大于或小于设定的均值,将窗口中的像素设置为全黑或全白。
您可以处理整个图像:假设您有三个矩阵:img_in、object、background
flag = img_in > mean + k * standard_deviation;
img_out = flag .* object + (1 - flag) .* background;