Po pierwsze, przeczytałem o tym problemie

Mam np. Tablicę (ze zdjęcia)

[[255 255 255 ... 255 255 255]
 [255 255 0 ... 255 255 255]
 [255 255 255 ... 255 255 255]
 ...
 [255 255 0 ... 0 255 255]
 [255 255 0 ... 255 255 255]
 [255 255 255 ... 255 255 255]]

Chcę usunąć wiersz, w którym kwota 0 jest mniejsza niż określona wartość. Mój kod to:

import numpy
from collections import Counter

for i in range(pixelarray.shape[0]):
    # Counter(pixelarray[i])[0] represent the amount of 0 in one row.
    if Counter(pixelarray[i])[0] < 2: # check the amount of 0,if it is smaller than 2,delete it.
        pixelarray = np.delete(pixelarray,i,axis=0) # delete the row
print(pixelarray)

Ale wywołało to błąd:

Traceback (most recent call last):
  File "E:/work/Compile/python/OCR/PictureHandling.py", line 23, in <module>
    if Counter(pixelarray[i])[0] <= 1:
IndexError: index 183 is out of bounds for axis 0 with size 183

Co powinienem zrobić?

3
Kevin Mayo 3 kwiecień 2020, 17:20

3 odpowiedzi

Najlepsza odpowiedź

np.delete prawdopodobnie nie jest najlepszy wybór dla tego problemu. Można to rozwiązać po prostu maskując wiersze, które nie spełniają wymaganych kryteriów. W tym celu zacznij od policzenia liczby zer w wierszu:

zeros_per_row = (pixelarray == 0).sum(1)

Najpierw porównuje się każdą wartość w pixelarray z zerem, a następnie sumuje (liczy liczbę True wartości) jej kolumn (oś 1), więc otrzymujemy liczbę zer w każdym wierszu . Następnie możesz po prostu zrobić:

rows_with_min_zeros = pixelarray[zeros_per_row >= MIN_ZEROS]

Tutaj zeros_per_row >= MIN_ZEROS tworzy tablicę logiczną, w której każda wartość większa lub równa MIN_ZEROS to True. Korzystając z indeksowania tablic logicznych, można użyć do wykluczenia wierszy, w których znajduje się False, to znaczy wierszy, w których liczba zer jest mniejsza niż MIN_ZEROS.

3
jdehesa 3 kwiecień 2020, 15:16
if Counter(pixelarray[i])[0] <= 1:
IndexError: index 183 is out of bounds for axis 0 with size 183

W tym wyrażeniu pixelarray[i] jest jedyną częścią, która może wywołać ten błąd. To jest błąd numpy, który mówi nam, że i jest za duże dla obecnego kształtu pixelarray.

pixelarray to tablica dwuwymiarowa. i liczy się w górę do pixelarray.shape[0] (pierwotny kształt). Ale usuwasz wiersze z pixelarray w pętli; kurczy się. Więc w pewnym momencie licznik wykracza poza aktualny rozmiar tablicy.

Możesz napotkać to w podstawowym Pythonie, jeśli usuniesz elementy z listy w pętli.

In [456]: alist = [1,2,3,4]                                                                    
In [457]: for i in range(len(alist)): 
     ...:     print(i, alist) 
     ...:     del alist[i] 
     ...:                                                                                      
0 [1, 2, 3, 4]
1 [2, 3, 4]
2 [2, 4]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-457-5e5f105666aa> in <module>
      1 for i in range(len(alist)):
      2     print(i, alist)
----> 3     del alist[i]
      4 

IndexError: list assignment index out of range

Zobacz, jak lista kurczy się, nawet gdy rośnie i. Do i=2 lista jest zredukowana do 2 pozycji, więc alist[2] jest już nieważna. Zwróć uwagę, jak wypadła również „3”, a nie „1”. Jeśli moim zamiarem było usunięcie kolejnych wartości z listy, to nie zadziała.

W przypadku list sposobem obejścia tego rodzaju problemu jest upadek z końca

In [463]: for i in range(len(alist),0,-1): 
     ...:     print(i, alist) 
     ...:     del alist[i-1] 
     ...:      
     ...:                                                                                      
4 [1, 2, 3, 4]
3 [1, 2, 3]
2 [1, 2]
1 [1]
In [464]: alist                                                                                
Out[464]: []

W twoim przypadku np.delete tworzy nową tablicę przy każdym wywołaniu. W przypadku tablic jest to dość nieefektywne. W związku z tym, czy problem jest indeksowany, czy nie, odradzamy iteracyjne usuwanie w ten sposób. Możesz jednak zebrać wszystkie pożądane indeksy `` usuń '' na liście (dołączanie listy jest wydajne) i zrobić na koniec usuń. np.delete pobiera listę indeksów.

3
hpaulj 3 kwiecień 2020, 15:48

Po prostu użyj kopii tablicy pikseli podczas iteracji. Spróbuj tego:

import numpy
from collections import Counter
from copy import copy

pixelarray2 = copy(pixelarray)
for i in range(pixelarray2.shape[0]):
    # Counter(pixelarray[i])[0] represent the amount of 0 in one row.
    if Counter(pixelarray2[i])[0] < 2: # check the amount of 0,if it is smaller than 2,delete it.
        pixelarray = np.delete(pixelarray,i,axis=0) # delete the row
print(pixelarray)
0
Muhammad Moiz Ahmed 3 kwiecień 2020, 16:08