Skip to content

Instantly share code, notes, and snippets.

@luispedro
Last active December 16, 2020 07:50
Show Gist options
  • Select an option

  • Save luispedro/3437255 to your computer and use it in GitHub Desktop.

Select an option

Save luispedro/3437255 to your computer and use it in GitHub Desktop.
Read ImageJ's ROI files
# UPDATE IN 2020
# You almost always will want to use the version at
# https://github.com/luispedro/imread, which is
# up-to-date and works with Python 3
# Copyright: Luis Pedro Coelho <luis@luispedro.org>, 2012
# License: MIT
import numpy as np
def read_roi(fileobj):
'''
points = read_roi(fileobj)
Read ImageJ's ROI format
'''
# This is based on:
# http://rsbweb.nih.gov/ij/developer/source/ij/io/RoiDecoder.java.html
# http://rsbweb.nih.gov/ij/developer/source/ij/io/RoiEncoder.java.html
SPLINE_FIT = 1
DOUBLE_HEADED = 2
OUTLINE = 4
OVERLAY_LABELS = 8
OVERLAY_NAMES = 16
OVERLAY_BACKGROUNDS = 32
OVERLAY_BOLD = 64
SUB_PIXEL_RESOLUTION = 128
DRAW_OFFSET = 256
pos = [4]
def get8():
pos[0] += 1
s = fileobj.read(1)
if not s:
raise IOError('readroi: Unexpected EOF')
return ord(s)
def get16():
b0 = get8()
b1 = get8()
return (b0 << 8) | b1
def get32():
s0 = get16()
s1 = get16()
return (s0 << 16) | s1
def getfloat():
v = np.int32(get32())
return v.view(np.float32)
magic = fileobj.read(4)
if magic != 'Iout':
raise IOError('Magic number not found')
version = get16()
# It seems that the roi type field occupies 2 Bytes, but only one is used
roi_type = get8()
# Discard second Byte:
get8()
if not (0 <= roi_type < 11):
raise ValueError('roireader: ROI type %s not supported' % roi_type)
if roi_type != 7:
raise ValueError('roireader: ROI type %s not supported (!= 7)' % roi_type)
top = get16()
left = get16()
bottom = get16()
right = get16()
n_coordinates = get16()
x1 = getfloat()
y1 = getfloat()
x2 = getfloat()
y2 = getfloat()
stroke_width = get16()
shape_roi_size = get32()
stroke_color = get32()
fill_color = get32()
subtype = get16()
if subtype != 0:
raise ValueError('roireader: ROI subtype %s not supported (!= 0)' % subtype)
options = get16()
arrow_style = get8()
arrow_head_size = get8()
rect_arc_size = get16()
position = get32()
header2offset = get32()
if options & SUB_PIXEL_RESOLUTION:
getc = getfloat
points = np.empty((n_coordinates, 2), dtype=np.float32)
else:
getc = get16
points = np.empty((n_coordinates, 2), dtype=np.int16)
points[:,1] = [getc() for i in xrange(n_coordinates)]
points[:,0] = [getc() for i in xrange(n_coordinates)]
points[:,1] += left
points[:,0] += top
points -= 1
return points
def read_roi_zip(fname):
import zipfile
with zipfile.ZipFile(fname) as zf:
return [read_roi(zf.open(n))
for n in zf.namelist()]
@tdsmith
Copy link
Copy Markdown

tdsmith commented Jun 11, 2013

super helpful; thanks for posting this!

one note: the first column of points will hold y values and the second column will hold x values!

@martinitus
Copy link
Copy Markdown

Sweet! saves me quite some time 👍

@fepegar
Copy link
Copy Markdown

fepegar commented Oct 16, 2015

This is very nice. Where did you get the info to about the .roi file?

I have some files whose roi_type was 0, so this code didn't work. I commented lines 62 and 63 and it works now.

@tdsmith
Copy link
Copy Markdown

tdsmith commented May 24, 2016

I've packaged this gist into a pypi package: https://github.com/tdsmith/ijroi, https://pypi.python.org/pypi/ijroi

@nvladimus
Copy link
Copy Markdown

Nice, thanks! Do you happen to have code for writing ROI by any chance?

@hadim
Copy link
Copy Markdown

hadim commented May 7, 2017

@luispedro
Copy link
Copy Markdown
Author

This old gist does not work with Python 3, but I have now folded the code into the imread project and updated it to work with both Python 2 & 3:

https://github.com/luispedro/imread

@YubinXie
Copy link
Copy Markdown

Nice, thanks! Do you happen to have code for writing ROI by any chance?

I have the same question. Any one knows how to write ROI? I want to generate some region and go back to image J to edit. Thanks!

@kazemSafari
Copy link
Copy Markdown

The above code does not work in python 3.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment