Multiple lists in a for loop, numpy shape command requiring list entry?

Question:

I created the following for loop

for ItemTemplate in ItemTemplates:
    x = 0
    self.needle_images.append(cv.imread(ItemTemplate, cv.IMREAD_UNCHANGED))
    self.needle_widths.append(self.needle_images[x].shape[1])
    self.needle_heights.append(self.needle_images[x].shape[0])
    x = x+1

I originally tried to write the for loop like this:

for ItemTemplate in ItemTemplates:
    self.needle_images.append(cv.imread(ItemTemplate, cv.IMREAD_UNCHANGED))
    self.needle_widths.append(self.needle_images.shape[1])
    self.needle_heights.append(self.needle_images.shape[0])

I was assuming I didn’t need to add the list entries to this code and perhaps there is a better way to do this but my Python skills are very young. The top example is fine and my code runs ok with it, but I am looking to see if there was a better way to accomplish this task.

Asked By: Busta

||

Answers:

I don’t know why you need to store the image, width and height in three lists since image already has the width and height as its shape member, which you are already using. I also wonder why your top example works, since x will always stay 0 and this way all the upcoming Images will have the size of the first Image. The second example clearly doesn’t work since you try to take the shape member of an array.

Changes I would make

if you need the index (x in your case) I would use the enumerate() function to get it:

for x, ItemTemplate in enumerate(ItemTemplates):
    # x : index starting from 0
    ...

you could also first get the image into a local variable and then add it:

for ItemTemplate in ItemTemplates:
    img = cv.imread(ItemTemplate, cv.IMREAD_UNCHANGED)
    self.needle_images.append(img)
    self.needle_widths.append(img.shape[0]) # if needing to store widths in own array
    ...

if you don’t want to get the width and height from the shape member you could store the Image in an own class or dict, in two separate members width and height though this wouldn’t make a big difference from just using the shape.
So if the for loop doesn’t get more functionality, I would write:

for ItemTemplate in ItemTemplates:
    self.needle_images.append(cv.imread(ItemTemplate, cv.IMREAD_UNCHANGED))

and use the shape member for the size since you can always store the shape value in a local variable when using it later:

for img in self.needle_images:
    width, height, channels = img.shape
    display.blit(img, (width, height)) # pseudo operation
    ...
Answered By: Emmmmllll

The last two lines of the loop are always using the last image appended to needle_images. The index of the last item in a list is -1.

for ItemTemplate in ItemTemplates:
    self.needle_images.append(cv.imread(ItemTemplate, cv.IMREAD_UNCHANGED))
    self.needle_widths.append(self.needle_images[-1].shape[1])
    self.needle_heights.append(self.needle_images[-1].shape[0])

Or just bite the bullet and assign the image to a name at the top of the loop.

for ItemTemplate in ItemTemplates:
    temp = cv.imread(ItemTemplate, cv.IMREAD_UNCHANGED)
    self.needle_images.append(temp)
    self.needle_widths.append(temp.shape[1])
    self.needle_heights.append(temp.shape[0])

Or even…

for ItemTemplate in ItemTemplates:
    temp = cv.imread(ItemTemplate, cv.IMREAD_UNCHANGED)
    w,h = temp.shape
    self.needle_images.append(temp)
    self.needle_widths.append(w)
    self.needle_heights.append(h)
Answered By: wwii
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.