Monday, 23 May 2016

Matlab memory management

A couple of quick tips if you run out of memory in Matlab. All of these commands will have an almost insignificant impact on your actual work, but they might be useful in some occasions when Matlab gets cranky. It has happened to me before that Matlab runs out of "heap memory" when opening and closing figures. Then all you want to do is to save your work, exit and relaunch Matlab, but Matlab might complain that it doesn't have enough memory for that. So I'm listing a couple of commands that might just about allow you to save and exit without losing the content of your workspace.

  • pack This command calls Matlab's garbage collector. It only works from the command line, and if you call it inside a procedure it will return an error. You shouldn't need to use it, as Matlab calls its garbage collector automatically, but it might still be helpful if you're using some other software along with Matlab and you're running low on memory.
  • java.lang.Runtime.getRuntime.gc This command calls Java's garbage collector. Matlab's UI is largely written in Java, and when you open a lot of figures you sometimes incur in out of Java memory errors. This command has been helpful in some occasions as it's given me some leeway to save my work and restart Matlab.
  • java.lang.Runtime.getRuntime.freeMemory This command doesn't really free any memory, but it will show you the amount of memory available for the Java runtime environment. Using this you'll clearly see the effect of the previous gc command.

Monday, 8 February 2016

Odd behaviour of imresize in Matlab

I stumbled across what I would classify as a bug in Matlab's imresize. Try out the following snipped of code:

little1 = imresize(IM, 0.2, 'nearest');
[M, N] = size(little1(:,:,1))
little2 = imresize(IM, [M, N], 'nearest');

I would expect little1 to be exactly the same as little2. If I wrote a routine to rescale images, I'd probably take as input the final dimensions [M,N], and if I had to handle a single scaling factor I'd use that to calculate the final width and height for the previous case.

It is not so in Matlab. I don't know exactly what's going on there, I don't have the time to debug imresize and see what happens. But if you try the snipped of code above for any image IM, you'll find that norm(little1(:)-little2(:)) is not 0, and in fact you can also imshow the absolute value of the difference and see where the resizing differs. Indeed, the picture below is exactly that.

This little quirk costed me probably about two days worth of work! I hope I've saved you some headaches by sharing this.

Friday, 7 August 2015

Matlab's repmat in Python

This post is partly to remind myself of this, partly for others who might find themselves in a similar situation. I find myself wanting to use a repmat function in Python - used as I am to Matlab's syntax. A quick search will tell you that the function to use is numpy.tile, and that's indeed true.

But, say that you have an image of shape (1024,512) and you'd like it to become (1024,512,3). What's the way to go? In Matlab you would just say

B = repmat(A,[1,1,3]);

and if you try that with np.tile you'll find that B has shape (1,1024,1536). Somehow, it's added a new dimension at the beginning, not at the end!

To obtain the same behaviour as Matlab, you have to do

B = np.tile(A.reshape(1024,512,1), (1,1,3))

In practice you're explicitly adding a dimension to the array A before tiling it.

Having said that, numpy does something that Matlab doesn't: it broadcasts operators. So if you have two arrays of different dimensions, numpy can automatically repeat the same operation (a bit like Matlab's bsxfun). The catch is that the operation is repeated over the first dimension of the array. So let's say we want to add A of shape (1024,512) and B of shape (1024,512,3). The way I'd go about doing that is with transposes:

C = A.T + B.T
C = C.T

Transposition in numpy is more generic than in Matlab and can be applied to n-dimensional arrays. It changes the dimensions so that that an array of size w,x,y,z its transpose will have size z,y,x,w. So that's now adding matrices of shapes (512,1024) and (3,512,1024), which works because the broadcasting happens along the first dimension. Then, of course, the result needs to be transposed back.

Wednesday, 29 July 2015

Compiling OpenCV on Yosemite

I found myself wanting to use some OpenCV features from Python. But I prefer to use Python 3, which made the Homebrew distribution of OpenCV almost useless - as the version coming with Homebrew doesn't support it. The only option was then compiling OpenCV 3.0.0. Here's how I went about doing it.

For the following, I'm assuming you're using Python 3.4.3 coming with Homebrew. Note that future updates might break the compilation, so proceed with care. Also, the OpenCV distribution that comes with Homebrew mustn't be installed or you'll have problem linking this one later.

