Friday, February 1, 2013

How to add Slider or Trackbar to a cvWindow

0 comments
    You might have seen my previous post regarding the HSV values extraction. That code used Sliders to vary the value of the parameter passed to the thresholding algorithm. In this post, we are going to learn ahow to add a Slider or Trackbar to a cvWindow.

the function below will create and add a trackbar to the window "Output"
  cvCreateTrackbar("LowHue", "Output", &lowHue, max, onLowHue);

you see here five arguments to the function.

"LowHue" - it is a string, used as caption on the cvWindow above the Trackbar. something like a name for the trackbar.



"Output" - name of the window, which must be created using cvNamedWindow("Output", CV_WINDOW_NORMAL ) before attaching a trackbar to it.
 cvNamedWindow("Output",CV_WINDOW_NORMAL)

&lowHue - it is a variable, corresponding to the slider position.
 int lowHue = 10;

max - maximum value for the slider. the value corresponding to slider postion when it is at the rightmost end.
 int max = 255;

onLowHue - it is a function pointer, which will be called when, there is a change in slider position due to user interaction.

void onLowHue (int value )

     lowHue = value;
 }

voila!!!
Read more ►

HSV trainer

1 comments
    This code snippet extracts the lower and higher bound HSV values for the object of interest.

Code Listing

#include<stdio.h>
#include<cv.h>
#include<highgui.h>

int max = 255;

int lowHue = 10 ;
int lowSat = 0 ;
int lowVal = 0 ;

int highHue = 100 ;
int highSat = 255 ;
int highVal = 255 ;

void onLowHue ( int value ) { lowHue = value ; }
void onLowSat ( int value ) { lowSat = value ; }
void onLowVal ( int value ) { lowVal = value ; }

void onHighHue ( int value ) { highHue = value ; }
void onHighSat ( int value ) {  highSat = value ; }
void onHighVal ( int value ) { highVal = value ; }

IplImage* hsv_from_rgb(IplImage* _src);
IplImage* hsv_threshold ( IplImage* _hsv_src,
     CvScalar _min,
     CvScalar _max );

void cvCreateShowWindow(char* name, IplImage *src)
{
 cvNamedWindow(name,CV_WINDOW_NORMAL);
 cvShowImage(name, src);
 
}

IplImage* resize_640x480(IplImage* _src)
{
    IplImage* res = cvCreateImage( cvSize(640,480) ,
                                   _src->depth, 
                                   _src->nChannels
                                  );   
    cvResize ( _src, res, CV_INTER_LINEAR );
 return res;
}

int main ( int  argc, char* argv[] )
{
 if ( argc < 2 ) {
     printf ("Error: no input image found\n" ) ;
     exit (1) ;
   }
 cvStartWindowThread();

   IplImage* src = cvLoadImage(argv[1], CV_LOAD_IMAGE_UNCHANGED);
   cvCreateShowWindow("src", src);
   cvWaitKey(0);
   IplImage* cir = cvCloneImage (src) ;
   //IplImage* _src = cvCreateImage ( cvGetSize(src), IPL_DEPTH_8U, 1 ) ;
   //cvCvtColor (src, _src, CV_BGR2GRAY) ;
   IplImage* _src = resize_640x480 (src);
   //cvSmooth ( _src, _src, CV_GAUSSIAN, 15, 0, 0, 0);

   cvCreateShowWindow(" input", _src);

  cvCreateShowWindow("Output",_src  );

  cvCreateTrackbar("LowHue", "Output", &lowHue, max, onLowHue);
  cvCreateTrackbar("HighHue", "Output", &highHue, max, onHighHue);

  cvCreateTrackbar("LowSat", "Output", &lowSat, max, onLowSat);
  cvCreateTrackbar("HighSat", "Output", &highSat, max, onHighSat);

  cvCreateTrackbar("LowVal", "Output", &lowVal, max, onLowVal);
  cvCreateTrackbar("HighVal", "Output", &highVal, max, onHighVal);

  CvMemStorage* storage = cvCreateMemStorage(0);
  IplImage* hsved = hsv_from_rgb ( _src );
  IplImage* res ;
 while ( 1 )
 {
   res = hsv_threshold( hsved, 
                        cvScalar( lowHue, lowSat, lowVal, 0),
                        cvScalar( highHue, highSat, highVal, 255) );
   cvWaitKey(30);
   cvShowImage("Output", res );
 
 } // End of while loop
  
  cvCreateShowWindow("res", res);
  cvWaitKey(0);
  cvDestroyWindow("res");
  cvDestroyAllWindows();
}  

