title: Isolating and tracking multiple objects in real time using OpenCV?
body: <p>I'm currently making a program to track 4 paddles, with 3 different colors. I'm having trouble understanding how best to proceed, with the knowledge I have now, and how to reduce the computational costs of running the project. There are code examples of the steps listed at the end of this post.</p>
  
  <p>The program contains a class file called Controllers, that has simple get and set functions for things such as X and Y position, and which HSV values are used for thresholding.</p>
  
  <p>The program in its unoptimized state now does the following:</p>
  
  <ol>
  <li>Reads image from webcam</li>
  <li>Converts image to HSV colorspace</li>
  <li>Uses the inRange function of OpenCV, together with some previously defined max/min values for HSV, to threshold the HSV image 3 times, one for each colored paddle. This saves to seperate Mat arrays.</li>
  <li><strong>(This step is problematic for me)</strong> - Performs erosion and dilation of EACH of the three thresholded images.</li>
  <li>Passes the image into a function, that uses Moments to create a vector of point describing the contours, and then uses moments to calculate the X and Y location, which is saved as an object and pushed back into a vector of these paddle objects.</li>
  </ol>
  
  <p>Everything technically works at this point, but the resources required to perform the morphological operations three times each loop through the while loop that reads images from the webcam is slowing the program immensely.(<em>Applying 2 iterations of erosion, and 3 of dilation on 3 640*480 images at an acceptable frame rate.</em>)</p>
  
  <p><strong>Threshold Images for different paddles</strong></p>
  
  <pre><code>inRange(HSV, playerOne.getHSVmin(), playerOne.getHSVmax(), threshold1);
  inRange(HSV, playerTwo.getHSVmin(), playerTwo.getHSVmax(), threshold2);
  inRange(HSV, powerController.getHSVmin(), powerController.getHSVmax(), threshold3);
  </code></pre>
  
  <p><strong>Perform morphological operations</strong></p>
  
  <pre><code>morphOps(threshold1);
  
  void morphOps(Mat &amp;thresh)
  {
      //Create a structuring element to be used for morph operations.
      Mat structuringElement = getStructuringElement(MORPH_RECT, Size(3,3));
      Mat dilateElement = getStructuringElement(MORPH_RECT, Size(6, 6));
      //Perform the morphological operations, using two/three iterations because the noise is horrible.
      erode(thresh, thresh, structuringElement, Point(-1, -1), 3);
      dilate(thresh, thresh, dilateElement, Point(-1, -1), 2);
  }
  </code></pre>
  
  <p><strong>Track the image</strong></p>
  
  <pre><code>trackFilteredObject(playerOne, threshold1, cameraFeed);
  trackFilteredObject(playerTwo, threshold2, cameraFeed);
  trackFilteredObject(powerController, threshold3, cameraFeed);
  
  void trackFilteredObject(Controllers theControllers, Mat threshold, Mat HSV, Mat &amp;cameraFeed)
  {
      vector &lt;Controllers&gt; players;
  
      Mat temp;
      threshold.copyTo(temp);
      //these vectors are needed to save the output of findCountours
      vector&lt; vector&lt;Point&gt; &gt; contours;
      vector&lt;Vec4i&gt; hierarchy;
      //Find the contours of the image
      findContours(temp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
      //Moments are used to find the filtered objects.
      double refArea = 0;
      bool objectFound = false;
      if (hierarchy.size() &gt; 0)
      {
          int numObjects = hierarchy.size();
          //If there are more objects than the maximum number of objects we want to track, the filter may be noisy.
          if (numObjects &lt; MAX_NUM_OBJECTS)
          {
              for (int i = 0; i &gt;= 0; i = hierarchy[i][0])
              {
                  Moments moment = moments((Mat)contours[i]);
                  double area = moment.m00;
                  //If the area is less than min area, then it is probably noise
                  if (area &gt; MIN_AREA)
                  {
                      Controllers player;
  
                      player.setXPos(moment.m10 / area);
                      player.setYPos(moment.m01 / area);
                      player.setType(theControllers.getType());
                      player.setColor(theControllers.getColor());
  
                      players.push_back(player);
  
                      objectFound = true;
                  }
                  else objectFound = false;
              }
  
              //Draw the object location on screen if an object is found
              if (objectFound)
              {
                  drawObject(players, cameraFeed);
              }
          }
      }
  }
  </code></pre>
  
  <p>The idea is that I want to be able to isolate each object, and use the X and Y positions as points of a triangle, and use the information to calculate angle and power of an arrow shot. So I want to know if there is a better way to isolate the colored paddles and remove the noise, that doesn't require me to perform these morphological operations for each color.</p>