Python Image Processing en Captcha cómo eliminar el ruido

8

Soy muy nuevo en el procesamiento de imágenes y lo que intento hacer es eliminar el ruido de las captchas;

Para captchas, tengo diferentes tipos de ellos:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Para el primero lo que hice es:

Primer paso

ingrese la descripción de la imagen aquí

En primer lugar, convertí cada píxel que no es negro al negro. Luego, encontré un patrón que es un ruido de la imagen y lo eliminé. Para el primer captcha, fue fácil borrarlo y encontré el texto con tesseract.

Pero estoy buscando una solución para el segundo y el tercero.

¿Cómo debe ser esto? Quiero decir, ¿cuáles son los métodos posibles para borrarlo?

Así es como borro patrones:

def delete(searcher,h2,w2):
    h = h2
    w = w2
    search = searcher
    search = search.convert("RGBA")
    herear = np.asarray(search)
    bigar  = np.asarray(imgCropped)

    hereary, herearx = herear.shape[:2]
    bigary,  bigarx  = bigar.shape[:2]

    stopx = bigarx - herearx + 1
    stopy = bigary - hereary + 1

    pix = imgCropped.load()

    for x in range(0, stopx):
        for y in range(0, stopy):
            x2 = x + herearx
            y2 = y + hereary
            pic = bigar[y:y2, x:x2]
            test = (pic == herear)
            if test.all():
                for q in range(h):
                    for k in range(w):
                        pix[x+k,y+q] = (255,255,255,255) 

Perdón por los nombres de las variables, solo estaba probando la función.

Gracias..

Ahmet Aziz Beşli
fuente
2
Estas son tareas bastante pesadas para un único método básico de procesamiento de imágenes, pero puede buscar "patrones muaré" y métodos para eliminarlos. Además, puede utilizar métodos de aprendizaje profundo como la segmentación de texto u obtener una plantilla limpia de la imagen y eliminar cualquier coincidencia en la imagen al correlacionarla.
SajanGohil
@SajanGohil sí, a través del método del patrón, hice algo. Gracias
Ahmet Aziz Beşli

Respuestas:

5

Esto es lo más lejos que puedo llegar:

Probablemente conozca la medianBlurfunción que encuentra el valor medio en cada núcleo y lo sustituye al centro del núcleo. Podemos hacer algo similar a eso, pero en lugar de la mediana, use el valor máximo y luego el valor mínimo. Con una mediana de desenfoque también, obtuve algunos resultados. Sé que no son perfectos, pero espero que te den algunas ideas (puedes jugar con los tamaños de la imagen de entrada y los núcleos, puede mejorar los resultados un poco).

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

No tengo Python instalado ahora, así que comparto el código exacto de C ++ que he usado:

Mat im1 = imread("E:/1/3.jpg", 0);
Mat im2, im3;

im2 = Mat::zeros(im1.size(), CV_8U);
for (size_t i = 1; i < im1.rows-1; i++)
{
    for (size_t j = 1; j < im1.cols-1; j++)
    {
        double minVal, maxVal = 0;
        minMaxIdx(im1(Rect(j - 1, i - 1, 3, 3)), &minVal, &maxVal);
        im2.at<uchar>(i, j) = maxVal;
    }
}

imshow("(1) max bluring", im2);

medianBlur(im2, im2, 3);

imshow("(2) median bluring", im2);

im2.copyTo(im1);

im2 = Mat::zeros(im1.size(), CV_8U);
for (size_t i = 1; i < im1.rows - 1; i++)
{
    for (size_t j = 1; j < im1.cols - 1; j++)
    {
        double minVal, maxVal = 0;
        minMaxIdx(im1(Rect(j - 1, i - 1, 3, 3)), &minVal, &maxVal);
        im2.at<uchar>(i, j) = minVal;
    }
}

imshow("(3) min bluring", im2);

Mat tmp;
double st = threshold(im2, tmp, 10, 255, THRESH_OTSU);
threshold(im2, im2, st + 14, 255, THRESH_BINARY_INV);
//dilate(im2, im2, Mat::ones(3, 3, CV_8U));

imshow("(4) final", im2);

waitKey(0);

Por cierto, en tales casos, los métodos de aprendizaje profundo como YOLO y RCNN son los mejores métodos. Pruébalos también.

MH304
fuente
su enfoque es bastante bueno, pero donde la ure atascada no es suficiente para mi problema, mezclé su solución y la mía e intenté aclarar algo, pero no funcionó
Ahmet Aziz Beşli
2

Aquí está mi solución

ingrese la descripción de la imagen aquí

En primer lugar, obtuve el patrón de fondo (Editado en pintura a mano). Desde:

ingrese la descripción de la imagen aquí

Después de eso, creé una imagen en blanco para llenarla con diferencias entre el patrón y la imagen.

img = Image.open("x.png").convert("RGBA")
pattern = Image.open("y.png").convert("RGBA")

pixels = img.load()
pixelsPattern = pattern.load()

new = Image.new("RGBA", (150, 50))
pixelNew = new.load()

for i in range(img.size[0]):
    for j in range(img.size[1]):
         if(pixels[i,j] != pixelsPattern[i,j]):
             pixelNew[i,j] = pixels[i,j]

new.save("differences.png")

Aquí están las diferencias ...

ingrese la descripción de la imagen aquí
y finalmente, agregué desenfoque y borré los bits que no son negros.

Resultado:

ingrese la descripción de la imagen aquí

Con el resultado de pytesseract es 2041, está mal para esta imagen, pero la tasa general es de alrededor de% 60.

Ahmet Aziz Beşli
fuente
1

Puede usar la biblioteca opencv para el procesamiento de imágenes. Muy útil podría ser esta página de documentación de OpenCV . Luego intente extraer su número a través del método findCountour como:

import cv2 
import numpy as np 

image = cv2.imread('C:\\E0snN.png')
cv2.waitKey(0) 

# Grayscale 
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 
gray = cv2.bitwise_not(gray)

# Threshold
ret,thresh = cv2.threshold(gray,150,255,1)
# Get countours
contours,h = cv2.findContours(thresh,1,2)
# Draw
cv2.drawContours(image, contours, -1, (0, 255, 0), 3) 
cv2.imshow('Contours', image) 
cv2.waitKey(0)

cv2.destroyAllWindows() 

Después de eso hay el siguiente resultado:

Primera coincidencia de imagen ingrese la descripción de la imagen aquí

Está lejos de ser perfecto, pero si intenta con valores de umbral diferentes, por ejemplo:

ret,thresh = cv2.threshold(gray,127,255,1)

Puedes obtener mejores resultados.

ElConrado
fuente