title: Color detection on Vuforia frames with OpenCV for Android
body: <p>I need to do color detection(ball tracking) for Augmented Reality. I want to use Qualcomms Vuforia SDK for AR and OpenCV for image processing. I found a color detection algorithm that works on desktop(OpenCV, C++) and tried to apply this to FrameMarkers(a Vuforia sample code) but no success yet.</p>
  
  <p>I got a frame from Vuforia(I can only get RGB565 or GRAYSCALE frames.) and convert to OpenCV Mat object and apply same steps with desktop solution. But I got an error on HSV conversion side. Below is the code.</p>
  
  <pre><code>//HSV range for orange objects
  const int H_MIN = 7;
  const int S_MIN = 186;
  const int V_MIN = 60;
  
  const int H_MAX = 256;
  const int S_MAX = 256;
  const int V_MAX = 157;
  
  const bool shouldUseMorphologicalOperators = true;
  
  const int FRAME_WIDTH = 240;
  const int FRAME_HEIGHT = 320;
  
  const int MAX_NUM_OBJECTS = 50;
  const int MIN_OBJECT_AREA = 20 * 20;
  const int MAX_OBJECT_AREA = 320 * 240 / 1.5;
  
  
  ObjectTracker::ObjectTracker()
  {
      x=y=0;
  }
  
  ObjectTracker::~ObjectTracker()
  {
  
  }
  
  void ObjectTracker::track(QCAR::Frame frame)
  {
      int nImages = frame.getNumImages();
      for(int i = 0; i &lt; nImages; i++)
      {
          const QCAR::Image *image = frame.getImage(i);
          if(image-&gt;getFormat() == QCAR::RGB565)
          {
              Mat RGB565 = Mat(image-&gt;getHeight(),image-&gt;getWidth(),CV_8UC2,(unsigned char *)image-&gt;getPixels());
  
              Mat HSV;
                      //I got error an error here
              cvtColor(RGB565,HSV,CV_RGB2HSV);
  
  
              Mat thresholdedImage;
              inRange(HSV,Scalar(H_MIN,S_MIN,V_MIN),Scalar(H_MAX,S_MAX,V_MAX),thresholdedImage);
  
              if(shouldUseMorphologicalOperators)
                  applyMorphologicalOperator(thresholdedImage);
  
              trackFilteredObject(x,y,thresholdedImage,RGB565);
  
              //waitKey(30);
          }
      }
  
  }
  
  void ObjectTracker::applyMorphologicalOperator(Mat &amp;thresholdedImage)
  {
      //create structuring element that will be used to "dilate" and "erode" image
      //the element chosen here is 3px by 3px rectangle
  
      Mat erodeElement = getStructuringElement(MORPH_RECT,Size(3,3));
      //dilate with larger element so make sure object is nicely visible
      Mat dilateElement = getStructuringElement(MORPH_RECT,Size(8,8));
  
      erode(thresholdedImage,thresholdedImage,erodeElement);
      erode(thresholdedImage,thresholdedImage,erodeElement);
  
      dilate(thresholdedImage,thresholdedImage,dilateElement);
      dilate(thresholdedImage,thresholdedImage,dilateElement);
  }
  
  void ObjectTracker::trackFilteredObject(int &amp;x,int &amp;y,Mat &amp;thresholdedImage,Mat &amp;cameraFeed)
  {
      Mat temp;
      thresholdedImage.copyTo(temp);
      //Two vectors needed for output of findContours
      vector&lt; vector&lt;Point&gt; &gt; contours;
      vector&lt;Vec4i&gt; hierarcy;
      //find contours of filtered image using openCV findContours function
      findContours(temp,contours,hierarcy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE);
      //use moments method to find out filtered object
      double refArea = 0;
      bool objectFound = false;
      if(hierarcy.size() &gt; 0)
      {
          int nObjects = hierarcy.size();
          //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
          if(nObjects &lt; MAX_NUM_OBJECTS )
          {
              for(int index = 0; index &gt;= 0; index = hierarcy[index][0])
              {
                  Moments moment = moments((cv::Mat)contours[index]);
                  double area = moment.m00;
  
                  //if the area is less than 20 px by 20 px then it is probably just noise
                  //if the area is the same as the 3/2 of the image size, probably just a bad filter
                  //we only want the object with the largest area so we safe a reference area each
                  //iteration and compare it to the area in the next iteration.
                  if(area &gt; MIN_OBJECT_AREA &amp;&amp; area &lt; MAX_OBJECT_AREA &amp;&amp; area &gt; refArea)
                  {
                      x = moment.m10/area;
                      y = moment.m01/area;
                      objectFound = true;
                      refArea = area;
                  }
                  else
                      objectFound = false;
              }
  
              //let user know you found an object
              if(objectFound ==true)
              {
                  LOG("Object found");
                  highlightObject(x,y,cameraFeed);
              }
          }
          else
          {
              LOG("Too much noise");
          }
      }
      else
          LOG("Object not found");
  }
  
  void ObjectTracker::highlightObject(int x,int y,Mat &amp;frame)
  {
  }
  </code></pre>
  
  <p>How to do proper conversion from RGB565 to HSV color space?</p>