Friday, June 19, 2015

VTK 5 and FFMPEG shenanigans on Windows

Over the years, trying to get VTK 5 to work with FFMPEG has always been tricky. Thankfully, VTK 6 has no such problems, but for those that have legacy code that use VTK 5, this is still a problem.

In this post I will cover some necessary tweaks, steps and links to getting FFMPEG IO working with your project that uses VTK 5, such as the 'Animate' plugin for sMILX and SMILI.

Firstly, I have found VTK 5.8 to be far more stable and workable than 5.10.1. In my scientific visualisation software SMILI, certain features don't work at all with the same code that runs fine on VTK 6 and 5.8.

Secondly, it seems VTK 5 has issues with Visual Studio 2013 (required to support Windows 8), but a patched version of VTK 5.10.1 available on GitHub works OK, though I had to fix a few round brackets here and here.

For version 1.2 of FFMPEG, this is what I recently did to get VTK 5.8 working with FFMPEG. The best link for FFMPEG deprecation changes are found here. Summarised, I had to fix vtkFFMPEGWriter.cxx as the following:
  1. av_set_parameters  - comment out
  2. URL_WRONLY to AVIO_FLAG_WRITE
  3. url_fopen to avio_open and url_fclose to avio_close
  4. av_write_header to avformat_write_header, last arg to NULL
EDIT: You may also need AVCodecID, PKT_FLAG_KEY is replaced by AV_PKT_FLAG_KEY and replacing CODEC_TYPE_VIDEO with AVMEDIA_TYPE_VIDEO.
EDIT 2: I have created a GitHub VTK 5.8.0 fork with these changes applied.

EDIT 3: GCC 9.1 causes issues. It can be fixed by setting CMAKE_CXX_FLAGS as  -fpermissive -std=c++98 -DGLX_GLXEXT_LEGACY

No changes are required for VTK 6.1.0 at the time of writing.

Hope that helps
Cheers Shakes - L3mming

Friday, June 5, 2015

Mesh/Surface Processing with Command-line SMILI tools

I recently had to do some processing for a prostate segmentation scheme I've been working on and thought some uses of SMILI tools would be helpful to others. Majority of surface processing tasks can be achieved with the milxModelApp in SMILI, a easy to use open source medical imaging library and viewer.

My tasks involved involved:
  1. copying scalars from an atlas mesh to lots of other meshes
  2. using scalars to clip the meshes
  3. computing the surface distance of the meshes to their corresponding labelled images that were created by clinical experts
  4. computing the scalar statistics across the population of meshes (my meshes already have point to point correspondence) 
Luckily, the milxModelApp application provides most of these without needing to script for multiple surfaces. Furthermore, the Qt framework is not required for these applications as they are VTK/ITK only applications (i.e. built on milxSMILI, the GUI-independent sub-library of SMILI).The following examples are for Version 0.998 (SMILI Release Beta 1).

Each one of the above tasks can be achieved as:
  1. The --scalarcopy  option in milxModelApp provides a way to do this. I did:
    milxModelApp --scalarcopy focus_atlases/focus_bladder_atlas.vtk results/bladder/asm_bladder_*.vtk -p results_scalars/bladder/
    Copy scalars from atlas mesh (focus_bladder_atlas.vtk) to other meshes in directory (results/bladder/asm_bladder_*.vtk) and output to another directory with same names.
  2. The --clip  option in milxModelApp provides a way to do this. I did:
    milxModelApp --clip 1 results_scalars/bladder/asm_bladder_*.vtk -p results_clipped/bladder/
    Clip meshes in directory keeping only parts with value of 1 and output to another directory with same names.
  3. We need to write a script for the milxHausdorffDistance application that provides this using distance maps in a straight forward way. This script is now in the repository as scripts/ batch_hausdorff.py. An example usage of the application:
    milxHausdorffDistance results_clipped/bone/asm_bone_4.vtk -p Hausdorff/bone/bone__ -o Hausdorff/bone/bone__004.vtk --label manuals_renamed/bone/manual_case_bone_004.nii.gz --labelvalue 1 -c 004
    The distance map of the manual is created and the distances stored on the mesh thus giving the surface distances to the manual.
  4. The --scalarstats option in milxModelApp provides this. I did:
    milxModelApp --scalarstats Hausdorff/bladder/bladder__*.vtk -o bladder_stats.vtk
    Compute scalars stats (mean, variance etc. per point) of meshes in directory and output single mesh (of first mesh) with stats as arrays in mesh. You can then use sMILX viewer to view the meshes and change the loaded arrays via the Right Click->Show->Load Array menu.
Note that the milxDeformableModel app is an application derived from milxModelApp and additionally provides options for voxelising surfaces and applying image orientation to surfaces.

Hope this helps
Cheers Shakes - L3mming