Tuesday 17 April 2012

Distance Transformation Labels/Features

Distance transformation functions on most of the libraries (OpenCV, VXL etc.) only output the distance transformation. However, must of the time we also need the label/position of the shorted distance point along with the shortest distance for a given point, which is often referred as distance transformation feature in computer vision and machine learning. Following is the simplest implementation of distance transformation feature in C++  using OpenCV library.
   
 //============================================================================  
 // Name    : OpenCVTest.cpp  
 // Author   : Rudra Poudel  
 // Description : Example of distance transformation features. To find the shorted distance label we travel shorted distance path i.e. kind of gradient descent.  
 //============================================================================  
   
 #include "opencv2/core/core.hpp"  
 #include "opencv2/imgproc/imgproc.hpp"  
 #include "opencv2/calib3d/calib3d.hpp"  
 #include "opencv2/highgui/highgui.hpp"  
 #include <stdio.h>  
 #include <iostream>  
   
 #define VIDEO_FRAME_HEIGHT 480  
 #define VIDEO_FRAME_WIDTH 640  
 void VerifyDistTransformLabels(cv::Mat& depth_map, cv::Mat& labels, int row_start, int row_end, int col_start, int col_end) {  
  for( int y = row_start; y < row_end; y++ ) {  
   //src_data_row = dist_trans.ptr<float>(y);  
   for( int x = col_start; x < col_end; x++ ) {  
   
    cv::Vec2i alabel = labels.at<cv::Vec2i>(y,x);  
    assert(alabel[0] != -1);
    assert(alabel[1] != -1);
   
   }  
  }  
 }  
 cv::Vec2i GetLowestDistNeighbour(cv::Mat& dist_trans, int x, int y){  
  int x_start = x>0 ? x-1 : 0;  
  int y_start = y>0 ? y-1 : 0;  
   
  int x_end = x<(dist_trans.cols -1) ? x+1 : x;  
  int y_end = y<(dist_trans.rows -1) ? y+1 : y;  
   
  cv::Vec2i p; //p[0] = x; p[1] = y; assignment not necessary  
  float min_dist = dist_trans.at<float>(y, x);  
  float dist;  
  for( int row = y_start; row <= y_end; row++ ) {  
   for( int col = x_start; col <= x_end; col++ ) {  
    dist = dist_trans.at<float>(row, col);  
    if(dist<min_dist) {  
     min_dist = dist;  
     p[0] = col;  
     p[1] = row;  
    }  
   }  
  }  
   
  return p;  
 }  
 cv::Vec2i GetDistTransformLabel(cv::Mat& dist_trans, cv::Mat& labels, int x, int y) {  
   
  if(dist_trans.at<float>(y,x) == 0) {  
   cv::Vec2i alabel(x,y);  
   return alabel;  
  } else {  
   cv::Vec2i p = GetLowestDistNeighbour(dist_trans, x, y);  
   cv::Vec2i& alabel = labels.at<cv::Vec2i>(p[1], p[0]); // (y, x)  
   if(alabel[0] == -1 )  
    alabel = GetDistTransformLabel(dist_trans, labels, p[0], p[1]);  
   
   return alabel;  
  }  
 }  
 void GetDistTransformLabels(cv::Mat& dist_trans, cv::Mat& labels, int row_start, int row_end, int col_start, int col_end) {  
   
  assert(dist_trans.type() == CV_32FC1);  
  assert(labels.type() == CV_32SC2);  
   
  labels.setTo(-1); //float* src_data_row;  
  for( int y = row_start; y < row_end; y++ ) {  
   //src_data_row = dist_trans.ptr<float>(y);  
   for( int x = col_start; x < col_end; x++ ) {  
   
    cv::Vec2i& alabel = labels.at<cv::Vec2i>(y,x);  
    if(alabel[0] == -1 ) {  
     alabel = GetDistTransformLabel(dist_trans, labels, x, y);  
    }  
   
   }  
  }  
 }  
 int main( int argc, char** argv )  
 {  
  cv::Mat depth_map(VIDEO_FRAME_HEIGHT, VIDEO_FRAME_WIDTH, CV_8UC1, 1);  
  cv::Mat dist_trans(VIDEO_FRAME_HEIGHT, VIDEO_FRAME_WIDTH, CV_32FC1);  
  cv::Mat labels(VIDEO_FRAME_HEIGHT, VIDEO_FRAME_WIDTH, CV_32SC2);  
   
  cv::circle(depth_map, cv::Point2i(320, 240), 40, cvScalar(255,255,255), 10);  
  cv::MatExpr mask_fg = depth_map > 1;  
  cv::MatExpr mask_bg = depth_map == 1;  
  depth_map.setTo(0, mask_fg);  
  depth_map.setTo(255, mask_bg);  
   
  cv::distanceTransform(depth_map, dist_trans, CV_DIST_L2, CV_DIST_MASK_PRECISE);  
  GetDistTransformLabels(dist_trans, labels, 0, dist_trans.rows, 0, dist_trans.cols);  
  VerifyDistTransformLabels(depth_map, labels, 0, labels.rows, 0, labels.cols);  
   
  double min_value, max_value;  
  cv::minMaxLoc(dist_trans, &min_value, &max_value);  
  dist_trans *=(1/max_value);  
  std::cout<<"\nmin_value: "<<min_value<<"\tmax_value: "<<max_value;  
   
  std::cout<<"\n";  
  //cv::imshow("Dist transform for", depth_map);  
  cv::imshow("Distance Transformation", dist_trans);  
  cv::waitKey(40000);  
   
  return 0;  
 }  

Tuesday 3 April 2012

Computer Vision and Machine Learning Libraries

Some useful computer vision and machine learning libraries are listed here- https://sites.google.com/site/rudrapoudel/links

Eclipse tips for CDT

It is strange that new versions of eclipse are changing some important desirable behaviours and no doubt most of us spending more time to fix one after another. So following are few tips.
  1. Indexing is not working or GC overhead limit exceeded: change memory size in eclipse.ini as following or even more if needed -Xms512m, -Xmx1024m and .XXMaxPermSize 256m
  2. Content assist or ctrl+space is not working: Go to: Window->Preferences->C/C++->Editor->Content Assist-> Advanced and check "Parsing-based Proposals"
And don't forget to rebuild the index after above changes.