Closed swharden closed 7 years ago
I came up with this hack (supporting rectangles only) to get me started. It might help. It produces the output above when given an ROI (zip). Currently only rectangles are supported. The roi_areas
function is what I think may eventually belong in your project.
"""this example is extremely simplistic and not very efficient, but it's easy to read."""
import inspect_t
from read_roi import read_roi_zip
import os
import numpy as np
import matplotlib.pyplot as plt
def roi_areas(roiFile):
"""
Given an ROI file (created with ImageJ's ROI Manager), analyze each
ROI and return a dictionary with its keys including 'area' which is
a list of X/Y pixel pairs encircled by the ROI.
Also adds a 'bounds' key [X1,X2,Y1,Y2] of the bounds of the ROI
based on its area.
"""
assert os.path.exists(roiFile)
rois = read_roi_zip(roiFile)
for key in rois:
roi=rois[key]
# populate keys for rectangles
if roi['type'] is 'rectangle':
X1,Y1=roi['left'],roi['top']
X2,Y2=roi['width']+X1,roi['height']+Y1
area=[]
for x in range(X1,X2):
for y in range(Y1,Y2):
area.append((x,y))
rois[key]['area']=area
else: #TODO: add eclipse and polygon support
print("WARNING: 'area' key unavailable for",roi['type'])
# calculate bounds of a shape based on its area
if 'area' in rois[key].keys():
Xs,Ys=[],[]
for X,Y in rois[key]['area']:
Xs.append(X)
Ys.append(Y)
rois[key]['bounds']=np.min(Xs),np.max(Xs),np.min(Ys),np.max(Ys)
return rois
def label_rois(rois,color='k',drawBounds=False):
"""
given the rois (dict), label each ROI on an existing subplot.
Assume matplot's imshow() has already been called. Optionally
add ROI labels, set their color, and/or draw bounding box rectangles.
"""
assert type(rois) is dict
for i,key in enumerate(rois.keys()):
X1,X2,Y1,Y2=rois[key]['bounds']
plt.text(X1,Y1+-1,i,verticalalignment='bottom',color=color)
if drawBounds:
plt.plot([X1,X2,X2,X1,X1],[Y1,Y1,Y2,Y2,Y1],'-',color=color)
plt.margins(0,0)
return
if __name__=="__main__":
# load the 3D image data (basically a list of 2D images) from disk
fldr=r'C:\Users\swharden\Documents\temp\TSeries-01112017-1536-1177'
G,R,fnamesCH1,fnamesCH2,conf=inspect_t.inspect_folder(fldr)
pic=R[1].copy() # a 2D array representing an image
picROI=R[1].copy() # a 2D array we will use to depict what's masked
picROI[:,:]=np.nan
roiFile=r'C:\Users\swharden\Documents\temp\TSeries-01112017-1536-1177\RoiSet.zip'
rois=roi_areas(roiFile)
for i,key in enumerate(rois):
mask=np.zeros(R[0].shape,dtype=np.bool)
for Y,X in rois[key]['area']:
mask[Y,X]=True
picROI[X,Y]=pic[X,Y]
roiValues=pic[mask]
# plot the ROIs
plt.figure(figsize=(15,10))
plt.subplot(131)
plt.imshow(pic)
plt.subplot(132)
plt.imshow(picROI)
label_rois(rois)
plt.subplot(133)
plt.imshow(pic)
label_rois(rois,color='w',drawBounds=True)
plt.tight_layout()
plt.show()
print("DONE")
Hello,
read-roi
only focus on reading IJ ROIs files so if the information like the area is not the ROI file read-roi
won't provide it.
I think this kind of analysis should be done in your code. Or you could also create a new library that use read-roi
for I/O and has its main part doing some ROIs computation such as calculating the area.
I agree with your logic! I'll make a standalone area_from_roi()
function that does this then link back to it when it's complete.
Thank you for your understanding !
Currently all ROIs (rectangle, polygon, oval, etc.) just report x/y coordinates of their edges. Do you have any plans to add a function to convert an ROI to area, which would output x,y pixel coordinates of all pixels inside the ROI?
This:
Currently outputs:
But it would be great if:
...displayed a large list of all X/Y positions encircled by each shape. Each ROI dictionary would be pre-loaded with the area key when the data is read. Do you have code on hand that does this?
Resources: