简体   繁体   English

清理验证码图像

[英]Cleaning up captcha image

验证码图片

I'm trying to clean up the image above I've tried several different methods using open cv, I either erode the original image too much to the point where parts of the letters become missing such as below:我正在尝试清理上面的图像我已经尝试了几种使用 open cv 的不同方法,我要么过度侵蚀原始图像,以至于部分字母丢失,如下所示:

通过python opencv 3侵蚀的结果

I'm not really sure sure how to get rid of the last diagonal line and repair the S, my code so far is:我不太确定如何去掉最后一条对角线并修复 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')

Any help would be greatly appreciated, Here are more examples of the type of images that are produced from the captcha;任何帮助将不胜感激,这里有更多由验证码生成的图像类型的示例; 验证码图像示例

also heres the link to a folder containing the images也是包含图像的文件夹的链接

Here is a C# solution using OpenCvSharp (which should be easy to convert back to python/c++ because the method names are exactly the same).这是一个使用OpenCvSharp的 C# 解决方案(它应该很容易转换回 python/c++,因为方法名称完全相同)。

It uses OpenCV'sinpainting technique to avoid destroying too much of the letters before possibly running an OCR phase.它使用 OpenCV 的修复技术来避免在可能运行 OCR 阶段之前破坏太多字母。 We can see that the lines have a different color than the rest, so we'll use that information very early, before any grayscaling/blackwhiting.我们可以看到线条的颜色与其他线条不同,因此我们将在任何灰度/黑白色之前尽早使用该信息。 Steps are as follow:步骤如下:

  • build a mask from the lines using their color (#707070)使用它们的颜色从线条构建蒙版 (#707070)
  • dilate that mask a bit because the lines may have been drawn with antialiasing稍微扩大那个蒙版,因为线条可能是用抗锯齿绘制的
  • repaint ("inpaint") the original image using this mask, which will remove the lines while preserving most of what was below the lines (letters).使用此蒙版重新绘制(“修复”)原始图像,这将删除线条,同时保留线条下方的大部分内容(字母)。 Note we could remove the small points before that step, I think it would be even better请注意我们可以该步骤之前删除小点,我认为它会更好
  • apply some dilate/blur/threshold to finalize应用一些扩张/模糊/阈值来完成

Here is the mask:这是面具:

在此处输入图片说明

Here is the result:结果如下:

在此处输入图片说明

Here is the result on sample set:这是样本集的结果:

在此处输入图片说明

Here is the C# code:这是 C# 代码:

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)));
                    }
                }
            }
        }
    }
}

Take a closer look to your captcha.仔细看看你的验证码。 most of the dust in that image has a different grayscale value than the text.该图像中的大部分灰尘具有与文本不同的灰度值。

The text is in 140 and the dust is in 112 .文字在140 ,灰尘在112

A simple grayscale filtering will help a lot here.一个简单的灰度过滤在这里会有很大帮助。

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)

在此处输入图片说明

Now use cv2.dilate ( cv2.erode on a white on black text) to get rid of the remaining dust.现在使用cv2.dilate ( cv2.erode on a white on black text) 去除剩余的灰尘。

This is not a very robust solution but it might be help full in most of the cases:这不是一个非常强大的解决方案,但在大多数情况下可能会有所帮助:

By seeing the image sample posted above i can observe one common feature about the diagonal lines that they either start or end at the image edges while the text which we are interested in are in the middle so in this way we can determine the pixel values of those diagonal lines by searching them in the first and last few rows and columns of the image matrix and eliminate them as noise.通过查看上面张贴的图像样本,我可以观察到对角线的一个共同特征,它们在图像边缘开始或结束,而我们感兴趣的文本位于中间,因此我们可以通过这种方式确定通过在图像矩阵的前几行和最后几列中搜索这些对角线并将它们作为噪声消除。 And this approach also might be less time costly.而且这种方法也可能花费更少的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM