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

Очистка изображения captcha

captcha image

Я пытаюсь очистить изображение выше. Я пробовал несколько разных методов, используя open cv, я слишком сильно разрушаю исходное изображение до такой степени, когда части букв теряются, например, ниже:

результат эрозии через python opencv 3

Я не совсем уверен, как избавиться от последней диагональной линии и исправить S, мой код до сих пор:

import cv2 
import matplotlib.pylab as plt
img = cv2.imread('/captcha_3blHDdS.png')

#make image gray 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#Blur
blur = cv2.GaussianBlur(gray,(5,5),0)
bilateral = cv2.bilateralFilter(gray,5,75,75)

#Thresholding
ret, thresh = cv2.threshold(bilateral,25,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

#Kernal
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

#other things
erosion = cv2.erode(thresh,kernel,iterations = 1)
closing = cv2.morphologyEx(erosion, cv2.MORPH_CLOSE, kernel, iterations = 1)

#Transform image
dist_transform = cv2.distanceTransform(closing,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.02*dist_transform.max(),255,cv2.THRESH_BINARY)#,255,0)

#kernel_1
kernel_1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (1, 2))

dilation_1 = cv2.dilate(sure_fg,kernel_1,iterations = 2)
erosion_1 = cv2.erode(dilation_1,kernel_1,iterations = 3)

plt.imshow(erosion_1, 'gray')

Любая помощь будет принята с благодарностью. Ниже приведены примеры типов изображений, созданных с помощью captcha; пример изображений captcha

также ссылается на папку, содержащую изображения

4b9b3361

Ответ 1

Вот решение С#, используя OpenCvSharp (что должно быть легко преобразовать обратно в python/С++, потому что имена методов - это точно то же самое).

Он использует метод OpenCV inpainting, чтобы избежать слишком большого количества писем, прежде чем, возможно, запустил этап OCR. Мы можем видеть, что линии имеют другой цвет, чем остальные, поэтому мы будем использовать эту информацию очень рано, прежде чем любой оттенок серого/черный. Шаги следующие:

  • создайте маску из линий, используя свой цвет (# 707070)
  • расширение, которое маскирует немного, потому что линии, возможно, были нарисованы с помощью сглаживания
  • перерисовать ( "inpaint" ) исходное изображение, используя эту маску, которая удалит строки, сохранив большую часть того, что было ниже строк (букв). Заметьте, что мы могли бы удалить небольшие точки до этого шага, я думаю, что было бы еще лучше
  • примените некоторое расширение/размытие/порог для завершения

Вот маска:

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

Вот результат:

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

Вот результат на выборке:

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

Вот код С#:

static void Decaptcha(string filePath)
{
    // load the file
    using (var src = new Mat(filePath))
    {
        using (var binaryMask = new Mat())
        {
            // lines color is different than text
            var linesColor = Scalar.FromRgb(0x70, 0x70, 0x70);

            // build a mask of lines
            Cv2.InRange(src, linesColor, linesColor, binaryMask);
            using (var masked = new Mat())
            {
                // build the corresponding image
                // dilate lines a bit because aliasing may have filtered borders too much during masking
                src.CopyTo(masked, binaryMask);
                int linesDilate = 3;
                using (var element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(linesDilate, linesDilate)))
                {
                    Cv2.Dilate(masked, masked, element);
                }

                // convert mask to grayscale
                Cv2.CvtColor(masked, masked, ColorConversionCodes.BGR2GRAY);
                using (var dst = src.EmptyClone())
                {
                    // repaint big lines
                    Cv2.Inpaint(src, masked, dst, 3, InpaintMethod.NS);

                    // destroy small lines
                    linesDilate = 2;
                    using (var element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(linesDilate, linesDilate)))
                    {
                        Cv2.Dilate(dst, dst, element);
                    }

                    Cv2.GaussianBlur(dst, dst, new Size(5, 5), 0);
                    using (var dst2 = dst.BilateralFilter(5, 75, 75))
                    {
                        // basically make it B&W
                        Cv2.CvtColor(dst2, dst2, ColorConversionCodes.BGR2GRAY);
                        Cv2.Threshold(dst2, dst2, 255, 255, ThresholdTypes.Otsu);

                        // save the file
                        dst2.SaveImage(Path.Combine(
                            Path.GetDirectoryName(filePath),
                            Path.GetFileNameWithoutExtension(filePath) + "_dst" + Path.GetExtension(filePath)));
                    }
                }
            }
        }
    }
}

Ответ 2

Присмотритесь к вашему captcha. большая часть пыли в этом изображении имеет другое значение оттенков серого, чем текст.

Текст находится в 140, а пыль находится в 112.

Простая фильтрация в оттенках серого поможет здесь много.

from scipy.misc import imread, imsave
import numpy as np

infile = "A1nO4.png"
outfile = "A1nO4_out.png"

im = imread(infile, True)
out_im = np.ones(im.shape) * 255

out_im[im == 140] = 0

imsave(outfile, out_im)

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

Теперь используйте cv2.dilate (cv2.erode на белом черном тексте), чтобы избавиться от оставшейся пыли.

Ответ 3

Это не очень надежное решение, но в большинстве случаев это может быть полезно:

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