title: getting image from callback method without blocking in OpenCV
body: <p>I am getting the Mat image that is provided from the OpenCV callback method onCameraFrame(). this I get from CvCameraViewFrame inputFrame that is passed in the parameters.   This callback method required a Mat image to be returned back.</p>
  
  <p>the purpose is to get give this Mat image to thhe HoughCircles() method to detect circle shaped objects in the camera viewfinder frame image.</p>
  
  <p>This use of OpenCV in this example is the Java API version to be used in Android</p>
  
  <p>The problem is that two methods I am using inside of the onCameraFrame() callback method take time to process and slow down the camera fiewfinder video frame rate.</p>
  
  <pre><code> Imgproc.GaussianBlur(mGray, mGray, new Size(5, 5), 2, 2);                             
   Imgproc.HoughCircles(mGray, circles, Imgproc.CV_HOUGH_GRADIENT,
   1, mGray.rows()/8, 150, 60, 30, 0);
  </code></pre>
  
  <p>the frame rate becomes vary slow especially if objects are detected in the frame.  The only way I found to improve this frame rate is to reduce the frame size. This results in a low quality image, and even this change the frame rate is still too slow.</p>
  
  <p>How can I avoid this problem?   I tried to pass the Mat mGray and mRGB objects into a separate thread and start it from inside the onCameraFrame() callback method.  Using a background thread is not working. Tried both Java thread and AsyncTask.</p>
  
  <p>two types of solutions were tried,</p>
  
  <p>type one possible solution</p>
  
  <p>Tried using a counter with a integer variable that in incremented each time the onCameraFrame() method is called, so that only one out of ten, or one out of 20 method calls will start a new thread for processing the image HoughCircles.  This did not work.</p>
  
  <p>type two possible solution</p>
  
  <p>The other thing I tried is to use either a AtomicBoolean or Boolean to block the starting of a new thread until the last thread has completed execution,  This will make sure that only one background thread will be launched at a time, and only one Mat image is processed by the HoughCircles Method at a time.   This also is not working for some reason. it is shown in the example code below.</p>
  
  <p>the only way I was able to get this circle detection code working is to not to use any background thread at all. just putting HoughCircles() method and all the rest of the code for examining frames in the onCameraFrame() callback method in the same thread.  As mentioned earlier this does slow down the frame rate, but the HoughCircles() method is getting called and I actually get Log messages to show in logcat showing either circle detected or not detected.</p>
  
  <p>How can I get this to work on a background thread without slowing down the frame rate of the camera viewfinder?</p>
  
  <pre><code>public void onCameraViewStarted(int width, int height) {
  
              mGray = new Mat();
              mRgba = new Mat();
  
              camera = mOpenCvCameraView.getCamera();
              Camera.Parameters params = camera.getParameters();
              camera.setParameters(params);
  
              previewStatus = true;
  
      } // onCameraViewStarted
  
  
  
      public void onCameraViewStopped() {
  
              previewStatus = false;
              mGray.release();
              mRgba.release();
  
      } // onCameraviewStopped
  </code></pre>
  
  <h1>1 - SYNCHRONOUS version of Circle detection, works but slows down frame rate</h1>
  
  <pre><code>      public Mat onCameraFrame(final CvCameraViewFrame inputFrame) {
  
              mRgba = inputFrame.rgba();
              mGray = inputFrame.gray();
  
              MatOfRect circles = new MatOfRect();
  
              // doing a gaussian blur prevents getting a lot of false hits  
              Imgproc.GaussianBlur(mGray, mGray, new Size(5, 5), 2, 2);
  
              // for detection of circles  
              Imgproc.HoughCircles(mGray, circles, Imgproc.CV_HOUGH_GRADIENT,
                                    1, mGray.rows()/8, 150, 60, 30, 0);
  
              // returns int as number of circles detected                      
              int detected = circles.cols();
  
              // if detected circles is more than zero
              // or Animation settings page fragment is not visible on screen
              if((detected &gt; 0) {            
  
                   Log.i("CIRCLE DETECTION", "number circles detected" + circles);
  
                   // add action method to be called here on circle detection
  
              } else {
  
                    Log.i("CIRCLE DETECTION", "no circles detected");
  
              }
  
              circles.release();
  
              return mRgba;
  
        } // onCameraFrame
  </code></pre>
  
  <h1>2 - ASYNCHRONOUS version of Circle Detection, does not work</h1>
  
  <pre><code>   public Mat onCameraFrame(final CvCameraViewFrame inputFrame) {
  
              mRgba = inputFrame.rgba(); // colo
              mGray = inputFrame.gray(); // grayscale required for detection
  
              // if detected circles is more than zero
              // or Animation settings page fragment is not visible on screen
              if((detected &gt; 0)&amp;&amp;(!detectionRunning)) {  
  
              // prevent any more Asynchronous task threads from being launched
              // until this one is finished running
              detectionRunnning = false;
  
              // launnch new Asynchronous task that takes mGray Mat image
              // and checks to see of any circles exist by using
              // the OpenCV Imgproc.HoughCircles() method, passing
              // in the mGray as parameter to the doInBackground() method
              // of this class
              new CircleTask().execute(mGray);
  
              }
  
              // mRgba must be returned with this callback method to show
              // up on screen of viewfinder
              return mRgba;
  
      } // onCameraFrame
  
     // background thread task takes Mat image from onCameraFrame and
     // runs the HoughCircles method on a background thread so UI thread is not blocked
  
     public class CircleTask extends AsyncTask&lt;Mat, Void, Integer&gt; {
  
     // run detection method in background thread
     // takes in parameter in the .execute(Mat mGray) call on the class that is created
     @Override
     protected Integer doInBackground(Mat... params) {
  
         grayMatImage = params[0];
  
         MatOfRect circles = new MatOfRect();
  
         // doing a gaussian blur prevents getting a lot of false positives  
         Imgproc.GaussianBlur(grayMatImage, grayMatImage, new Size(5, 5), 2, 2);
  
        // for detection of circles  
        Imgproc.HoughCircles(grayMatImage, circles, Imgproc.CV_HOUGH_GRADIENT,
                              1, grayMatImage.rows()/8, 150, 60, 30, 0);
  
        // int detected is the number of circles detected                   
        int detected = circles.cols(); 
  
        circles.release();
        grayMatImage.release();
  
        // this integer is passes to the onPostExecute method below
        return detected;
    }
  
     // result Integer is passed here after
     // this method is run on main UI thread
     @Override
     protected void onPostExecute(Integer result) {
  
         Log.i("RESULT OF DETECTION", "number of circles detected " + result);
  
         // add methods here to be executed after circle is detected
  
         // stop blocking and allow the next frame to be an
         detectionRunning = false;
  
     }
  
     }
  </code></pre>