При фотографировании листа бумаги (например, с помощью камеры телефона) я получаю следующий результат (левое изображение) (jpg скачать здесь). Желаемый результат (обработанный вручную с помощью программного обеспечения для редактирования изображений) справа:
Я хотел бы обработать исходное изображение с помощью openCV, чтобы автоматически получить лучшую яркость/контрастность (чтобы фон был более белым).
Предположение: изображение имеет портретный формат А4 (нам не нужно перетягивать его в этой теме здесь), а лист бумаги белый с возможным текстом/изображениями черного или цветного изображения.
Что я пробовал до сих пор:
-
Различные адаптивные методы определения порога, такие как Gaussian, OTSU (см. OpenCV doc Image Thresholding). Обычно это хорошо работает с OTSU:
ret, gray = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)
но он работает только для изображений в градациях серого, а не для цветных изображений. Кроме того, вывод является двоичным (белым или черным), что мне не нужно: я предпочитаю сохранять цветное недвоичное изображение в качестве вывода
-
- применяется к Y (после преобразования RGB => YUV)
- или применяется к V (после преобразования RGB => HSV),
как это было предложено этим ответом (уравнивание Гистограмма не работает на цветном изображении - OpenCV) или этого одного (OpenCV Python equalizeHist цветные изображения):
img3 = cv2.imread(f) img_transf = cv2.cvtColor(img3, cv2.COLOR_BGR2YUV) img_transf[:,:,0] = cv2.equalizeHist(img_transf[:,:,0]) img4 = cv2.cvtColor(img_transf, cv2.COLOR_YUV2BGR) cv2.imwrite('test.jpg', img4)
или с HSV:
img_transf = cv2.cvtColor(img3, cv2.COLOR_BGR2HSV) img_transf[:,:,2] = cv2.equalizeHist(img_transf[:,:,2]) img4 = cv2.cvtColor(img_transf, cv2.COLOR_HSV2BGR)
К сожалению, результат довольно плохой, поскольку он создает ужасные микроконтрасты локально (?):
Я также попробовал YCbCr вместо этого, и это было похоже.
-
Я также попробовал CLAHE (эквалайзер с ограниченной адаптивной гистограммой) с различными
tileGridSize
от1
до1000
:img3 = cv2.imread(f) img_transf = cv2.cvtColor(img3, cv2.COLOR_BGR2HSV) clahe = cv2.createCLAHE(tileGridSize=(100,100)) img_transf[:,:,2] = clahe.apply(img_transf[:,:,2]) img4 = cv2.cvtColor(img_transf, cv2.COLOR_HSV2BGR) cv2.imwrite('test.jpg', img4)
но результат был одинаково ужасен.
-
Выполнение этого метода CLAHE с цветовым пространством LAB, как предлагается в вопросе Как применять CLAHE на цветных изображениях RGB:
import cv2, numpy as np bgr = cv2.imread('_example.jpg') lab = cv2.cvtColor(bgr, cv2.COLOR_BGR2LAB) lab_planes = cv2.split(lab) clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(100,100)) lab_planes[0] = clahe.apply(lab_planes[0]) lab = cv2.merge(lab_planes) bgr = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR) cv2.imwrite('_example111.jpg', bgr)
дал плохой результат тоже. Выходное изображение:
-
Адаптивное выравнивание порогового значения или выравнивание гистограммы отдельно для каждого канала (R, G, B) не вариант, поскольку это может привести к нарушению цветового баланса, как описано здесь.
-
Метод "Contrast strechting" из
scikit-image
по выравниванию гистограммы:изображение масштабируется, чтобы включить все интенсивности, которые попадают во 2-й и 98-й процентили
немного лучше, но все еще далек от желаемого результата (см. изображение в верхней части этого вопроса).
TL; DR: как получить автоматическую оптимизацию яркости/контрастности цветной фотографии листа бумаги с помощью OpenCV/Python? Какой вид порогового/выравнивания гистограммы/другой метод можно использовать?