清理验证码图像

use*_*569 21 python captcha opencv image computer-vision

验证码图像

我正在尝试清理上面的图像我已经尝试了几种使用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')
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激,以下是更多从验证码产生的图像类型的例子; 验证码图像的示例

还包含指向包含图像的文件夹的链接

Sim*_*ier 22

这是一个使用OpenCvSharp的C#解决方案(应该很容易转换回python/c ++,因为方法名称完全相同).

它使用OpenCV的修复技术,以避免在可能运行OCR阶段之前破坏过多的字母.我们可以看到线条的颜色与其他颜色不同,所以我们会在任何灰度/黑白之前很早就使用这些信息.步骤如下:

  • 使用颜色从线条构建蒙版(#707070)
  • 因为线条可能已经用抗锯齿绘制而扩大了一点掩盖
  • 使用此蒙版重绘("inpaint")原始图像,这将删除线条,同时保留线条(字母)下方的大部分内容.注意我们可以该步骤之前删除小点,我认为它会更好
  • 应用一些扩张/模糊/阈值来完成

这是面具:

在此输入图像描述

结果如下:

在此输入图像描述

以下是样本集的结果:

在此输入图像描述

这是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)));
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常优雅的解决方案和创新方法. (3认同)
  • 确实是优雅的解决方案!如果有人在 python 中需要相同的实现,我已经创建了一个要点 - https://gist.github.com/nirajpandkar/887ac6e95db3920382718095dc82e582 (2认同)

Ghi*_*ADJ 7

仔细看看你的验证码.该图像中的大部分灰尘具有与文本不同的灰度值.

文字在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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

现在使用cv2.dilate(cv2.erode在黑色文本上的白色)去除剩余的灰尘.

  • 当我尝试`findContours`和`boundingRect`时,不会创建会导致问题的单独区域 (2认同)
  • 是的,您不能使用`findContours`和`boundingRect`来获取字母,但您至少可以使用它们来删除小斑点. (2认同)

fla*_*ite 5

这不是一个非常可靠的解决方案,但在大多数情况下可能会有所帮助:

通过查看上面发布的图像样本,我可以观察到对角线的一个共同特征,即对角线在图像边缘处开始或结束,而我们感兴趣的文本位于中间,因此我们可以确定的像素值通过在图像矩阵的前几行和后几​​行中搜索这些对角线,并消除它们作为噪声。而且这种方法也可能减少时间花费。