Алгоритм удаления битых пикселей из букв

Рейтинг: 2Ответов: 1Опубликовано: 12.09.2014

Добрый день.

Есть вот такие картинки:

http://cdn.joxi.ru/uploads/prod/2014/09/12/42c/58d/6262f90e63c4b76fdeb27a6dd1d18b336663d92f.jpg

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

Ответы

▲ 2

Можно попробовать применить алгоритм Тана-Триггса (Tan-Triggs). В OpenCV я встречал его использование для снижения вариативности освещённости при распознавании лиц, но и в обозначенной задаче он, на мой взгляд, может помочь.

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

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

Сам алгоритм довольно быстрый и не требует какого-либо обучения:

Mat tan_triggs_preprocessing(InputArray src
    , float alpha = 0.1, float tau = 10.0, float gamma = 0.2
    , int sigma0 = 1, int sigma1 = 2) {

    Mat X = src.getMat();
    X.convertTo(X, CV_32FC1);

    Mat I;
    pow(X, gamma, I);

    // Calculate the DOG Image:
    {
        Mat gaussian0, gaussian1;

        // Kernel Size:
        int kernel_sz0 = (3*sigma0);
        int kernel_sz1 = (3*sigma1);

        // Make them odd for OpenCV:
        kernel_sz0 += ((kernel_sz0 % 2) == 0) ? 1 : 0;
        kernel_sz1 += ((kernel_sz1 % 2) == 0) ? 1 : 0;
        GaussianBlur(I, gaussian0, Size(kernel_sz0,kernel_sz0)
            , sigma0, sigma0, BORDER_CONSTANT);
        GaussianBlur(I, gaussian1, Size(kernel_sz1,kernel_sz1)
            , sigma1, sigma1, BORDER_CONSTANT);
        subtract(gaussian0, gaussian1, I);
    }

    {
        double meanI = 0.0;
        {
            Mat tmp;
            pow(abs(I), alpha, tmp);
            meanI = mean(tmp).val[0];

        }

        I = I / pow(meanI, 1.0/alpha);
    }

    {
        double meanI = 0.0;
        {
            Mat tmp;
            pow(min(abs(I), tau), alpha, tmp);
            meanI = mean(tmp).val[0];
        }

        I = I / pow(meanI, 1.0/alpha);
    }

    // Squash into the tanh:
    {
        for(int r = 0; r < I.rows; r++) {
            for(int c = 0; c < I.cols; c++) {
                I.at<float>(r,c) = tanh(I.at<float>(r,c) / tau);
            }
        }
        I = tau * I;
    }

    return I;
}

Использовать просто:

Mat src_mat = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat dst_mat = tan_triggs_preprocessing(src_mat);
normalize(dst_mat, dst_mat, 0, 255, NORM_MINMAX, CV_8UC1);

Mat res_mat = src_mat - dst_mat;

imshow("TanTriggs Image", res_mat);