1

I'm iterating over a NumPy (nd) array of OpenCV lines. I want to remove all lines which are outwith 8 degrees of vertical. I realise the numpy array is immutable and what I'm doing in the code is not right but it demonstrates the idea of what I'm trying to do;

index = 0
for line in self.lines[0]:
    if (line[1]*180)/np.pi > 8:                                      
        self.lines[0] = np.delete(self.lines[0], index, axis=0)
    index+=1

How can I go about removing these NumPy array indexes?

Thanks!

4
  • A better explanation of problem is required if you want someone to help you... Commented Dec 22, 2014 at 14:48
  • what other information would you like? Commented Dec 22, 2014 at 15:00
  • What actually this code line if (line[1]*180)/np.pi > 8 does, or what are you trying to achieve with it? Commented Dec 22, 2014 at 15:02
  • it checks whether the line is greater than 8 degrees and if so removes that item from the NumPy array. The question is mainly about removing from a NumPy array or creating a new one without these in it Commented Dec 22, 2014 at 15:09

2 Answers 2

4

You cannot delete array indexes while iterating over that array. It will give wrong results. Say you are at iteration 5 and this index satisfies if condition and needs to be deleted, but if we delete this it will cause array element at index 6 to come at index 5 and next element selected will be 7 which comes to index 6 after deletion and thus condition is never checked for element initially at index 6 i.e., before deletion.

Basic idea to deal with this issue is to append these indices to a list and delete them outside lope. So your code is:

index = 0
idx = []
for line in self.lines[0]:
    if (line[1]*180)/np.pi > 8:     
       idx.append(index)         
    index+=1

self.lines[0] = np.delete(self.lines[0], idx, axis=0)
Sign up to request clarification or add additional context in comments.

1 Comment

I get an error with your solution. ValueError: invalid entry
1

I guess you are missing indentation in your code, so I interpret it like this:

index = 0
for line in self.lines[0]:
    if (line[1]*180)/np.pi > 8:                                      
        self.lines[0] = np.delete(self.lines[0], index, axis=0)
    index+=1

You can do that of course without a loop. First we do the check to build the boolean indexing array (True/False values for every item in the array):

index = self.lines[0,:,1]*180/np.pi > 8

Then we select the lines, where the condition is false:

a[~a%2==0]

Where np.nonzero converts from a boolean array to an array, where all indices with True-values are listed.

For example:

>>> a  = np.arange(10)
>>> a[~a%2==0]
array([1, 3, 5, 7, 9])

3 Comments

what does your second last line do? not familiar with the syntax
@MarkCorrigan I added now more explanations, an example and links to the docs. This would be now the way how to achieve your problem in a 'Numpythonic' way.
That last delete could be replaced with boolean indexing: a[~a%2==0]. delete is a complex function that always returns a new array. It does not directly modify its input.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.