Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

niblack thresholding

I am trying to implement the niblack thresholding algorithm which uses the formula:

pixel = ( pixel >  mean + k * standard_deviation ) ? object : background

where k has standard value 0. Could someone please tell me how to implement this in matlab? I cant figure out how to do it

like image 296
NeedHelp Avatar asked May 04 '26 12:05

NeedHelp


2 Answers

The power of Matlab is matrix operations, so you can do a lot without a single for-loop. The code below does what you need.

% 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');

enter image description here

like image 196
Serg Avatar answered May 07 '26 09:05

Serg


I would like to say upfront it is not Niblack algorithm but rather an implementation that gives better result. I don't know where this implementation will fail but I tried to binarize the above image and the result is as below.

Binarized grains

I divided the image up into 25*25 pixels block and then used a global set mean of 90 and global set mean of 20. And then applied Otsu's binarization on small windows.

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

If the small window's standard deviation(SD) is greater than the set one, then otsu's thresholding is used, else based on whether the mean is greater or smaller than set mean, the pixels in the window are set to complete black or white.

like image 34
hlkstuv_23900 Avatar answered May 07 '26 08:05

hlkstuv_23900



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!