python image opencv computer-vision captcha

python - selenium captcha c#



Limpiando imagen captcha (3)

Aquí hay una solución de C # que usa OpenCvSharp (que debería ser fácil de volver a convertir a python / c ++ porque los nombres de los métodos son exactamente iguales).

Utiliza la técnica de inpainting de OpenCV para evitar destruir demasiadas letras antes de ejecutar una fase de OCR. Podemos ver que las líneas tienen un color diferente al resto, por lo que usaremos esa información muy pronto, antes de cualquier escalado de grises / negro blanco. Los pasos son los siguientes:

  • construir una máscara a partir de las líneas utilizando su color (# 707070)
  • dilata esa máscara un poco porque las líneas pueden haber sido dibujadas con antialiasing
  • vuelva a pintar ("pintar") la imagen original con esta máscara, que eliminará las líneas y conservará la mayor parte de lo que había debajo de las líneas (letras). Tenga en cuenta que podríamos eliminar los puntos pequeños antes de ese paso, creo que sería aún mejor
  • aplicar algunos dilatar / difuminar / umbral para finalizar

Aquí está la máscara:

Aquí está el resultado:

Aquí está el resultado en el conjunto de muestra:

Aquí está el código 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))); } } } } } }

Estoy tratando de limpiar la imagen de arriba. He intentado varios métodos diferentes utilizando cv abierto. O bien, erosiono la imagen original demasiado hasta el punto en que faltan partes de las letras, como a continuación:

No estoy seguro de cómo deshacerme de la última línea diagonal y reparar la S, mi código hasta ahora es:

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

Cualquier ayuda sería muy apreciada. Aquí hay más ejemplos del tipo de imágenes que se producen desde el captcha;

También aquí está el enlace a una carpeta que contiene las images


Echa un vistazo más de cerca a tu captcha. la mayor parte del polvo en esa imagen tiene un valor de escala de grises diferente al del texto.

El texto está en 140 y el polvo en 112 .

Un simple filtro de escala de grises ayudará mucho aquí.

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)

Ahora use cv2.dilate ( cv2.erode en un texto blanco sobre negro) para deshacerse del polvo restante.


Esta no es una solución muy robusta, pero podría ser una ayuda completa en la mayoría de los casos:

Al ver la muestra de la imagen publicada arriba, puedo observar una característica común acerca de las líneas diagonales que comienzan o terminan en los bordes de la imagen, mientras que el texto que nos interesa está en el medio, de esta manera podemos determinar los valores de píxeles de esas líneas diagonales al buscarlas en las primeras y últimas filas y columnas de la matriz de la imagen y eliminarlas como ruido. Y este enfoque también podría costar menos tiempo.