Адаптивный порог размытого изображения

У меня есть довольно размытое изображение головоломки Sudoku 432x432, которое не адаптивно пороговое значение (возьмите среднее значение над размером блока 5x5 пикселей, а затем вычтите 2):

enter image description here

Как вы можете видеть, цифры слегка искажены, в них много разломов, а несколько 5-х слились в 6 и 6 с в 8 сек. Кроме того, там тонна шума. Чтобы исправить шум, я должен сделать изображение еще более размытым, используя размытие Gaussian. Однако даже довольно большое гауссовское ядро ​​и адаптивный порог blockSize (21x21, вычесть 2) не могут удалить все поломки и еще больше скомпоновать цифры:

enter image description here

Я также попытался расширить изображение после порогового значения, что имеет сходный эффект с увеличением blockSize; и затачивание изображения, что не так много или так. Что еще я должен попробовать?

Ответ 1

Довольно хорошее решение - использовать морфологическое закрытие, чтобы сделать однородность яркости, а затем использовать обычный (неадаптивный) порог Otsu:

// Divide the image by its morphologically closed counterpart
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));
Mat closed = new Mat();
Imgproc.morphologyEx(image, closed, Imgproc.MORPH_CLOSE, kernel);

image.convertTo(image, CvType.CV_32F); // divide requires floating-point
Core.divide(image, closed, image, 1, CvType.CV_32F);
Core.normalize(image, image, 0, 255, Core.NORM_MINMAX);
image.convertTo(image, CvType.CV_8UC1); // convert back to unsigned int

// Threshold each block (3x3 grid) of the image separately to
// correct for minor differences in contrast across the image.
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        Mat block = image.rowRange(144*i, 144*(i+1)).colRange(144*j, 144*(j+1));
        Imgproc.threshold(block, block, -1, 255, Imgproc.THRESH_BINARY_INV+Imgproc.THRESH_OTSU);
    }
}

Результат:

enter image description here

Ответ 2

Взгляните на Сглаживание изображений в учебнике OpenCV. Кроме GaussianBlur существуют также medianBlur и bilateralFilter, которые вы также можете использовать для уменьшения шума. У меня есть это изображение из исходного изображения (вверху справа):

result image

Обновление: И следующее изображение, которое я получил после удаления небольших контуров:

enter image description here

Обновление: также можно затачивать изображение (например, используя Laplacian). Посмотрите эту дискуссию.

Ответ 3

Всегда применяйте гауссово для получения лучших результатов.

cvAdaptiveThreshold(original_image, thresh_image, 255,
            CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 11, 2);