IplImage* hsv_from_rgb(IplImage* _src)
{
  IplImage* img = cvCloneImage ( _src ) ;
  cvCvtColor ( _src, img, CV_BGR2HSV );
  return img;
}

IplImage* hsv_threshold ( IplImage* _hsv_src,
     CvScalar _min,
     CvScalar _max )
{
    IplImage* thresholded = cvCreateImage(cvGetSize( _hsv_src ), 8, 1 );
    cvInRangeS( _hsv_src, _min, _max, thresholded );  
    return thresholded;  
}



    Run the program with any input image. Adjust the slider so that the object of interest is show white. Note the values. Thats it. You are done.
 
Read more ►

Second Review - Report

0 comments
   Well, the second review went very well.We have showed the program that tracks the ball. Before the review, we tested the code with the images of same ball at different environments. WHITE is a major villain in HSV space. So we tried with different colored environments. Actually only three backgrounds. The Hue values almost remained the same. So it was easy to extract the position of the ball.

   We used this snippet, for extracting the HSV values for training(what we call it) the code for object detection. Just before the review started, we shot another video of the ball in the lab itself and trained the code to suit the environment. We just finished extracting concurrent values for HSV params, the reviewers entered the lab.

   Suriyadeepan first presented the control of bot using Android through Blue-tooth(BtBee) module. Then the object tracking code is demostrated. Thats it. Thank you for reading this boring story.


Second Review report can be downloaded here
Read more ►

Thursday, January 31, 2013

Second Review

0 comments
Tomorrow comes the second review. Prepared report and planned to show,
  • Controlling of locomotion of the bot through Android.
  • Tracking the ball, in video input.
Ooh. I didn't tell you anything about the bot, right? wait-up until the review is over. I'll reveal the story.

Time to bed.
Read more ►

Tuesday, January 29, 2013

Vision Implementation Part-I

1 comments
This is first post in this series. Vision Implementation.

   Our image processing approach uses simple filters, morphological operation and few transforms for object detection from  OpenCV library. OpenCV comes with very high level object detection and segmentation algorithms. But there is a reason why we use simple operations.


    i. For using high level features extractors and classifiers, the object must have considerable amount of texture. i.e corners, edges, gradients etc. in our case the ball does not have much texture on it.
   ii. To use classifiers, the code must be trained before used to detect objects, which is a time consuming, and tedious process.
  iii. third and important reason is, "isn't it enough to use simple transforms instead of complex algorithms, if the former one does the intended job"

To code then:
  Here is the snapshot of Work in Progress(WIP) working code. We will go block by block.

#include<stdio.h>
#include<cv.h>
#include<highgui.h>

void cvCreateShowWindow ( char* _name, IplImage *_src ) ;
IplImage* hsv_from_rgb  ( IplImage* _src )    ;
IplImage* hsv_threshold ( IplImage* _hsv_src,
        CvScalar _min,
        CvScalar _max )    ;
IplImage* hough_circles ( IplImage* _src )    ;
IplImage* find_contours ( IplImage* _src )    ;


int main(int argc, char* argv[])
{
  if ( argc < 2 ) {
    printf ("Error: no input image found\n" ) ;
    exit (1) ;
  }

  char* image = malloc ( sizeof ( argv[1][0] ) 
       * strlen ( argv[1] ) + 1) ;
  strcpy ( image, argv[1] ) ;
  cvStartWindowThread();

  IplImage* tmp = cvLoadImage ( image, CV_LOAD_IMAGE_UNCHANGED ) ;
  cvCreateShowWindow("tmp", tmp);

 /* defines the stages of processing pipeline...*/
 #define CV_ATHENA_HSV_CONVERSION     1
 #define CV_ATHENA_HSV_THRESHOLD      1
 /* #define CV_ATHENA_ADAPTIVE_THRESHOLD    1 */
 #define CV_ATHENA_SMOOTH_BEFORE_MORPH  1
 #define CV_ATHENA_MORPH       1
 #define CV_ATHENA_SMOOTH_BEFORE_THRESHOLD 1
 #define CV_ATHENA_THRESHOLD     1
 #define CV_ATHENA_SMOOTH_BEFORE_CANNY     1
 #define CV_ATHENA_CANNY       1
 #define CV_ATHENA_HOUGH_CIRCLES     1
 /* #define CV_ATHENA_CONTOURS             1 */

#ifdef CV_ATHENA_HSV_CONVERSION
  IplImage* hsv_src = tmp;
  IplImage* hsved = hsv_from_rgb(hsv_src);
  cvCreateShowWindow("hsved", hsved);
  cvSaveImage("hsved.jpg",hsved,0);
#endif /* CV_ATHENA_HSV_CONVERSION */


#ifdef CV_ATHENA_HSV_THRESHOLD
  IplImage* thresh_src = hsved ;
  IplImage* thresholded = hsv_threshold ( thresh_src, 
            cvScalar(36, 0, 0,0),
            cvScalar(50, 255, 255,255)
          );
  cvCreateShowWindow("thresholded", thresholded);
  cvSaveImage("thresh.jpg",thresholded,0);
#endif /* CV_ATHENA_HSV_THRESHOLD*/


#ifdef CV_ATHENA_ADAPTIVE_THRESH
  IplImage* adaptive_src = thresholded ;
  IplImage* adaptive_thresh = cvCloneImage(adaptive_src) ;
  cvAdaptiveThreshold ( adaptive_src, adaptive_thresh, 255,
         CV_ADAPTIVE_THRESH_GAUSSIAN_C,
      CV_THRESH_BINARY, 35, 25
       );
  cvCreateShowWindow("adaptive_thresh", adaptive_thresh);
  cvSaveImage("adaptive_thresh.jpg",adaptive_thresh,0); 
#endif /* CV_ATHENA_ADAPTIVE_THRESH*/

#ifdef CV_ATHENA_SMOOTH_BEFORE_MORPH  
  IplImage* smooth_src_morph = thresholded;
  IplImage* smoothed_morph = cvCloneImage (smooth_src_morph);
  cvSmooth ( smooth_src_morph, smoothed_morph, CV_GAUSSIAN,
       21, 21, 0, 0
      ); 
  cvCreateShowWindow("smoothed_morph", smoothed_morph);
  cvSaveImage("smoothed_morph.jpg",smoothed_morph,0);
#endif /* CV_ATHENA_SMOOTH_1*/

#ifdef CV_ATHENA_MORPH  
  IplImage* morph_src = smoothed_morph;
  IplImage* morphed = cvCloneImage(morph_src);
  IplImage* morph_tmp = cvCloneImage(morph_src);
  int mask_strength = 14 ;
  cvMorphologyEx ( morph_src,morphed,morph_tmp,
       NULL,CV_MOP_OPEN,mask_strength
                );
  /* cvMorphologyEx ( morphed, morphed, morph_tmp,
       NULL,CV_MOP_CLOSE,2
      ); */
  cvCreateShowWindow("morphed", morphed);
  cvSaveImage("morphed.jpg",morphed,0);
#endif /* CV_ATHENA_MORPH*/


#ifdef CV_ATHENA_SMOOTH_BEFORE_THRESHOLD
  IplImage* smooth_src_thresh = morphed;
  IplImage* smoothed_thresh = cvCloneImage (smooth_src_thresh);
  cvSmooth ( smooth_src_thresh, smoothed_thresh, CV_GAUSSIAN,
    21, 21,0,0
   ); 
  cvCreateShowWindow("smoothed_thresh", smoothed_thresh);
  cvSaveImage("smoothed_thresh.jpg",smoothed_thresh,0);
#endif /* CV_ATHENA_SMOOTH_BEFORE_THRESHOLD*/

#ifdef CV_ATHENA_THRESHOLD
  IplImage* bin_thresh_src = smoothed_thresh ;
  IplImage* bin_threshed = cvCloneImage (bin_thresh_src );
  cvThreshold ( bin_thresh_src, bin_threshed,
    120, 255, CV_THRESH_BINARY
      );
  cvCreateShowWindow("bin_threshed", bin_threshed);
  cvSaveImage("bin_threshed.jpg",bin_threshed,0);
#endif /* CV_ATHENA_THRESHOLD */



#ifdef CV_ATHENA_SMOOTH_BEFORE_CANNY
  IplImage* smooth_src_hough = bin_threshed;
  IplImage* smoothed_hough = cvCloneImage (smooth_src_hough);
  cvSmooth ( smooth_src_hough, smoothed_hough,
    CV_GAUSSIAN, 71, 71, 0, 0
   ); 
  cvCreateShowWindow("smoothed_hough", smoothed_hough);
  cvSaveImage("smoothed_hough.jpg",smoothed_hough,0);
#endif /* CV_ATHENA_SMOOTH_BEFORE_CANNY*/

#ifdef CV_ATHENA_CANNY
  IplImage* canny_src = smoothed_hough ;
  IplImage* canny = cvClone ( canny_src );
  cvCanny(canny_src, canny, 10, 10, 3); 
  cvCreateShowWindow("canny", canny);  
  cvSaveImage("canny.jpg",canny,0);
#endif /* CV_ATHENA_CANNY*/

#ifdef CV_ATHENA_HOUGH_CIRCLES
  IplImage* hough_src = canny ;
  IplImage* cir = hough_circles ( hough_src );
  cvCreateShowWindow("cir", cir);
  cvSaveImage("cir.jpg",cir,0);
#endif /* CV_ATHENA_HOUGH_CIRCLES*/

#ifdef CV_ATHENA_CONTOURS      
  IplImage* contour_src = cir ;
  IplImage* contoured = find_contours ( contour_src );
  cvCreateShowWindow("contoured", contoured);
  cvSaveImage("contoured.jpg",contoured,0);
#endif /* CV_ATHENA_CONTOURS*/      


  cvWaitKey(0);
  cvDestroyWindow("tmp");
  cvDestroyWindow("hsved");

  return 0;

}/* end of main */

