ROI and Colormaps

996 views
Skip to first unread message

antonell...@gmail.com

unread,
Apr 8, 2013, 6:01:00 PM4/8/13
to pyqt...@googlegroups.com
Hi everybody, 

I am very very new to python and pyqtgraph, so my questions are probably trivial. 
I have to handle and show some image taken with microscopes.


1) First of all, I have a 2D numpy array (the image)

: type(mat)
: numpy.ndarray

: mat.shape
: (256, 256)

I can visualize it with pg.image(mat) and it is of course in a gray scale. I am not able to visualize it using a colormap.


2) I use the pg.PolyLineROI tool to draw a region of interest. How can I have a mask of the selected ROI?
For the sake of clarity, with mask I mean a numpy array with the same shape of the image and that has 1 (or True) for all the inside the ROI points and 0 (or False) for all the points outside the ROI.

Thanks in advance

Ant

Luke Campagnola

unread,
Apr 8, 2013, 9:15:19 PM4/8/13
to pyqt...@googlegroups.com
On Mon, Apr 8, 2013 at 6:01 PM, <antonell...@gmail.com> wrote:

1) First of all, I have a 2D numpy array (the image)

: type(mat)
: numpy.ndarray

: mat.shape
: (256, 256)

I can visualize it with pg.image(mat) and it is of course in a gray scale. I am not able to visualize it using a colormap.

If you click on the greyscale bar at the right side of the image view, you can add new color stops or change the colors. Right clicking gives you a menu of pre-defined colormaps.

2) I use the pg.PolyLineROI tool to draw a region of interest. How can I have a mask of the selected ROI?
For the sake of clarity, with mask I mean a numpy array with the same shape of the image and that has 1 (or True) for all the inside the ROI points and 0 (or False) for all the points outside the ROI.

The latest PolyLineROI has a getArrayRegion method that does the following:
   1. Slice out the rectangular region of the image covered by the bounding rectangle of the ROI
   2. Create a black image and draw the shape of the ROI in white to the image
   3. Convert the image to a float-valued mask
   4. Return the sliced data multiplied by the mask. 

Depending on your intention, you may be able to use this method as-is or construct a modified version that gives you the mask over the entire image. 

Let me know if you need more help with this..


Luke

antonell...@gmail.com

unread,
Apr 10, 2013, 2:13:25 PM4/10/13
to pyqt...@googlegroups.com
Hi Luke, thanks a lot for your replay. Great help for the Colormap.
For the other problem, I am still in trouble... I don't know which arguments do I have to pass to the method getArrayRegion.
If I type help(rr.getArrayRegion) - where "rr" is the name of the PolyLineROI - it is wrote that I have to pass the arguments data and img.
What are them? I don't think they are rr methods and I have no clue about it.

Thanks in advance for your patience

Luke Campagnola

unread,
Apr 10, 2013, 3:18:09 PM4/10/13
to pyqt...@googlegroups.com
On Wed, Apr 10, 2013 at 2:13 PM, <antonell...@gmail.com> wrote:
Hi Luke, thanks a lot for your replay. Great help for the Colormap.
For the other problem, I am still in trouble... I don't know which arguments do I have to pass to the method getArrayRegion.
If I type help(rr.getArrayRegion) - where "rr" is the name of the PolyLineROI - it is wrote that I have to pass the arguments data and img.
What are them? I don't think they are rr methods and I have no clue about it.

Thanks in advance for your patience


All of the ROI.getArrayRegion methods work basically the same: the assumption is that the ROI is being displayed over an image and you would like to use the position of that ROI relative to the image to extract data from an array. The image is provided via the 'img' argument and the array to slice is provided by 'data'.   The 'axes' argument tells you which axes in 'data' correspond to the x and y axes of 'img'. Here's an example:

    win = pg.GraphicsWindow()
    view = win.addViewBox()
    data = np.random.normal(size=(100,100,100))
    img = pg.ImageItem()
    img.setImage(data.mean(axis=0))  # img x and y axes are data axes 1 and 2
    roi = pg.RectROI(pos=[10, 10], size=[20, 20])
    view.addItem(img)
    view.addItem(roi)
    
    ## let user move ROI, then pull out selected region:
    roiData = roi.getArrayRegion(data, img, axes=(1,2))
   
