title: JavaCV : Tracking objects using the Camshift algorithm
body: <p>I want to track objects using the Camshift algorithm. I tried to correct the bugs that I found in the JavaCV translation of the original OpenCV Camshift file. </p>
  
  <p>Here is my code: </p>
  
  <pre><code>package objectTracking;
  
  import com.googlecode.javacv.CanvasFrame;
  import com.googlecode.javacv.FrameGrabber;
  import com.googlecode.javacv.OpenCVFrameGrabber;
  import static com.googlecode.javacv.cpp.opencv_core.*;
  import com.googlecode.javacv.cpp.opencv_core.CvBox2D;
  import com.googlecode.javacv.cpp.opencv_core.CvPoint;
  import com.googlecode.javacv.cpp.opencv_core.CvRect;
  import com.googlecode.javacv.cpp.opencv_core.CvScalar;
  import com.googlecode.javacv.cpp.opencv_core.IplImage;
  import com.googlecode.javacv.cpp.opencv_core.IplImageArray;
  import static com.googlecode.javacv.cpp.opencv_imgproc.*;
  import com.googlecode.javacv.cpp.opencv_imgproc.CvConnectedComp;
  import com.googlecode.javacv.cpp.opencv_imgproc.CvHistogram;
  import static com.googlecode.javacv.cpp.opencv_video.*;
  import com.sun.jna.ptr.FloatByReference;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseListener;
  
  public class CamShifter implements MouseListener{
  final static int MOUSE_PRESSED = 1;
  final static int MOUSE_RELEASED = 2;
  
      IplImage image, frame, hsv, hue, mask, backproject, histimg;
      IplImageArray hueArray;
      CvHistogram hist;
      CanvasFrame histogram = new CanvasFrame("Histogram"), camshiftDemo = new CanvasFrame("CamshiftDemo");
  
      boolean backproject_mode = false;
      boolean select_object = false;
      int track_object = 0;
      boolean show_hist = true;
  
      boolean paused = false;
  
      CvPoint origin = new CvPoint();
      CvRect selection = new CvRect();
  
      OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
      CvRect track_window = new CvRect();
      CvBox2D track_box = new CvBox2D();
  
      CvConnectedComp track_comp = new CvConnectedComp();
  
      int hsize = 16;
      float hranges[] = {0,180};
      int[] hdims = {hsize};
      float hranges_arr[][] = {hranges};
  
      int vmin = 10, vmax = 256, smin = 30;
  
      public static void main(String args[]) throws  Exception  {
  
          CamShifter csh = new CamShifter();
          csh.work(csh);
          System.out.println("CamShiftDetector trial");
  
  
      }
  
      public CamShifter() throws FrameGrabber.Exception {
  
          grabber.start();
          camshiftDemo.getCanvas().addMouseListener(this);
  
      }
  
  
      public void onMouse(int event, int x, int y) {
          if (select_object) {
              //get selection
              int selX, selY, selW, selH;
              selX = Math.min(x, origin.x());
              selY = Math.min(y, origin.y());
              selW = selX + Math.abs(x - origin.x());
              selH = selY + Math.abs(y - origin.y());
              selection = cvRect(selX, selY, selW, selH);
              System.out.println("Selection : \n("+selX+", "+selY+")\n("+selW+", "+selH+")");
  
              //ensure that selection is enclosed within the image
              selX = Math.max(selection.x(), 0);
              selY = Math.max(selection.y(), 0);
              selW = Math.min(selection.width(), image.width());
              selH = Math.min(selection.height(), image.height());
              selection = cvRect(selX, selY, selW - selX, selH - selY);
              System.out.println("ensure that selection is enclosed within the image");
              System.out.println("Selection : \n("+selX+", "+selY+")\n("+selW+", "+selH+")");
          }
  
          switch (event) {
              case MOUSE_PRESSED: 
                  origin = cvPoint(x, y);
                  selection = cvRect(x, y, 0, 0);
                  select_object = true;
                  break;
              case MOUSE_RELEASED: 
                  select_object = false;
                  if (selection.width() &gt; 0 &amp;&amp; selection.height() &gt; 0) {
                      track_object = -1;
                  }
                  break;
          }
      }
  
  
      CvScalar hsv2rgb(float hue) {
          int[] rgb = new int[3];
          int p, sector;
          int[][] sector_data = {{0, 2, 1}, {1, 2, 0}, {1, 0, 2}, {2, 0, 1}, {2, 1, 0}, {0, 1, 2}};
          hue *= 0.033333333333333333333333333333333f;
          sector = (int) Math.floor(hue);
          p = Math.round(255 * (hue - sector));
          p = p ^ 1;
          int temp = 0;
          if ((sector &amp; 1) == 1) {
              temp = 255;
          } else {
              temp = 0;
          }
          p ^= temp;
  
          rgb[sector_data[sector][0]] = 255;
          rgb[sector_data[sector][1]] = 0;
          rgb[sector_data[sector][2]] = p;
  
          return cvScalar(rgb[2], rgb[1], rgb[0], 0);
      }
  
      String coffee;
      public void work(CamShifter csh) throws Exception {
          IplImage capture = grabber.grab();
  
          System.out.println("paused = "+paused);
          if (capture == null) {
              System.out.println("Could not initialize capturing...\n");
              return;
          }
  
          while (true) {
              int bin_w;
              if (!paused) {
                  frame = grabber.grab();
                  if (frame == null) {
                  return;
                  }
              }
  
              if (image == null) {
                  image = cvCreateImage(frame.cvSize(), 8, 3);
                  hsv = cvCreateImage(frame.cvSize(), 8, 3);
                  hue = cvCreateImage(frame.cvSize(), 8, 1);
                  mask = cvCreateImage(frame.cvSize(), 8, 1);
                  backproject = cvCreateImage(frame.cvSize(), 8, 1);
                  histimg = cvCreateImage(cvSize(320, 200), 8, 3);
                  cvZero(histimg);
                  hist = cvCreateHist( 1, hdims, CV_HIST_ARRAY, hranges_arr, 1 );
  
              }
              cvCopy(frame, image);
              if (!paused)
              {
                  cvCvtColor(image, hsv, CV_BGR2HSV);
  
                  if (track_object != 0) {
  
                      int _vmin = vmin, _vmax = vmax;
  
                      cvInRangeS(hsv, cvScalar(0, smin, Math.min(_vmin, _vmax), 0), cvScalar(180, 256, Math.max(_vmin, _vmax), 0), mask);
                      cvSplit(hsv, hue, null, null, null);
  
                      hueArray = new IplImageArray(hue);
  
                      if (track_object &lt; 0) {
                          float max_val = 0.f;
  
                          cvSetImageROI(hue, selection);
                          cvSetImageROI(mask, selection);
                          cvCalcHist(hueArray, hist, 0, null);
  
  
                          if (max_val != 0) { // TODO: entier non null == true en C, à vérifier
                              max_val = (float) 255. / max_val;
                          } else {
                              max_val = 0;
                          }
  
                          FloatByReference fl_ref = new FloatByReference(max_val);
                          cvConvertScale(hist.bins(), hist.bins(), Float.parseFloat(fl_ref.toString()), 0);
                          cvResetImageROI(hue);
                          cvResetImageROI(mask);
                          track_window = selection;
                          track_object = 1;
  
                          cvZero(histimg);
                          bin_w = histimg.width() / hsize;
                          for (int i = 0; i &lt; hsize; i++) {
                              int val = Math.round((int) (cvGetReal1D(hist.bins(), i) * histimg.height() / 255.));
                              CvScalar color = hsv2rgb(i * 180.f / hsize);
                              cvRectangle(histimg, cvPoint(i * bin_w, histimg.height()), cvPoint((i + 1) * bin_w, histimg.height() - val), color, -1, 8, 0);
                          }
                      }
  
                      cvCalcBackProject(hueArray, backproject, hist);
                      cvAnd(backproject, mask, backproject, null);
  
                      cvCamShift(backproject, track_window, cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1), track_comp, track_box);
                      track_window = track_comp.rect();
  
  //                        if (track_window.width()*track_window.height()&lt;=1)
  //                        {
  //                            int cols = backproject.width(), rows = backproject.height(), r = (Math.min(cols, rows)+5)/6;
  //                            track_window = cvRect(
  //                                    Math.max(track_window.x()-r,0), 
  //                                    Math.max(track_window.y()-r,0), 
  //                                    Math.min(track_window.x()+r,cols), 
  //                                    Math.min(track_window.y()+r,rows));
  //                        }
  
                      if (backproject_mode) {
                          cvCvtColor(backproject, image, CV_GRAY2BGR);
                      }
                      if (image.origin() == 0) {
                          track_box = track_box.angle(-track_box.angle());
                          cvEllipseBox(image, track_box, cvScalar(0, 0, 255, 0), 3, CV_AA, 0);
                      }
                  }
              } else if (track_object &lt; 0) {
                  paused = false;
              }
              if (select_object &amp;&amp; selection.width() &gt; 0 &amp;&amp; selection.height() &gt; 0) {
                  cvSetImageROI(image, selection);
                  cvXorS(image, cvScalarAll(255), image, null);
                  cvResetImageROI(image);
              } 
              camshiftDemo.showImage(image);
              histogram.showImage(histimg);
  
          }
  
      }
  
  @Override
      public void mouseClicked(MouseEvent e) {
  //            System.out.println("Mouse Clicked !");
  
      }
  
  @Override
      public void mousePressed(MouseEvent e) {
          this.onMouse(MOUSE_PRESSED, e.getX(), e.getY());
          System.out.println("Mouse Pressed !");
          System.out.println("\t e.getX(): "+e.getX());
          System.out.println("\t e.getY(): "+e.getY());
      }
  
  @Override
      public void mouseReleased(MouseEvent e) {
          this.onMouse(MOUSE_RELEASED, e.getX(), e.getY());
          System.out.println("Mouse Released !");
          System.out.println("\t e.getX(): "+e.getX());
          System.out.println("\t e.getY(): "+e.getY());
      }
  
  @Override
      public void mouseEntered(MouseEvent e) {
  //            System.out.println("Mouse Entered !");
  
      }
  
  @Override
      public void mouseExited(MouseEvent e) {
  //            System.out.println("Mouse Exited !");
  
      }
  }
  </code></pre>
  
  <p>Everytime I run the application, and after I select my object to track, the JVM crashes when getting to the line containing <code>cvCalcHist</code>.</p>
  
  <p>Can anyone please tell me what's wrong with my code. I've been on it since days and I can't figure out the problem with it :(</p>
  
  <p>Thank you very much.</p>