User Tools

Site Tools


blogtng:2012-10-28:imglib2_first_test

ImgLib2, first test

I pretty much enjoyed ImageJ User and Developer conference 2012 in Luxemburg. Interesting people from different areas in science, very exciting to see how people are doing image processing and analysis. Some of live notes could be found in my time line. One of the great contribution for the third day was Bene Schmidt's work intseg_3D, combining user clicking and active contour fitting in 3D.

One of the core topic there was ImgLib2, the generic image typ behind ImageJ2. After coming back home, I tested ImgLib2 with the Jython code below.

Results were: Started testImgLib2.py at Sun Oct 28 16:41:57 CET 2012

  • ImgLib2 cursor 333 millisec
  • ImgLib2 for : 138 millisec
  • ImagePlus 152 millisec
  • ImageProcessor 114 millisec
  • Pixel Array 59 millisec

for loop using Img iterator is a bit faster than going through ImagePlus using classic nested for-loop. Even with the classic nested for-loop, using ImageProcessor was a bit faster than Img. The fastest is of course accessing pixels via pixel array. I only did this via ImagePlus, but there should be also some methods to extract an array from Img, which I did not test.

Addendum: See also proper benchmark in the following link in ImageJ2 site:

http://developer.imagej.net/imglib-benchmarks

Thanks to Albert Cardona for commenting on this.

# first trial with ImageLib2
# iterations

from net.imglib2.img import ImagePlusAdapter

imp = IJ.openImage("http://imagej.nih.gov/ij/images/blobs.gif")
img = ImagePlusAdapter.wrapReal(imp)

# accessing via ImagePlus
t3 = System.currentTimeMillis()
for i in range(imp.getHeight()):
	for j in range(imp.getWidth()):
#		print imp.getPixel(j, i)[0]
		imp.getPixel(j, i)[0]
				
t4 = System.currentTimeMillis()

# accessing via ImageProcessor
t5 = System.currentTimeMillis()
ip = imp.getProcessor()
for i in range(imp.getHeight()):
	for j in range(imp.getWidth()):
#		print ip.getPixelValue(j, i)
		ip.getPixelValue(j, i)
				
t6 = System.currentTimeMillis()

# ImgLib2 cursor
t1 = System.currentTimeMillis()
cursor = img.cursor()
cursor.fwd()
while cursor.hasNext():
	cursor.next()
#	print cursor.get()
	cursor.get()

t2 = System.currentTimeMillis()

t7 = System.currentTimeMillis()
for t in img:
#	print t.get()
	t.get()

t8 = System.currentTimeMillis()

# pixel array
t9 = System.currentTimeMillis()
pix = imp.getProcessor().getPixels()
for i in pix:
	i = i
#	print i

t10 = System.currentTimeMillis()	

print 'ImgLib2 cursor',(t2-t1), 'millisec'
print 'ImgLib2 for : ',(t8-t7), 'millisec'
print 'ImagePlus',(t4-t3), 'millisec'
print 'ImageProcessor',(t6-t5), 'millisec'
print 'Pixel Array',(t10-t9), 'millisec'
	

Comments

Hi Kota,

good to see you playing with ImgLib2. Regarding the benchmarks I want to comment a bit:

1. ImgLib2 virtualizes data access by which it becomes generic. This is standard stuff for all Java programs. The Java runtime has a Just-In-Time (JIT) compiler that can inline frequently called virtual methods by which the execution speed of virtualized data access can become equivalent to that of direct data access. Therefore, abstract code is always slower than direct code the first time you call it but can become equally quick from the second or third call. You should measure the execution speed for several iterations of the same code to see this effect. It is uninteresting to see the first iteration only because it only shows the `warmup' phase which plays only a minor role in a running system.

2. Jython adds an additional level of abstraction that we have not yet tested to its full extent. I would expect it to be slower in general compared with a Java implementation for dynamic typing but this is not always necessary. In addition, I have seen unexpected things happening when using ImgLib2 from Jython because Jython expects an Iterable<E> to deliver independent E instances. ImgLib2 is fast and memory effective because E may be a re-used proxy. We stumbled into Jython implementing a lot of Python sweetness by copying data which may leed to things not work as expected. E.g.

for (a,b) in zip(img1,img2) :
  a.set(b)

will unfortunately not work because zip apparently creates a reference copy of img1 and img2 by iteration beforehand which then contains only references to the last pixel of img1 and img2 respectively.

Best regards, Stephan

1 |
Stephan Saalfeld
| 2012/11/06 16:41 | reply
blogtng/2012-10-28/imglib2_first_test.txt · Last modified: 2016/05/24 12:46 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki