Первым шагом является выравнивание различий в освещении изображения с учетом проблем с балансом белого.Теория здесь состоит в том, что самая яркая часть изображения в пределах ограниченной области представляет белый цвет.За счет размытия изображения заранее мы исключаем влияние шума на изображение.
from PIL import Image
from PIL import ImageFilter
im = Image.open(r'c:\temp\temp.png')
white = im.filter(ImageFilter.BLUR).filter(ImageFilter.MaxFilter(15))
Следующим шагом является создание полутонового изображения на входе RGB.Масштабируя до белой точки, мы исправляем проблемы с балансом белого.Взяв максимум R, G, B, мы преуменьшаем любой цвет, который не является чисто серым, например синие линии сетки.Первая строка кода, представленная здесь, является фиктивной, для создания изображения правильного размера и формата.
grey = im.convert('L')
width,height = im.size
impix = im.load()
whitepix = white.load()
greypix = grey.load()
for y in range(height):
for x in range(width):
greypix[x,y] = min(255, max(255 * impix[x,y][0] / whitepix[x,y][0], 255 * impix[x,y][2] / whitepix[x,y][3], 255 * impix[x,y][4] / whitepix[x,y][5]))
Результатом этих операций является изображение, которое имеет в основном согласованные значения и может быть преобразовано в черныйи белый через простой порог.
Редактировать: Приятно видеть небольшое соревнование. nikie предложил очень похожий подход, использующий вычитание вместо масштабирования для удаления изменений уровня белого.Мой метод увеличивает контраст в регионах с плохим освещением, а метод Ники - нет - какой метод вы предпочитаете, будет зависеть от того, есть ли в плохо освещенных областях информация, которую вы хотите сохранить.
Моя попытка воссоздатьэтот подход привел к следующему:
for y in range(height):
for x in range(width):
greypix[x,y] = min(255, max(255 + impix[x,y][0] - whitepix[x,y][0], 255 + impix[x,y][7] - whitepix[x,y][8], 255 + impix[x,y][9] - whitepix[x,y][10]))
Я работаю над сочетанием методов для достижения еще лучшего результата, но он еще не совсем готов.