DIPimage 2.6 released
Today we released version 2.6 of DIPimage and DIPlib. The change list is rather short. There are two items that I think are important: 1) We fixed a bug that caused an unnecessary copy of the output image(s) in the DIPlib-MEX interface, slowing down functions especially for large images. 2) We introduced a new setting to automatically make use of a feature introduced in the previous release.
The bug
Thanks to some attentive users, and some nifty sleuthing by a colleague, we were able to track down a curious bug: it
seems that, when the DIPlib-MEX interface created a dip_image
object, the data array inside the object would be copied
while exiting the MEX-file. I am very sure that this did not happen when we first developed the interface (way back in
1999, when the newest MATLAB version was 5.3!). I don’t know when this “new behaviour” was introduced, but it certainly
wasn’t announced in the release notes. We now avoid the copy by creating an empty object, and then inserting the data
array into it.
For simple functions working on large images, the impact of this bug was huge. For example, a simple arithmetic operation on a large image is completely limited by the speed at which memory can be accessed. Computing the division with a constant takes just as much time as making a copy of the data. Let’s test this:
a = repmat(readim,[6,7,20]);
timeit(@()(a/2))
ans =
1.3306
I created a large image by replicating a standard image; the size of a
is 1536×1792×20 = 55 Mpixels, of type uint8
.
Then I time the division of this image by 2. This produces a single-precision floating-point (sfloat
) image. The
computation time was 1.33 s with DIPimage 2.5.1. Let’s restart MATLAB with the new version of DIPimage, and repeat the
experiment:
a = repmat(readim,[6,7,20]);
timeit(@()(a/2))
ans =
0.6345
As expected, the computation time is about half. For more complex functions, the difference might not be as dramatic, but it certainly is worth upgrading!
A new setting
In the previous version of
DIPimage we introduced the ability to do arithmetic operations and specify the data type of the output image
. By default, DIPimage usually chooses sfloat
as the output data type. This is to avoid unexpected results, as keeping
the data type of the image typically leads to rounding errors or overflow, which can simply be avoided by choosing a
floating-point data type. Note that this default behaviour is usually what is expected, and frees the user from having
to think about what data type to use.
However, sometimes advanced users want to control the output data type. For example, when working with very large
images, it can be convenient (saves time, avoids memory problems) to use only uint8
or uint16
data types (a sfloat
image takes up 4 times as much space as a uint8
image). In the previous version of DIPimage, one could then type, for
example, dip_arith(a,2,'div','uint8')
instead of a/2
. Not very elegant, not very readable, but hey! it saves up
memory space!
With the new version of DIPimage comes a new setting, called 'KeepDataType'
. It causes the output of arithmetic
operations to be the same as that of the input images. If the types are different, then the larger of the two types is
chosen, except if one of the inputs is a MATLAB array, as we only look at the data type of the image. This simplifies
the use of the memory-saving feature, as the choice made is usually a good choice. However, note that overflow and
rounding errors can (and will) occur! Let’s try the same division as before, but using the new setting:
dipsetpref KeepDataType on
a = readim;
a = repmat(a,[6,7,20]);
timeit(@()(a/2))
ans =
0.3595
As you can see, since the output image is only a fourth the size it was before, it takes a lot less time to write the output to memory. But again, be careful when using this feature! You will get unexpected output if you’re not careful!