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;
}
}