andro_analytics
andro_analytics

Reputation: 23

How to avoid 'for' loop in numpy array

I'm working on greyscale images of some alloys microstructures taken with optical microscope, etc. My goal is to analyse the amount (%) of areas with given threshold (pixel count), as well as the number, size, etc. of these segments. For last I use: from skimage import measure, morphology, which finds these segments and each segment has unique integer in labels matrix, which has same shape as pic. I can do all, except coloring those segments on original image without a for loop..

import numpy as np
import matplotlib.pyplot as plt

grains = np.array([[1,3], [2,5], [6,2]] )

labels=np.array([[1,1,0,0,0],[1,0,0,2,0],[0,0,2,2,2],[0,0,0,2,0],[6,6,0,0,0]])

im = np.array([[223, 222, 225, 224, 227],[222, 224, 218, 220, 221],[216, 221, 219, 223, 225],[228, 226, 231, 224, 228],[226, 228, 225, 218, 225]])

image=np.stack((im, im, im), axis=2)       # greyscale sample image

color = [0, 0, 255]                        # rgb blue color

for i in grains:
    B=np.full((i[1],3), color).astype('int')
    image[labels==i[0]]=B

plt.imshow(image)
plt.show()

Is there any efficient 'numpy way', which won't include 'for' loop, and would, therefore, be much faster.

Upvotes: 1

Views: 150

Answers (1)

Matt Hall
Matt Hall

Reputation: 8152

If the output is correct already, then you can turn the pixels flagged in labels blue like so:

import numpy as np
import matplotlib.pyplot as plt

labels = np.array([[1,1,0,0,0],
                   [1,0,0,2,0],
                   [0,0,2,2,2],
                   [0,0,0,2,0],
                   [6,6,0,0,0]])

im = np.array([[223, 222, 225, 224, 227],
               [222, 224, 218, 220, 221],
               [216, 221, 219, 223, 225],
               [228, 226, 231, 224, 228],
               [226, 228, 225, 218, 225]])

image = np.stack((im, im, im), axis=2)
image[labels >= 1] = [0, 0, 255]

plt.imshow(image)

Which gives the same output you have:

output from matplotlib

But it seems like you are trying to do something else — so that label = 1 looks different from label = 2. As you can see, I didn't use grains at all. If you can explain how you want the final image to look, there's almost certainly a way to do it without loops.

Upvotes: 3

Related Questions