Cris’ Image Analysis Blog

theory, methods, algorithms, applications

DIPimage 2.4 released

I’m pleased to announce that a new version of DIPimage has been released. There’s some performance improvements, some bug fixes, and some new functions. The measure function has some new features also, that use the convex hull of the objects. The Feret measure is computed differently now, also using the convex hull. This makes this computation more accurate and also somewhat faster.

But most importantly, we have rewritten a lot of the code that does binary arithmetic and logic operators. Binary here means these operators take two inputs. +, -, *, &, > and == are examples of binary operators. All of these used to be computed using MATLAB code, which required some nifty tricks. For example, computations between images of different type (i.e. an 8-bit integer image added to an 16-bit integer image) used to require data conversion because MATLAB cannot perform such a computation. All of these binary operators are now computed by DIPlib instead. This makes some cases much more efficient. We parallelized the arithmetic and logic code in DIPlib for further speed improvements.

One added benefit of the new implementation is that these operators now all have built-in singleton dimension expansion. What this means is that, if one image has a dimension with size one (a singleton dimension), and the corresponding dimension in the other image has a larger size, the first image is automatically replicated to match the size of the first. For example, assume we have these two images:

a = readim('chromo3d');
t = mean(a,[],[1,2]);

The image a, one of the standard images that come with DIPimage, has a size of 160x140x16 pixels. The image t has a size of 1x1x16 pixels. This image contains the average intensity in each 2D plane of image a. If we now want to divide each 2D plane by its average, we want to do a/t, except that the two images have different sizes! One way around this is to replicate the smaller image using repmat:

a = a / repmat(t,imsize(a,1),imsize(a,2),1);

This requires lots of memory, because a large array is created by repmat. Another option is to do the operation on each 2D slice using a for loop:

for ii=0:imsize(a,3)-1
    a(:,:,ii) = a(:,:,ii)/t(ii);
end

This method is slower, because a slice has to be extracted and inserted into the image a. MATLAB has a relatively new function, bsxfun (binary singleton expansion function), which can efficiently calculate our operation (see for example this post by Loren). Of course, it doesn’t work with dip_image objects, and also requires that the two inputs are of the same data type, so we convert the images to single-precision floating-point arrays:

a = bsxfun(@rdivide,single(a),single(t));
a = dip_image(a);

This looses a lot of the efficiency because the large image must be converted to single. Luckily, DIPlib has had binary singleton expansion included in its operators since its inception. Now these operators are used by DIPimage, so we can simply type:

a = a / t;

and obtain the same result we have been after!

For a full log of changes see the DIPlib website.