Thursday, May 03, 2012

A short note about using Canon EDSDK


I had been trying to automate an imaging process using a Canon 40D and Canon EDSDK 2.10. Basically, I wanted the camera to take a picture and send the image (directly from the camera buffer) to my computer. The computer would save/process the image afterwards.

I didn't want to have the camera saved the images on the memory card, since I needed to take a lot of images and I only had a 2 GB card.

I followed the samples in the Canon EDSDK API document and the VC sample code. My code was written in C.

At start, I couldn't have the object event handler worked properly. No object event was detected, even property and camera state events could be found. After countless attempts, I finally know why. I wrote what I found here and hope that it will be useful for other people as well.

1. Add a Windows message loop. 
It seems that the EDSDK relies on the Windows message loop to fire and dispatch events. Without it, no object event can be fired (so the object event handlers are never called).



Note that my code is written in Visual C++ Express 2010, and the subsystem in the project setting is Console (not Windows).

2. Set kEdsPropID_SaveTo property to SaveTo_Host. 



Somehow this property on my camera was set to SaveTo_Camera. Therefore, event 520 (kEdsObjectEvent_DirItemRequestTransfer) had never been fired after a picture was taken. Set it to SaveTo_Host and everything is fine.

3. Catch event kEdsObjectEvent_DirItemCreated
It is possible to retrieve the image from the memory card when kEdsPropID_SaveTo property is set to SaveTo_Camera. The workaround is to catch is event 516 (kEdsObjectEvent_DirItemCreated). As this is more like a trick, I do not recommend using it.

Ensure that the memory card is inserted to the camera. Otherwise, no event 516 can be generated.

Saturday, March 24, 2012

Windows CMD string concatenation

To update a variable in a for loop in Windows batch script we need to call subroutines. Here is an example script that concatenates all .txt filenames to a variable using Windows CMD.


@echo off
rem List and concatenate all .txt filenames to a variable
set files=
for /f %%F in ('dir /B *.txt') do call :concat %%F
echo %files%
goto :eof


:concat
set files=%files% %1
goto :eof

See more at: http://ss64.com/nt/ and http://stackoverflow.com/questions/2027070/batch-file-string-concatenation

Friday, March 09, 2012

Videolectures.net RTMP streaming URL


Videolectures.net is a great website that provides videos and slides of several lectures and talks. Due to some technical reasons, they have not provided links to download their videos yet. If you want to download the video, you will need to get the streaming URL yourself. Here is how.

Videolectures.net uses Flowplayer to stream video using RTMP protocol. The streaming URL of a video on their website comprises of three parts:
Streaming URL = clip.netConnectionUrl + sub_folder + clip.url
where
sub_folder is the folder that contains the lecture page.
clip.url is the relative URL to the video.
clip.netConnectionUrl is the base URL pointing to the RTMP streaming server.

You can easily find out sub_folder in the URL of the webpage that contains the lecture you are viewing. You can look for the value of clip.url and clip.netConnectionUrl in the source code of the webpage.

For example, suppose you are browsing for the lecture at http://videolectures.net/cvpr2010_ecker_psfs/. Then we have:
sub_folder : cvpr2010_ecker_psfs
clip.url   : flv:v001/bb/xo3o537fdbo7kpfidhxsfu6ecc5rn2rj
clip.netConnectionUrl : rtmp://oxy.videolectures.net/video

Concatenating the above strings, the RTMP streaming URL is
rtmp://oxy.videolectures.net/video/cvpr2010_ecker_psfs/flv:v001/bb/xo3o537fdbo7kpfidhxsfu6ecc5rn2rj/

You can now use ffmpeg or VLC to stream and save the video to your PC. For example, simply try
ffmpeg -i <input URL> <output file>



Wednesday, February 22, 2012

Compile Numpy and Scipy with Intel Math Kernel Library

Intel Math Kernel Library (Intel MKL) comes with its own LAPACK and BLAS implementation that optimizes for Intel processors. Compiling and link Numpy and Scipy with Intel MKL can be a good way to speed up your computations.

For example, in my case, the DGETRF function, which performs LU decomposition, of Intel MKL is about 40% faster than the same function in Debian's default LAPACK and ATLAS implementation. Specifically, I was able to reduce the running time of the LU decomposition call on a (3444, 2846) matrix from ~2.5s (the default LAPACK) to only ~1.5s (Intel MKL). The computation is on an Intel Core 2 Quad Q9550 CPU with 4 GB of RAM. This can be considered as a good speedup to me since I need to perform the LU decomposition several times (say, hundreds to thousands).

This tutorial will list out necessary steps to compile Numpy and Scipy using Intel C compiler  and link them with Intel Math Kernel Library (Intel MKL) to make use of its optimized LAPACK and BLAS implementation for Intel processors. The Python version is 2.7.

For preparation, let us clone the git repositories of Numpy and Scipy to your local machine and check out the latest stable versions. When this note is written, the stable version for Numpy is v1.6.1 and for Scipy is v0.10.1rc1.
$ git clone https://github.com/numpy/numpy.git
$ git checkout v1.6.1
$ git clone https://github.com/scipy/scipy.git
$ git checkout v0.10.1rc1

