Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Android Round Object Tracking with OpenCV

Hi all. I have been following a tutorial on tracking circular/elliptical objects with OpenCV 3.1.0 on Android and I need some help with code optimization and improving the recognition accuracy. Currently, the code tries to find all circles in each frame and draw an outline around it. Since I am very new to OpenCV, I was hoping someone could help me with the following issues:

  • When the camera recognizes a circular object and draws an outline, the framerate drops to 1-2fps. Otherwise, the framerate is decent. How can I optimize my code to remedy this?

  • I want to track a very specific object which also happens to be an imperfect circle. By that, I mean there are indents around the circumference of the circle. Also, if possible, I want to be able to track the object from the side (the object is cylindrical), which means smooth transitions between drawing circles (top view) and drawing ellipses/rectangles with rounded corners (angled/side view).

  • I get a lot of false positives as well as recognition of other circular objects. I have considered thresholding the frames based on the specific color of the object I want to track (white), but I am unsure how to implement this. Any tutorials/other resources on doing this would be greatly appreciated!

public class MainActivity extends Activity implements CvCameraViewListener2 { private static final String TAG = "OCVSample::Activity";

private CameraBridgeViewBase mOpenCvCameraView;
private boolean              mIsJavaCamera = true;
private MenuItem             mItemSwitchCamera = null;

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");
                mOpenCvCameraView.enableView();
                mOpenCvCameraView.setMaxFrameSize(640,480);
            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};

public MainActivity() {
    Log.i(TAG, "Instantiated new " + this.getClass());
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    Log.i(TAG, "called onCreate");
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    setContentView(R.layout.activity_main);

    mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.activity_main);

    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);

    mOpenCvCameraView.setCvCameraViewListener(this);
}

@Override
public void onPause()
{
    super.onPause();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

@Override
public void onResume()
{
    super.onResume();
    if (!OpenCVLoader.initDebug()) {
        Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
    } else {
        Log.d(TAG, "OpenCV library found inside package. Using it!");
        mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
    }
}

public void onDestroy() {
    super.onDestroy();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

public void onCameraViewStarted(int width, int height) {
}

public void onCameraViewStopped() {
}

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    Mat rgba = inputFrame.rgba();
    Core.flip(rgba, rgba, 1);
    Mat greyMat = new Mat(); 
    Imgproc.cvtColor(rgba, greyMat,Imgproc.COLOR_RGBA2GRAY , 0);
    Imgproc.GaussianBlur(greyMat, greyMat, new Size(9, 9), 2,2);
    double dp = 1.2d;
    double minDist = 100; 
    int minRadius = 0;
    int maxRadius = 0; 
    double param1 = 70, param2 = 72;
    Mat circles = new Mat();

    Imgproc.HoughCircles(greyMat, circles, Imgproc.HOUGH_GRADIENT, dp, minDist, param1, param2, minRadius, maxRadius);
    int numCircles = (circles.rows()==0) ? 0: circles.cols();
    for (int i = 0; i < numCircles; i++) {
        double[] circleCoordinates = circles.get(0, i);
        int x = (int) circleCoordinates[0], y = (int)circleCoordinates[1];
        Point center = new Point(x,y);
        int radius = (int) circleCoordinates[2];
        Imgproc.circle(rgba, center, radius, new Scalar(0, 255, 0), 4);
    }

    return rgba; 
}

}