Что такое быстрый и надежный способ создания пороговых изображений с возможной размытой и неравномерной яркостью?
Пример (размытие, но равномерная яркость):
Поскольку изображение не гарантирует равномерной яркости, нецелесообразно использовать фиксированный порог. Адаптивный порог работает хорошо, но из-за размытости он создает разрывы и искажения в функциях (здесь важными особенностями являются цифры судоку):
Я также попытался использовать выравнивание гистограммы (используя функцию OpenCV equalizeHist
). Это увеличивает контраст, не уменьшая различия в яркости.
Лучшее решение, которое я нашел, состоит в том, чтобы разделить изображение на его морфологическое закрытие (кредит этот пост), чтобы сделать однородность яркости, затем перенормировать, а затем использовать фиксированный порог (с использованием алгоритма Otsu для выбора оптимального порогового уровня):
Вот код для этого в OpenCV для Android:
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));
Mat closed = new Mat(); // closed will have type CV_32F
Imgproc.morphologyEx(image, closed, Imgproc.MORPH_CLOSE, kernel);
Core.divide(image, closed, closed, 1, CvType.CV_32F);
Core.normalize(closed, image, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);
Imgproc.threshold(image, image, -1, 255, Imgproc.THRESH_BINARY_INV
+Imgproc.THRESH_OTSU);
Это отлично работает, но операция закрытия очень медленная. Уменьшение размера структурирующего элемента увеличивает скорость, но снижает точность.
Изменить: на основе предложения DCS я попытался использовать фильтр верхних частот. Я выбрал фильтр Лапласа, но ожидал бы аналогичных результатов с фильтрами Sobel и Scharr. Фильтр захватывает высокочастотный шум в областях, которые не содержат признаков, и страдает от подобного искажения адаптивного порога из-за размытия. это также занимает примерно столько же времени, сколько и операция закрытия. Вот пример с фильтром 15x15:
Изменить 2: на основе ответа AruniRC я использовал обнаружение края Canny на изображении с предлагаемыми параметрами:
double mean = Core.mean(image).val[0];
Imgproc.Canny(image, image, 0.66*mean, 1.33*mean);
Я не уверен, как надежно автоматически настроить параметры для подключения цифр.