Processamento de imagem Python no Captcha como remover ruído

8

Eu sou tão novo no Processamento de imagens e o que estou tentando fazer é eliminar o ruído das captchas;

Para captchas, tenho diferentes tipos deles:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Para o primeiro, o que eu fiz é:

Primeiro passo

insira a descrição da imagem aqui

Primeiramente, eu converti todos os pixels que não são pretos para os pretos. Então, encontrei um padrão que é um ruído da imagem e o excluí. Para o primeiro captcha, foi fácil limpá-lo e encontrei o texto com o tesseract.

Mas estou procurando uma solução para o segundo e o terceiro.

Como isso deve ser? Quero dizer, quais são os métodos possíveis para limpá-lo?

É assim que eu apago padrões:

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) 

Desculpe pelos nomes das variáveis, eu estava apenas testando a função.

Obrigado..

Ahmet Aziz Beşli
fonte
2
Essas são tarefas bastante pesadas para um único método básico de processamento de imagem, mas você pode procurar "padrões de moiré" e métodos para removê-los. Além disso, você pode usar métodos de aprendizado profundo, como segmentação de texto ou obter um modelo limpo da imagem e remover qualquer correspondência na imagem, correlacionando-a.
SajanGohil 26/02
@SajanGohil sim através do método padrão, eu meio que fiz alguma coisa. Obrigado
Ahmet Aziz Beşli

Respostas:

5

Isto é o mais longe possível:

Você provavelmente conhece a medianBlurfunção que encontra o valor mediano em cada kernel e substitui esse valor no centro do kernel. Podemos fazer algo semelhante a isso, mas em vez da mediana, use o valor máximo e o valor mínimo. Com uma mancha mediana também, obtive alguns resultados. Eu sei que eles não são perfeitos, mas espero que isso lhe dê algumas idéias (você pode brincar com os tamanhos da imagem de entrada e os kernels, isso pode melhorar um pouco os resultados).

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Eu não tenho python instalado agora, então eu compartilho o código C ++ exato que eu usei:

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

A propósito, nesses casos, métodos de aprendizagem profunda, como YOLO e RCNN, são os melhores métodos. Experimente-os também.

MH304
fonte
sua abordagem é meio boa, mas onde você está preso não é suficiente para o meu problema, misturei sua e minha solução e tentei obter algo mais claro, mas não funcionou
Ahmet Aziz Beşli
2

Aqui está a minha solução,

insira a descrição da imagem aqui

Em primeiro lugar, obtive o padrão de fundo (editado à mão com tinta). De:

insira a descrição da imagem aqui

Depois disso, criei uma imagem em branco para preenchê-la com diferenças entre o padrão e a imagem.

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

Aqui estão as diferenças ..

insira a descrição da imagem aqui
e, finalmente, adicionei desfoque e limpei os bits que não são pretos.

Resultado:

insira a descrição da imagem aqui

Com o resultado pytesseract em 2041, está errado para esta imagem, mas a taxa geral está em torno de% 60.

Ahmet Aziz Beşli
fonte
1

Você pode usar a biblioteca opencv para processamento de imagem. Muito útil pode ser esta página de documentação do opencv . Em seguida, tente extrair seu número através do 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() 

Depois disso, há o seguinte resultado:

Correspondência da primeira imagem insira a descrição da imagem aqui

Está longe de ser perfeito, mas se você tentar com valores de limite diferentes, por exemplo:

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

você pode obter melhores resultados.

ElConrado
fonte