IPSDK  4_1_0_2
IPSDK : Image Processing Software Development Kit

module demonstrating the computation of boundary on a 2d binary image More...

module demonstrating the computation of boundary on a 2d binary image

Overview

This application computes the boundary image on a 2d binary input image loaded from a given input RAW file, and saves the result in a given RAW file.

See also
boundary 2d morphological algorithm

Usage

The application can be called through a command line as follows:

   <application_exe_filename> [--inputImgFilePath <input_image_file_path>] [--outputImgFilePath <output_image_file_path>]
     
   Arguments:
      --inputImgFilePath  optional; specifies the name of the RAW file, from
                          which the 2d binary input image will be loaded; if not 
                          specified by the user, the input image is loaded from
                          file 
                          <DEV_ROOT>/data/Sample/images/MorphoBin2d1.raw
                          
      --outputImgFilePath optional; specifies the name of the RAW file, in
                          which the 2d output image resulting from the 
                          boundary extraction will be saved;
                          if not specified by the user, the output image is 
                          saved in file
                          <TEMPORARY_IPSDK_DIR>/Sample/boundary.raw

      --imgXSz            mandatory if inputImgFilePath option is specified,
                          ignored otherwise; specifies the width of input image

      --imgYSz            mandatory if inputImgFilePath option is specified,
                          ignored otherwise; specifies the height of input image

Here is a snapshot of default input image used by the application and of corresponding output image when application is launched without any argument:

Sample_Boundary2d.png

Source code documentation

The sequence of operations executed by this application is very similar to other samples. However, we can notice in particular that, this time, instead of using TIFF file format to load/save images, we use RAW file format.

We start by including all necessary header files:

// --- IPSDK includes
// ------------------
// used to initialize IPSDK environment
#include <IPSDKCore/Config/LibraryInitializer.h>
// used to extract the boundary from the input image
// used to manage exceptions possibly thrown by algoritms functions
#include <IPSDKBaseProcessing/Logger/IPSDKBaseProcessingException.h>
// for BaseImageGeometry
#include <IPSDKImage/Geometry/BaseImageGeometry.h>
// for function "geometry2d"
// for ImageGeometryPtr typedef
// used to catch exceptions potentially thrown by functions loadRawImageFile and saveRawImageFile
#include <IPSDKImageFile/Logger/IPSDKImageFileException.h>
// used to read/write an image from/to a RAW file:
// used to retrieve usual folders (IPSDK temporary folder, root development folder, etc.)
// used to display log messages
// --- third-party boost includes
// ------------------------------
// boost/filesystem/*: contains functions and classes providing facilities to
// manipulate files and directories, and associated paths
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/convenience.hpp>
// boost/program_options/*: contains functions and classes used to manage and
// interpret arguments of command line
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
// --- third-party log4cplus include
// ---------------------------------
// used to add console as output support of logs
#include <log4cplus/consoleappender.h>
// --- STL include
// ---------------
// for std::cout
#include <iostream>

In the main function body, we start by asking to display all the log messages generated by IPSDK libraries and by our application itself to the application console:

int
main(int argc, char* argv[])
{
// add console appender for application logs
log4cplus::SharedAppenderPtr pConsole(new log4cplus::ConsoleAppender);
log4cplus::Logger::getRoot().addAppender(pConsole);
log4cplus::Logger::getRoot().setLogLevel(log4cplus::INFO_LOG_LEVEL);

Next, we initialize the IPSDK environment:

// initialize IPSDK environment (first call to be done before calling any
// function or using any entity of IPSDK environment)
switch(initRes.getResult().value()) {
case ipsdk::core::eLibInitStatus::eLIS_Warn:
// IPSDK library is initialized but there were warnings;
// notify the user by displaying a message
break;
case ipsdk::core::eLibInitStatus::eLIS_Failed:
// IPSDK library initialization; notify the user and exit
return -1;
break;
default:
break;
}

Then we declare objects 'inImgFilePath' and 'outImgFilePath'.

// boost objects, used to store input and output images files paths
boost::filesystem::path inImgFilePath, outImgFilePath;

We also declare the variables that will store the dimensions of input image:

Paths and image dimensions are initialized from the command line thanks to the call of the "readCmdArguments" function:

// read program options from command line, and, if appropriate,
// initialize input and output images files paths
if(!readCmdArguments(argc, argv, inImgFilePath, outImgFilePath,
imgXSz, imgYSz))
return -1;

Once the IPSDK environment is correctly initialized, we load our input image from the associated RAW file, by calling the function ipsdk::image::file::loadRawImageFile. Contrary to other image file formats such as TIFF, RAW files don't contain neither image dimensions information, nor number of channels or pixel data type. That's why "loadRawImageFile" function takes one more argument compared to a function such as "loadTiffImageFile": the geometry of the image. This geometry is represented with the type BaseImageGeometry, and is initialized here with the function geometry2d, that takes 3 arguments: the pixel data type, and the width and the height of the image.

The call of "loadRawImageFile is enclosed in a try/catch block, to handle the case where an exception is thrown by loadRawImageFile (if the file is not found or corrupted, for instance). If an error occurs, a message is displayed to the user, IPSDK environment is cleaned by calling "ipsdk::core::LibraryInitializer::getInstance().clear()" and the application terminates.

// declare the variable that will contain the input image, loaded from
// RAW file
// declare and initialize pImageGeometry variable, used to specify pixel type
// and dimensions of input image (contrary to TIFF format, RAW images don't
// contain this information)
ImageGeometryPtr pImageGeometry =
geometry2d(eImageBufferType::eIBT_Binary, imgXSz, imgYSz);
try {
// read input image from specified path
pInImg =
image::file::loadRawImageFile(inImgFilePath, *pImageGeometry);
} catch(const image::file::IPSDKImageFileException& e) {
// loadRawImageFile function threw an exception; display error log
// message
% inImgFilePath.string() % e.getMsg());
// clear IPSDK environment features; should be called before exiting
// program
// quit the application with an exit code indicating an error
return -1;
}

We can now apply the "boundary" operation on our freshly loaded input image, by calling "ipsdk::imaproc::morpho::boundary2dImg". This function takes our object pInImg, and returns the resulting image in an object of type ImagePtr, that we store in our variable pOutImg.

Once again, the call of "boundary2dImg" function is enclosed in a try/catch block to handle any failure during this operation. If the operation fails, we notify the user and clean IPSDK environment before exiting.

// declare the variable that will contain the output image, resulting from
// boundary extraction
ImagePtr pOutImg;
try {
// compute boundary image
} catch(const processor::IPSDKBaseProcessingException& e) {
// one of the 2 previous function calls
% e.getMsg());
// clear IPSDK environment features; should be called before exiting
// program
// quit the application with an exit code indicating an error
return -1;
}

If all the previous operations were successfully completed, we save the image resulting from the "boundary" operation to the RAW file specified by the user (or to a default RAW file, if the user did not specify anything), by calling the function "saveRawImageFile".

try {
// save the resulting image in specified path
ipsdk::image::file::saveRawImageFile(outImgFilePath, pOutImg);
} catch(const image::file::IPSDKImageFileException& e) {
% outImgFilePath % e.getMsg());
// clear IPSDK environment features; should be called before exiting
// program
// quit the application with an exit code indicating an error
return -1;
}

Finally, the program cleans the IPSDK environment and exitings:

// clearing IPSDK environment features; should be called before exiting
// program
return 0;
}

See the full source listing