Подтвердить что ты не робот

Как получить эффект Magic Color, например, Cam Scanner, используя OpenCV

Это исходное изображение.

Оригнальное изображение

Cam Scanner Магический эффект цвета Эффект сканера Cam

Мой фильтр на изображении.

Мой фильтр

Я меняю контраст изображения.

dst.convertTo(dst, -1, 2, 0);

Затем, используя гауссовское размытие для сглаживания.

cv::GaussianBlur(dst,result,cv::Size(0,0),3);
cv::addWeighted(dst, 1.5, result, -0.5, 0, result);

Что мне делать, чтобы добиться такого эффекта на моем изображении?

UPDATE

После выравнивания гистограммы -

vector<Mat> channels;
Mat img_hist_equalized;
cvtColor(dst, img_hist_equalized, CV_BGR2YCrCb);
split(img_hist_equalized,channels);
equalizeHist(channels[0], channels[0]);
merge(channels,img_hist_equalized);
cvtColor(img_hist_equalized, img_hist_equalized, CV_YCrCb2BGR);

Уравнивание гистограммы

4b9b3361

Ответ 1

Приложение для каскадеров может использовать какой-то сложный алгоритм для обработки различных случаев молнии и т.д. Но я попытаюсь осветить базовый подход к такой проблеме. Основная идея здесь - Бинаризация данного ввода image, или, точнее, мы можем сказать Порог заданное изображение. Если вы посмотрите на документацию OpenCV, существует множество ссылок на пороговое значение данного изображения. Поэтому давайте начнем с документация.

  • Глобальный порог. В этом подходе мы предполагаем, что значение интенсивности переднего плана всегда ниже определенного значения. В контексте печатных листов мы предполагаем, что цвет чернил всегда черный и цвет бумаги является однородным, а интенсивность больше, чем интенсивность цвета чернил, поэтому мы надежно принимаем некоторый порог (скажем, 40), (макс. 255) и порог входного изображения как:

    ret, thresh1 = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)
    

    введите описание изображения здесь

    ret, thresh1 = cv2.threshold(img, 130, 255, cv2.THRESH_BINARY)
    

    введите описание изображения здесь

    Существует много недостатков этого метода: во-первых, он НЕ не зависит от дисперсии интенсивности. Поэтому вероятность того, что вы можете точно оценить пороговое значение, которое отделяет текст от данного изображение, оно имеет очень ограниченные приложения, может применяться только в том случае, если фоновая бумага точно белая с минимальным изменением интенсивности, поэтому этот процесс нельзя использовать для изображений Real world.

  • Адаптивное пороговое значение. Этот метод охватывает проблему изменения интенсивности в данном изображении, здесь пороговое значение выполняется для значений соседних пикселей, поэтому переходы от меньшей интенсивности к высшей и наоборот успешно захвачены этим методом как:

    thresh = cv2.adaptiveThreshold(original_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
    

    введите описание изображения здесь

    Дальнейшая работа. Вы можете работать с различными методами шумоподавления двоичного изображения, удалять точки, или посмотреть на удаление соляных и перцовых шумов с изображения.

  • Бинаризация Otu. Это еще один приятный подход, который интеллектуально вычисляет пороговое значение между максимами. В некоторых случаях он может работать очень хорошо, но, похоже, ваш случай.

    ret2,thresh = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    

    введите описание изображения здесь

В основном он делает то же самое глобальное пороговое значение. Но теперь пороговое значение рассчитывается автоматически таким образом, что порог лежит между 2 пиками и, следовательно, сегментирует чернила из бумаги.

Рекомендуемый метод: Я думаю, что наилучшим подходом для начала является Adaptive Thresholding, вы можете попробовать некоторые другие методы предварительной обработки, такие как резкость изображения, Уравнивание гистограммы и т.д. и проанализируйте, как он создает более реалистичный вывод. Вы также можете попытаться выполнить некоторую пост-обработку, такую ​​как шумоподавление изображения, Морфологические операции

Я попытался разобрать изображение и нашел его более эффективным для других подходов,

denoised = cv2.fastNlMeansDenoising(thresh, 11, 31, 9) # you may experiment with the constants here

введите описание изображения здесь

Но я приветствую вас, чтобы попробовать различные комбинации вышеупомянутых подходов, чтобы посмотреть, какой из них работает для всех случаев.

Ответ 2

Я написал код, который делает такие вещи, хотя не с OpenCV.

Как правило, я анализировал гистограмму, подсчитал, какие "белые" и "черные" основаны на гистограмме, а затем масштабируйте значения изображений, чтобы черный был масштабирован ниже 0, а белый был масштабирован выше 1 (или 255 в зависимости от ваше представление), наконец, зажатие значений цвета.

Однако с OpenCV может быть проще. Попробуйте использовать выравнивание гистограммы на вашей обрезанной странице перед применением контрастного фильтра - это должно более распространять значения пикселей, чтобы корректировать контрастность более надежно в других ситуациях. Вы можете попробовать использовать выравнивание гистограммы локализованного, чтобы помочь уменьшить градиенты на обрезанном изображении из-за освещения, но это может вызвать проблемы с пустыми областями страницы.

Ответ 3

Я понимаю, что немного опаздываю в игру, но я нашел это простое и простое решение:

src.convertTo(dst, -1, 1.9, -80);

src и dst могут быть одним и тем же изображением, если вы работаете в конвейере обработки.