1. Compiling Numpy
To compile Numpy, we will need Intel C++ Composer XE, which bundles the C/C++ compiler and also includes the Intel MKL. To compile Scipy, we need to further install Intel Fortran Composer as well. These compiler suites are free for non-commerical use and you can easily download them from Intel's website. Unpack the tar packages, run ./install.sh and install the compilers by following the instructions on the screen.

Let us assume that the compilers are installed at /opt/intel/composer_xe_2011_sp1.9.293/. Note that the version of the Intel C and Fortran Composer is 1.9.293 in this tutorial. You may have a newer version number.

Now let's compile Numpy first. Go to numpy/numpy/disutils folder and edit the intelccompiler.py file. This file contains compiler flags for each processor architecture. On a 32-bit system, it is necessary to modify the IntelCCompiler class, in which the compiler type is intel. Since we are building for a 64-bit system, we will modify the IntelEM64TCCompiler class, which has the compiler type intelem. I set the self.cc_exe to 'icc -m64 -fPIC -O2 -g -openmp' and commented out the cc_exe and cc_args defined just before the __init__ function. These two variables seems not being used. Remember that we will later set the --compiler and --fcompiler (for Fortran for Scipy) both to intelem. If you are compiling on a 32-bit machine, be sure to set them to intel.

Next, copy site.cfg.example in Numpy's source folder and name it site.cfg. Add the following lines to site.cfg.
[DEFAULT]
library_dirs = /opt/intel/composer_xe_2011_sp1.9.293/compiler/lib/intel64:/opt/intel/composer_xe_2011_sp1.9.293/mkl/lib/intel64
include_dirs = /opt/intel/composer_xe_2011_sp1.9.293/mkl/include

[mkl]
mkl_libs = mkl_def, mkl_intel_lp64, mkl_intel_thread, mkl_core
lapack_libs = mkl_lapack95_lp64
libraries = iomp5

Save site.cfg. Remember to remove any existing build folders before compiling.
$ rm -rf build
Compile Numpy using
$ python setup.py config --compiler=intelem build_clib --compiler=intelem build_ext --compiler=intelem build

Now we can proceed to install Numpy
$ sudo python setup.py install

You can now proceed to test whether the new Numpy works. First, we need to set the LD_LIBRARY_PATH environment variable to those library folders in the Intel C and Fortran compiler suite. This can be done easily by:
$ export LD_LIBRARY_PATH=
$ source /opt/intel/composer_xe_2011_sp1.9.293/bin/compilervars.sh intel64
$ source /opt/intel/composer_xe_2011_sp1.9.293/mkl/bin/mklvars.sh intel64
LD_LIBRARY_PATH will be automatically set after calling compilervars.sh and mklvars.sh. Now start iPython in the same bash shell and import Numpy. Numpy should be imported without any errors. If you want to run numpy.test(), be sure to have the python-nose package installed on your system. It will perform a bunch of tests to see if Numpy computes some example problems correctly.
>>> import Numpy
>>> numpy.show_config()
>>> numpy.test() 

2. Compiling Scipy
After Numpy is compiled and installed, Scipy can be compiled in almost the same way. First, the site.cfg file we made for Numpy compilation can be used for Scipy, too. Copy site.cfg from the Numpy folder to the Scipy folder, remove any existing build folder, and build Scipy using:
python setup.py config --compiler=intelem --fcompiler=intelem build_clib --compiler=intelem --fcompiler=intelem build_ext --compiler=intelem --fcompiler=intelem build

After Scipy is compiled, we can now install it. Notice that I was *not* able to execute
$ sudo python setup.py install
successfully because setup.py under sudo cannot find the needed libraries under LD_LIBRARY_PATH set previously. I ended up running setup.py under root, which requires us to set the LD_LIBRARY_PATH one more time.
$ su
# export LD_LIBRARY_PATH=
# source /opt/intel/composer_xe_2011_sp1.9.293/bin/compilervars.sh intel64
# source /opt/intel/composer_xe_2011_sp1.9.293/mkl/bin/mklvars.sh intel64
# python setup.py install

Everything should be running well. You can now test Scipy by using
>>> import scipy
>>> scipy.show_config()
>>> scipy.test()


Appendix

Note that in site.cfg, the library iomp5 is necessary. It contains the symbols used in mkl_intel_thread library. If iomp5 is not linked during compilation of Numpy,  you still can compile Numpy successfully, but when you start importing it (say, in iPython):
>>> import numpy
you will get an exception saying undefined reference to `__kmpc_reduce_nowait' in mkl_intel_thread.so. You may want to verify this by doing a quick check on the symbols defined in mkl_intel_thread.so and libiomp5.so. You will see that
$ nm mkl_intel_thread.so | grep nowait
returns none. And
$ nm libiomp5.so | grep nowait 
shows that the __kmpc_reduce_nowait is defined in libiomp5.

Chapter 5 of Intel MKL document also suggests that libiomp5 is necessary besides the layers mkl_intel_lp64 (interface), mkl_intel_thread (threading), mkl_core (computation), as it is a runtime library.

A few sources on the web suggests adding iomp5 to mkl_libs. However, I found that this does not work. I need to add the line libraries = iomp5 to make it link correctly.

Also notice that mkl_def is needed; otherwise runtime error MKL_FATAL_ERROR: Cannot load neither xxxx will appear when calling some functions in Intel MKL from Numpy.