简体   繁体   中英

AttributeError: 'numpy.ndarray' object has no attribute 'convert' and error of IndexError: list index out of range

Attribute errors may have posted earlier however in my situation when I found a solution, I got another error stating that my list index was out of range. I am beginner in Python working on breaking an image captcha. I have used the code provided from here - How to remove line from captcha completely

Based on that I added few lines to run it

lineRemoval.py

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 i>=0:
                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

if __name__ == '__main__':
    img = cv2.imread("captcha.png")
    p = preprocessing()
    imgNew = p.pre_proc_image(img)
    cv2.imshow("Image", imgNew)
    cv2.waitKey(0)

Initially when trying with the above code I was getting the error

Traceback (most recent call last):
  File "lineRemoval.py", line 98, in <module>
    imgNew = p.pre_proc_image(img)
  File "lineRemoval.py", line 18, in pre_proc_image
    img_removed_noise=self.remove_noise(img)
  File "lineRemoval.py", line 25, in remove_noise
    img_gray=img.convert('L')
AttributeError: 'numpy.ndarray' object has no attribute 'convert'

I searched and found the solution by changing my main function to this

if __name__ == '__main__':
    image = cv2.imread("captcha.png")
    img = Image.fromarray(image)
    p = preprocessing()
    imgNew = p.pre_proc_image(img)
    cv2.imshow("Image", imgNew)
    cv2.waitKey(0)

However after that my array is out of index

Traceback (most recent call last):
  File "lineRemoval.py", line 98, in <module>
    imgNew = p.pre_proc_image(img)
  File "lineRemoval.py", line 20, in pre_proc_image
    img=self.remove_line(p1,p2,LL,img_removed_noise)
  File "lineRemoval.py", line 83, in remove_line
    if img_removed_line[i][j]==0 and img_removed_line[i+1][j]==0:
IndexError: list index out of range

Cannot identify where the error lies, does the while condition need to be changed or was the previous change causing it or is it something else.

Update

I have changed the condition for the while loop however similar comes for the initial while loop condition of i>=0

lineRemoval.py

while i>=0:
    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 i<len(img_removed_line)-1:
    f2=i
        if img_removed_line[i][j]==0 and img_removed_line[i+1][j]==0:
            break
        rlist.append(i)
        i=i+1

Error that is shown

Traceback (most recent call last):
  File "lineRemoval.py", line 98, in <module>
    imgNew = p.pre_proc_image(img)
  File "lineRemoval.py", line 20, in pre_proc_image
    img=self.remove_line(p1,p2,LL,img_removed_noise)
  File "lineRemoval.py", line 73, in remove_line
    if img_removed_line[i][j]==0 and img_removed_line[i-1][j]==0:
IndexError: list index out of range

Replace your second while loop in the function removed line with this code:

while i<len(img_remmoved_line)-1:
    f2=i
    if img_removed_line[i][j]==0 and img_removed_line[i+1][j]==0:
        break
    rlist.append(i)
    i=i+1

You are increasing i at each iteration which after sometime breaks the index limit of the list. This condition protects the iteration of the loop if the value of i is bigger then index limit of that list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM