Я хотел бы сказать, что это не алгоритм Niblack, а реализация, которая дает лучший результат. Я не знаю, где эта реализация потерпит неудачу, но я попытался преобразовать изображение в двоичную форму выше, и результат, как показано ниже.
![Binarized grains](https://i.stack.imgur.com/xHzSJ.jpg)
Я разделил изображение на блок 25 * 25 пикселей, а затем использовал глобальное среднее значение 90 и глобальное среднее значение 20. Затем применил бинаризацию Оцу к маленьким окнам.
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) небольшого окна больше установленного, то используется пороговое значение отсу, в зависимости от того, является ли среднее значение большим или меньшим, чем установленное среднее значение, пиксели в окне устанавливаются как черные или белый.