In the example, roiData.shape would be (100,20,20), assuming the ROI had not been resized.

Does this help?

Luke

 

antonell...@gmail.com

unread,
Apr 10, 2013, 3:53:35 PM4/10/13
to pyqt...@googlegroups.com
Thanks a lot, this gives me all the explanation I was searching for. Great job!!
Thanks again
Ant


On Tuesday, April 9, 2013 12:01:00 AM UTC+2, antonell...@gmail.com wrote:

Mike

unread,
Apr 22, 2013, 1:48:24 AM4/22/13
to pyqt...@googlegroups.com
Hi Luke,

I have just setup a viewbox that can handle multiple polyline ROIs. I added the getArrayRegion fuction that you recently posted so I could calculate the average grey scale value.
I was getting the following error:

File "ROI.py", line 1774, in getArrayRegion
    return sliced * mask
ValueError: operands could not be broadcast together with shapes (65,93,5) (65,93)

This appears to be related to the fact that my data is actually a 3D array of images (5 in this case) created using:

data = np.dstack(images)

where images is a list of 2D arrays (one for each image).

I modified this to:

    def getArrayRegion(self, data, img, axes=(0,1), returnMappedCoords=False, **kwds):

       sl = self.getArraySlice(data, img, axes=(0,1))

       if sl is None:

           return None

       sliced = data[sl[0]]

       im = QtGui.QImage(sliced.shape[axes[0]], sliced.shape[axes[1]], QtGui.QImage.Format_ARGB32)

       im.fill(0x0)

       p = QtGui.QPainter(im)

       p.setPen(fn.mkPen(None))

       p.setBrush(fn.mkBrush('w'))

       p.setTransform(self.itemTransform(img)[0])

       bounds = self.mapRectToItem(img, self.boundingRect())

       p.translate(-bounds.left(), -bounds.top())

       p.drawPath(self.shape())

       p.end()

       mask = fn.imageToArray(im)[:,:,0].astype(float) / 255.

       shape = [1] * data.ndim

       shape[axes[0]] = sliced.shape[axes[0]]

       shape[axes[1]] = sliced.shape[axes[1]]

       ar = sliced.copy()

       for i in range(sliced.shape[-1]):

           ar[:,:,i] = sliced[:,:,i]*mask

       return ar


This appears to work ok. I compared it to the values I was getting from a Rectangular ROI and I got essentially the same values. 

Thanks for your efforts on pyqtgraph.

Cheers,
Mike

Luke Campagnola

unread,
Apr 22, 2013, 8:06:56 AM4/22/13
to pyqt...@googlegroups.com
On Mon, Apr 22, 2013 at 1:48 AM, Mike <michael.chri...@gmail.com> wrote:
Hi Luke,

I have just setup a viewbox that can handle multiple polyline ROIs. I added the getArrayRegion fuction that you recently posted so I could calculate the average grey scale value.
I was getting the following error:

File "ROI.py", line 1774, in getArrayRegion
    return sliced * mask
ValueError: operands could not be broadcast together with shapes (65,93,5) (65,93)

This appears to be related to the fact that my data is actually a 3D array of images (5 in this case) created using:

data = np.dstack(images)

where images is a list of 2D arrays (one for each image).

Hi Mike, 
This looks good. You can simplify it further like this:

       shape = [1] * data.ndim
       shape[axes[0]] = sliced.shape[axes[0]]
       shape[axes[1]] = sliced.shape[axes[1]]
       return sliced * mask.reshape(shape)

For an explanation of this, you can read about numpy's broadcasting rules.


Luke

 

Mike

unread,
Apr 22, 2013, 8:12:36 AM4/22/13
to pyqt...@googlegroups.com
Hi Luke,

That works. I thought you were heading somewhere with the shape = [1] * data.ndim and following lines.

Thanks,
Mike

Luke Campagnola

unread,
Apr 22, 2013, 8:18:39 AM4/22/13
to pyqt...@googlegroups.com
On Mon, Apr 22, 2013 at 8:12 AM, Mike <michael.chri...@gmail.com> wrote:
Hi Luke,

That works. I thought you were heading somewhere with the shape = [1] * data.ndim and following lines.


AHA. I thought that was your code. 
Yeah I guess I never quite finished that thought :)
Thanks!

Luke 
Reply all
Reply to author
Forward
0 new messages