void cvCreateShowWindow(char* _name, IplImage *_src)
{
 cvNamedWindow ( _name, CV_WINDOW_NORMAL ) ;
 cvShowImage ( _name, _src ) ;
 
}

IplImage* hsv_from_rgb(IplImage* _src)
{

  IplImage* img = cvCloneImage ( _src ) ;
  cvCvtColor ( _src, img, CV_BGR2HSV );
  return img;

}

IplImage* hsv_threshold ( IplImage* _hsv_src,
        CvScalar _min,
        CvScalar _max )
{
 IplImage* thresholded = cvCreateImage(cvGetSize( _hsv_src ), 8, 1 );
 cvInRangeS( _hsv_src, _min, _max, thresholded );  
  
    return thresholded;  
}

IplImage* hough_circles ( IplImage* _src )
{
   CvMemStorage* storage = cvCreateMemStorage(0);
   /* CvSeq* circles = cvHoughCircles (_src, storage, CV_HOUGH_GRADIENT,
            1, _src->height/6, 100, 50,0,0
           ); */
   CvSeq* circles = cvHoughCircles ( _src, storage, CV_HOUGH_GRADIENT,
          2, 10, 200, 100 , 50, 130
         );
   IplImage* cir = cvClone(_src );
   cvSetZero (cir);
   size_t i;
   for ( i = 0; i < circles->total; i++)  {   

     float* p = (float*)cvGetSeqElem(circles, i); 
     CvPoint center = cvPoint( cvRound(p[0]), cvRound(p[1]) );
     int radius = cvRound(p[2]);
     cvCircle( cir, center, radius+10, CV_RGB(0,0,255), 2, 8, 0 );
     
  }

 return cir;
}   

IplImage* find_contours ( IplImage* _src )
{
 CvMemStorage *mem = cvCreateMemStorage(0);
 CvSeq *contours = 0;
 int n = cvFindContours (_src, mem, &contours, sizeof(CvContour),
       CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE,
       cvPoint(0,0)
       );
 /* int n = cvFindContours ( gray, mem, &contours, sizeof(CvContour),
        CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE,
        cvPoint (0,0)
        ); */
 IplImage* res = cvCloneImage(_src) ;
 cvSetZero(res) ;
 for (; contours != 0; contours = contours->h_next)
 {
     cvDrawContours (res, contours, CV_RGB(255,0,0),
      CV_RGB(0,0,0), -1, CV_FILLED, 8, cvPoint(0,0)
      );
 }
 return res;
}



At present the code uses 9 of 11 stages in the pipeline. they are,

RGB to HSV conversion
    the image is converted from RGB(RED-GREEN-BLUE) into HSV(HUE-SATURATIONN-VALUE) representation. easier to color based separation. The HUE value signifies the color of the objects. VALUE represents the brightness of the pixel. SATURATION represents the intensity.


RGB to HSV
HSV Thresholding
    the images is converted into binary image. The pixels whose HSV values lie between the specified range will appear white and the other pixels will turn black.
 

HSV-Threshold
Smoothing
    Smoothing in most cases, is done to reduce noise.




Smoothing before morphing
Morphing
    The OPEN morphological operation is used to erode the tiny black regions. OPEN is a combination of erode and dilate operations which cleans the image a bit.

Morphological Operation - OPEN


Smoothing



Thresholding
    This stages separates the object of interset after the morphological operation. This is similar to HSV thresholding.





Smoothing



Canny edge detection
    Canny edge detection, determines the boundaries of the object, and help in Circles detection using Hough Transform





Hough Transform for Circles
    find the circles present in the image. and draws them.




Read more ►

Tuesday, January 22, 2013

PCB designs

0 comments
     After the struggling with standard arduino boards and shields, we decided to design our own PCBs for use with the bot, and here are those... the design may be changed in near future based are requirements...







  
Read more ►
 

Copyright © Project Athena Design by O Pregador | Blogger Theme by Blogger Template de luxo | Powered by Blogger