how to remove line from captcha completely

旧城冷巷雨未停 提交于 2019-11-30 18:17:34

问题


I wrote a program to remove the line from this captcha:

first of all, I improve image visibility by median filter

def apply_median_filter(self,img):
    img_gray=img.convert('L')
    img_gray=cv2.medianBlur(np.asarray(img_gray),3)
    img_bw=(img_gray>np.mean(img_gray))*255
    return img_bw

then I try to remove line:

def eliminate_zeros(self,vector):
    return [(dex,v) for (dex,v) in enumerate(vector) if v!=0 ]

def get_line_position(self,img):
    sumx=img.sum(axis=0)
    list_without_zeros=self.eliminate_zeros(sumx)
    min1,min2=heapq.nsmallest(2,list_without_zeros,key=itemgetter(1))
    l=[dex for [dex,val] in enumerate(sumx) if val==min1[1] or val==min2[1]]
    mindex=[l[0],l[len(l)-1]]
    cols=img[:,mindex[:]]
    col1=cols[:,0]
    col2=cols[:,1]
    col1_without_0=self.eliminate_zeros(col1)
    col2_without_0=self.eliminate_zeros(col2)
    line_length=len(col1_without_0)
    dex1=col1_without_0[round(len(col1_without_0)/2)][0]
    dex2=col2_without_0[round(len(col2_without_0)/2)][0]
    p1=[dex1,mindex[0]]
    p2=[dex2,mindex[1]]
    return p1,p2,line_length

finally I remove line by its position:

def remove_line(self,p1,p2,LL,img):
    m=(p2[0]-p1[0])/(p2[1]-p1[1]) if p2[1]!=p1[1] else np.inf
    w,h=len(img),len(img[0])
    x=[x for x in range(w)]
    y=[p1[0]+k for k in [m*t for t in [v-p1[1] for v in x]]]
    img_removed_line=img
    for dex in range(w):
        i,j=np.round([y[dex],x[dex]])
        i=int(i)
        j=int(j)
        rlist=[]
        while True:
            f1=i
            if img_removed_line[i,j]==0 and img_removed_line[i-1,j]==0:
                break
            rlist.append(i)
            i=i-1

        i,j=np.round([y[dex],x[dex]])
        i=int(i)
        j=int(j)
        while True:
            f2=i
            if img_removed_line[i,j]==0 and img_removed_line[i+1,j]==0:
                break
            rlist.append(i)
            i=i+1
        print([np.abs(f2-f1),[LL+1,LL,LL-1]])
        if np.abs(f2-f1) in [LL+1,LL,LL-1]:
            rlist=list(set(rlist))
            img_removed_line[rlist,j]=0

    return img_removed_line

but line isn't removed completely in some cases and I get the captcha image with some noise:

Thank you very much for your help!


回答1:


The problem is solved! Here is my edited python code. this removes line from captcha. I hope it helps:

from PIL import Image,ImageFilter
from scipy.misc import toimage
from operator import itemgetter
from skimage import measure
import numpy as np
import copy
import heapq
import cv2
import matplotlib.pyplot as plt
from scipy.ndimage.filters import median_filter

#----------------------------------------------------------------
class preprocessing:  
def pre_proc_image(self,img):
    #img_removed_noise=self.apply_median_filter(img)
    img_removed_noise=self.remove_noise(img)
    p1,p2,LL=self.get_line_position(img_removed_noise)
    img=self.remove_line(p1,p2,LL,img_removed_noise)
    img=median_filter(np.asarray(img),1)
    return img

def remove_noise(self,img):
    img_gray=img.convert('L')
    w,h=img_gray.size
    max_color=np.asarray(img_gray).max()
    pix_access_img=img_gray.load()
    row_img=list(map(lambda x:255 if x in range(max_color-15,max_color+1) else 0,np.asarray(img_gray.getdata())))
    img=np.reshape(row_img,[h,w])
    return img

def apply_median_filter(self,img):
    img_gray=img.convert('L')
    img_gray=cv2.medianBlur(np.asarray(img_gray),3)
    img_bw=(img_gray>np.mean(img_gray))*255
    return img_bw

def eliminate_zeros(self,vector):
    return [(dex,v) for (dex,v) in enumerate(vector) if v!=0 ]

def get_line_position(self,img):
    sumx=img.sum(axis=0)
    list_without_zeros=self.eliminate_zeros(sumx)
    min1,min2=heapq.nsmallest(2,list_without_zeros,key=itemgetter(1))
    l=[dex for [dex,val] in enumerate(sumx) if val==min1[1] or val==min2[1]]
    mindex=[l[0],l[len(l)-1]]
    cols=img[:,mindex[:]]
    col1=cols[:,0]
    col2=cols[:,1]
    col1_without_0=self.eliminate_zeros(col1)
    col2_without_0=self.eliminate_zeros(col2)
    line_length=len(col1_without_0)
    dex1=col1_without_0[round(len(col1_without_0)/2)][0]
    dex2=col2_without_0[round(len(col2_without_0)/2)][0]
    p1=[dex1,mindex[0]]
    p2=[dex2,mindex[1]]
    return p1,p2,line_length

def remove_line(self,p1,p2,LL,img):
    m=(p2[0]-p1[0])/(p2[1]-p1[1]) if p2[1]!=p1[1] else np.inf
    w,h=len(img),len(img[0])
    x=list(range(h))
    y=list(map(lambda z : int(np.round(p1[0]+m*(z-p1[1]))),x))
    img_removed_line=list(img)
    for dex in range(h):
        i,j=y[dex],x[dex]  
        i=int(i)
        j=int(j)
        rlist=[]
        while True:
            f1=i
            if img_removed_line[i][j]==0 and img_removed_line[i-1][j]==0:
                break
            rlist.append(i)
            i=i-1

        i,j=y[dex],x[dex]
        i=int(i)
        j=int(j)
        while True:
            f2=i
            if img_removed_line[i][j]==0 and img_removed_line[i+1][j]==0:
                break
            rlist.append(i)
            i=i+1
        if np.abs(f2-f1) in [LL+1,LL,LL-1]:
            rlist=list(set(rlist))
            for k in rlist:
                img_removed_line[k][j]=0

    return img_removed_line


来源:https://stackoverflow.com/questions/42736616/how-to-remove-line-from-captcha-completely

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!