The first step is downloading OpenCV 3.0.0 - using git works just as well as downloading the zip file.

git https://github.com/Itseez/opencv.git
cd opencv
mkdir release
cd release

Now I'm assuming you'd like to keep your installation tidy, and the best way is to let Homebrew handle this. The next command will let you configure the compilation, and to do so you will have to set some variables. The command to launch is

ccmake ..

You need to fill in the following variables:

CMAKE_INSTALL_PREFIX/usr/local/Cellar/opencv/3.0.0
PYTHON2_EXECUTABLE/usr/local/bin/python3.4
PYTHON3_EXECUTABLE/usr/local/bin/python3.4
PYTHON3_INCLUDE_DIR/usr/local/Frameworks/ Python.framework/Versions/3.4/ include/python3.4m
PYTHON3_LIBRARY/usr/local/Frameworks/ Python.framework/Versions/3.4/ lib/libpython3.4.dylib
PYTHON3_NUMPY_INCLUDE_DIRS/usr/local/lib/python3.4/site-packages/numpy/core/include
PYTHON3_PACKAGES_PATH/usr/local/lib/python3.4/site-packages

Now, CMAKE_INSTALL_PREFIX is what will later allow Homebrew to handle your installation of OpenCv. Also, you might notice that PYTHON2_EXECUTABLE is actually set to Python 3. For reasons beyond me, without that it doesn't look the Python bindings are compiled correctly so, well, whatever works.

At this point, you can check that cmake is happy with what you've done with Python. To do so, first of all, save your configuration by pressing <C> from the keyboard, and then <Q>. Then, just type

cmake ..

and you should see the following:

--   Python 2:
--     Interpreter:                 /usr/local/bin/python3.4 (ver 3.4.3)
--
--   Python 3:
--     Interpreter:                 /usr/local/bin/python3 (ver 3.4.3)
--     Libraries:                   /usr/local/Frameworks/Python.framework/Versions/3.4/lib/libpython3.4.dylib (ver 3.4.3)
--     numpy:                       /usr/local/lib/python3.4/site-packages/numpy/core/include (ver 1.9.2)
--     packages path:               /usr/local/lib/python3.4/site-packages
--
--   Python (for build):            /usr/local/bin/python3.4

This way you should be confident that the compilation process will generate all your Python bindings. And now we go with the usual

make
make install

and of course, to make sure that Homebrew will take care of your installation,

brew link opencv

If you want to make sure that the Python binding has been compiled, you should find the file lib/python3/cv2.so inside your release directory.

And finally, one little catch. Keep in mind that this cv2.so will end up inside your python site-packages, i.e., outside the reach of Homebrew. An alternative might be to set PYTHON3_PACKAGES_PATH somewhere inside the Cellar, and then add it to your PYTHONPATH variable, but I don't know if that will work or not.

Friday, 7 February 2014

A rather impressive demo

I'm not sure what would push anyone to do this, but hats off. Here's a Super Mario Bros demo that runs in Matlab. I haven't really had the time to skim through the code, but I'm impressed with the effort it must have taken to get this to work at 60 fps.

Tuesday, 3 September 2013

Undocumented Matlab

I'm not writing here nearly as often as I'd like, but as the theme of the latest few posts has been Matlab I thought it would be appropriate to continue in the same fashion.

I came across a very interesting blog about undocumented Matlab functions. It has all sort of tips and tricks: for example, did you know you can have Matlab to run using a more recent JVM? No? Me neither. (But there are very few reasons why anyone would want to do it.) Or, did you know you can force Matlab to use a new (still beta) version of the handle graphics (i.e., the component that draws the plots)? No? I had no idea either. This could be useful as the new graphics look a lot better than the usual ones.

Well, I've given you the source of all that, so dive in and enjoy...

Tuesday, 29 January 2013

Functional programming in Matlab

I came across a very interesting blog post recently. I'll just link it here so you can read it at the source. But to give you a cliffhanger, how would you write a min_and_max function in Matlab, that does this:

[extrema, indices] = min_and_max(y);

You could write an m-file but the alternative is the following mind-blowing and very clever one-liner:

min_and_max = @(x) cellfun(@(f) f(x), {@min, @max});

I love it. Check out the original blog post on Loren on the Art of Matlab for an explanation on how it works.