在Android中使用OpenCV检测图像中的圆

在Android中使用OpenCV检测图像中的圆,android,opencv,Android,Opencv,我正在开发一个android应用程序,在该应用程序中,我必须检测现有图像上的圆圈,从图库浏览或从相机拍摄。浏览/捕获的图像将显示在ImageView上。顺便说一句,我使用的是OpenCVAndroid库,并且我正确地编译了它 任何帮助我的Android应用程序,我已经阅读C,C++,或等,在检测圈子,但我不能理解它的不同语言的Android。 谢谢 更新 好的。。。我就是这样用的 if (requestCode == 1) { //Take Photo from Andr

我正在开发一个android应用程序,在该应用程序中,我必须检测现有图像上的圆圈,从图库浏览或从相机拍摄。浏览/捕获的图像将显示在ImageView上。顺便说一句,我使用的是OpenCVAndroid库,并且我正确地编译了它

任何帮助我的Android应用程序,我已经阅读C,C++,或等,在检测圈子,但我不能理解它的不同语言的Android。 谢谢

更新

好的。。。我就是这样用的

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

        }
if(requestCode==1){//从Android摄像头拍照。。
文件f=新文件(Environment.getExternalStorageDirectory().toString());
对于(文件温度:f.listFiles()){
if(temp.getName().equals(“temp.jpg”)){
f=温度;
打破
}
}
试一试{
位图;
选项bitmapOptions=新的BitmapFactory.Options();
位图=BitmapFactory.decodeFile(f.getAbsolutePath(),
位图选项);
//位图=位图。createScaledBitmap(位图,70,70,真);
String path=android.os.Environment
.getExternalStorageDirectory()
+文件分隔符
+“Phoenix”+File.separator+“default”;
f、 删除();
OutputStream outFile=null;
File File=new File(路径,String.valueOf(System.currentTimeMillis())+“.jpg”);
试一试{
outFile=新文件OutputStream(文件);
bitmap.compress(bitmap.CompressFormat.JPEG,85,outFile);
outFile.flush();
outFile.close();
}catch(filenotfounde异常){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}捕获(例外e){
e、 printStackTrace();
}
/*将位图转换为mat*/
Mat Mat=新Mat(bitmap.getWidth(),bitmap.getHeight(),
CvType.CV_8UC1);
Mat grayMat=新Mat(位图.getWidth(),位图.getHeight(),
CvType.CV_8UC1);
位图映射器(位图、mat);
/*转换为灰度*/
int colorChannel=(mat.channels()==3)?Imgproc.COLOR\u bgr2灰色
:((材质通道()==4)?Imgproc.COLOR\u BGRA2GRAY:1);
Imgproc.cvtColor(mat、grayMat、彩色通道);
/*减少噪音,避免假圆检测*/
GaussianBlur(grayMat,grayMat,新尺寸(9,9,2,2));
//累加器值
双dp=1.2d;
//检测到的圆的中心坐标之间的最小距离(像素)
双重正念者=20;
//最小和最大半径(根据需要设置这些值)
int minRadius=0,maxRadius=0;
//param1=用于处理边缘检测的梯度值
//param2=该参数的累加器阈值
//cv2.CV_-HOUGH_梯度法。
//阈值越小,圆圈就越多
//检测到(包括假圆)。
//阈值越大,圆圈就越多
//可能会被退回。
双参数1=70,参数2=72;
/*创建Mat对象以存储检测到的圆*/
垫圆=新垫(位图.getWidth(),
bitmap.getHeight(),CvType.CV_8UC1);
/*在图中找到圆圈*/
Imgproc.HoughCircles(灰色、圆形、,
Imgproc.CV_HOUGH_GRADIENT,dp,Minist,param1,
参数2,最小半径,最大半径);
/*获取检测到的圆数*/
int numberOfCircles=(circles.rows()==0)?0:circles.cols();
/*画出图像上的圆圈*/

对于(int i=0;i可以找到关于圆检测的详细解释,尽管不是Java语言)

我在下面提供了一个用于圆检测的示例代码段,该代码段来自我上面提供的两个链接。该代码带有注释,因此易于理解。我假设图像位图
bitmap
已经具有要分析的图像

/* 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);

在第行:int numberOfCircles=(circles.rows()==0):0?circles.cols();出现错误。请修复。谢谢!我将更正您的Utils.matToBitmap(位图,mat);它是(mat,bitmap);我想。你能在你的问题中发布你的代码吗?我想看看你是如何使用圆圈检测代码片段的。我把它放在我的代码中的什么地方??在将位图转换为mat之前,先生?@cloudmorales在调用OpenCV的函数之前放置它。
/* 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);
if (!OpenCVLoader.initDebug()) {
    Log.e(TAG, "Cannot connect to OpenCV Manager");
}