Cleaning up captcha image

前端 未结 3 1497
忘掉有多难
忘掉有多难 2021-02-01 19:12

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

相关标签:
3条回答
  • 2021-02-01 19:46

    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.

    0 讨论(0)
  • 2021-02-01 19:47

    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.

    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.

    0 讨论(0)
  • 2021-02-01 19:52

    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).

    It uses OpenCV's inpainting technique to avoid destroying too much of the letters before possibly running an OCR phase. 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)
    • 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:

    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)));
                        }
                    }
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题