Q:

Detect Circle in image using OpenCV in Android

I'm developing an android app in which I have to detect circle on existing image browse from gallery or capture from the camera. The browsed / captured image will be shown onto the ImageView. By the way, I'm using OpenCVAndroid Library and I compiled it properly.
Any help for my android app, I had read C, C++, or etc in detecting circles but I can't understand it 'coz its different languages for android.
Thanks.
Update
Okay ... This is how I used. 
            if (requestCode == 1) { //Take Photo from Android Camera..

            File f = new File(Environment.getExternalStorageDirectory().toString());
            for (File temp : f.listFiles()) {
                if (temp.getName().equals("temp.jpg")) {
                    f = temp;
                    break;
                }
            }
            try {
                Bitmap bitmap;
                BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();

                bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(),
                        bitmapOptions);

                // bitmap = Bitmap.createScaledBitmap(bitmap, 70, 70, true);

                String path = android.os.Environment
                        .getExternalStorageDirectory()
                        + File.separator
                        + "Phoenix" + File.separator + "default";
                f.delete();
                OutputStream outFile = null;
                File file = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg");
                try {
                    outFile = new FileOutputStream(file);
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 85, outFile);
                    outFile.flush();
                    outFile.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                                    /* convert bitmap to mat */
                Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(),
                        CvType.CV_8UC1);
                Mat grayMat = new Mat(bitmap.getWidth(), bitmap.getHeight(),
                        CvType.CV_8UC1);

                Utils.bitmapToMat(bitmap, mat);

                  /* convert to grayscale */
                int colorChannels = (mat.channels() == 3) ? Imgproc.COLOR_BGR2GRAY
                        : ((mat.channels() == 4) ? Imgproc.COLOR_BGRA2GRAY : 1);

                Imgproc.cvtColor(mat, grayMat, colorChannels);

                /* reduce the noise so we avoid false circle detection */
                Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2);

                // accumulator value
                double dp = 1.2d;
                // minimum distance between the center coordinates of detected circles in pixels
                double minDist = 20;

               // min and max radii (set these values as you desire)
                int minRadius = 0, maxRadius = 0;

               // param1 = gradient value used to handle edge detection
              // param2 = Accumulator threshold value for the
              // cv2.CV_HOUGH_GRADIENT method.
              // The smaller the threshold is, the more circles will be
              // detected (including false circles).
              // The larger the threshold is, the more circles will
              // potentially be returned.
                double param1 = 70, param2 = 72;

              /* create a Mat object to store the circles detected */
                Mat circles = new Mat(bitmap.getWidth(),
                        bitmap.getHeight(), CvType.CV_8UC1);

              /* find the circle in the image */
                Imgproc.HoughCircles(grayMat, circles,
                        Imgproc.CV_HOUGH_GRADIENT, dp, minDist, param1,
                        param2, minRadius, maxRadius);

              /* get the number of circles detected */
                int numberOfCircles = (circles.rows() == 0) ? 0 : circles.cols();

              /* draw the circles found on the image */
                for (int i=0; i<numberOfCircles; i++) {

              /* get the circle details, circleCoordinates[0, 1, 2] = (x,y,r)
               * (x,y) are the coordinates of the circle's center*/
                                      double[] circleCoordinates = circles.get(0, 0);

                    int x = (int) circleCoordinates[0], y = (int) circleCoordinates[1];

                    Point center = new Point(x, y);

                    int radius = (int) circleCoordinates[2];

/* circle's outline */
                    Core.circle(mat, center, radius, new Scalar(0,
                            255, 0), 4);

/* circle's center outline */
                    Core.rectangle(mat, new Point(x - 5, y - 5),
                            new Point(x + 5, y + 5),
                            new Scalar(0, 128, 255), -1);
                }

              /* convert back to bitmap */
                Utils.matToBitmap(mat, bitmap);
                viewImage.setImageBitmap(bitmap);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

I run my app with the code above,My Android phone is crashing after I take photo from camera and  I have this errors in logcat:
          02-10 06:54:15.773    8914-8914/com.example.cloud.circle E/AndroidRuntime﹕ FATAL EXCEPTION: main

java.lang.UnsatisfiedLinkError: n_Mat
        at org.opencv.core.Mat.n_Mat(Native Method)
        at org.opencv.core.Mat.<init>(Mat.java:477)
        at com.example.cloud.circle.Image.onActivityResult(Image.java:152)
        at android.app.Activity.dispatchActivityResult(Activity.java:3908)
        at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
        at android.app.ActivityThread.handleSendResult(ActivityThread.java:2578)
        at android.app.ActivityThread.access$2000(ActivityThread.java:117)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:965)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:130)
        at android.app.ActivityThread.main(ActivityThread.java:3687)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:507)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
        at dalvik.system.NativeStart.main(Native Method)

Please help me. Thanks.

A:

A detailed explanation for circle detection can be found here and here (though not in Java).
I have included a sample code snippet for circle detection below garnered from the 2 links I provided above. The code is commented, so it can be easily understood. I assume that the image bitmap bitmap already has the image you want to analyze.
/* convert bitmap to mat */
Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(),
        CvType.CV_8UC1);
Mat grayMat = new Mat(bitmap.getWidth(), bitmap.getHeight(),
        CvType.CV_8UC1);

Utils.bitmapToMat(bitmap, mat);

/* convert to grayscale */
int colorChannels = (mat.channels() == 3) ? Imgproc.COLOR_BGR2GRAY
        : ((mat.channels() == 4) ? Imgproc.COLOR_BGRA2GRAY : 1);

Imgproc.cvtColor(mat, grayMat, colorChannels);

/* reduce the noise so we avoid false circle detection */
Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2);

// accumulator value
double dp = 1.2d;
// minimum distance between the center coordinates of detected circles in pixels
double minDist = 100;

// min and max radii (set these values as you desire)
int minRadius = 0, maxRadius = 0;

// param1 = gradient value used to handle edge detection
// param2 = Accumulator threshold value for the
// cv2.CV_HOUGH_GRADIENT method.
// The smaller the threshold is, the more circles will be
// detected (including false circles).
// The larger the threshold is, the more circles will
// potentially be returned.
double param1 = 70, param2 = 72;

/* create a Mat object to store the circles detected */
Mat circles = new Mat(bitmap.getWidth(),
        bitmap.getHeight(), CvType.CV_8UC1);

/* find the circle in the image */
Imgproc.HoughCircles(grayMat, circles,
        Imgproc.CV_HOUGH_GRADIENT, dp, minDist, param1,
        param2, minRadius, maxRadius);

/* get the number of circles detected */
int numberOfCircles = (circles.rows() == 0) ? 0 : circles.cols();

/* draw the circles found on the image */
for (int i=0; i<numberOfCircles; i++) {

/* get the circle details, circleCoordinates[0, 1, 2] = (x,y,r)
 * (x,y) are the coordinates of the circle's center
 */
    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];

    /* circle's outline */
    Core.circle(mat, center, radius, new Scalar(0,
            255, 0), 4);

    /* circle's center outline */
    Core.rectangle(mat, new Point(x - 5, y - 5),
            new Point(x + 5, y + 5),
            new Scalar(0, 128, 255), -1);
}

/* convert back to bitmap */
Utils.matToBitmap(mat, bitmap);

Update
In order to prevent the UnsatisfiedLinkError, before using OpenCV library's functions, ensure you load the library files, as I have done below:
if (!OpenCVLoader.initDebug()) {
    Log.e(TAG, "Cannot connect to OpenCV Manager");
}

