1

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.

3
  • Can you help me understand grains? What do those pairs of numbers represent, and where do they come from? I also want to check: is the output of this code what you want? I mean, the question is about getting the same output but without the loop? Commented Oct 18, 2019 at 7:38
  • Each item in grains is related to one segment, call it i, where i[0] is its unique 'serial' number, whereas i[1] is its area (number of pixels) .. Commented Oct 18, 2019 at 8:22
  • Ah, okay, makes sense now. Cheers! Commented Oct 18, 2019 at 8:26

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Many thanks! Yes, that's the solution. I was trying in this direction without grains, but without success :) All the best!

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.