Android OpenCV - 检测颜色的圆圈给出"图像必须是HoughCircle中的8位单通道"错误?

时间:2015-06-08 02:34:32

标签: android opencv bitmap

美好的一天。很抱歉这个长标题,我甚至不得不削减它,因为我超过了150个字符的限制。

我正在构建一个Android应用程序,我希望能够检测到黑色圆圈。我正在使用OpenCV3 for Android,我可以使用下面的代码从我的相机Feed中滤除黑色。请注意,我使用了Android SDK中给出的Color-blob检测示例并调整了代码:

public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    mRgba = inputFrame.rgba();

    if (mIsColorSelected) {

        Bitmap resultBitmap;

        resultBitmap = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(),Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(mRgba, resultBitmap);

        //TODO - look for circles
        Mat mat = new Mat(resultBitmap.getWidth(), resultBitmap.getHeight(), CvType.CV_8UC1);
        Utils.bitmapToMat(resultBitmap, mat);

        final Bitmap bitmap;

        //TODO - filter out the black only
        Mat mHSV = mat;
        Mat mHSVThreshed = mat;
        Mat mRgba2 = mat;

        Imgproc.cvtColor(mat, mHSV, Imgproc.COLOR_BGR2HSV, 0);
        Core.inRange(mHSV, new Scalar(0, 0, 0), new Scalar(130, 130, 130), mHSVThreshed);
        Imgproc.cvtColor(mHSVThreshed, mat, Imgproc.COLOR_GRAY2BGR, 0);
        Imgproc.cvtColor(mat, mRgba2, Imgproc.COLOR_BGR2RGBA, 0);

        Imgproc.GaussianBlur(mRgba2, mRgba2, new Size(9, 9), 2, 2);

        //this is for displaying purposes only. 
        //At this point, the image would be black and white, where the white spots are the black detected blobs 
        //            Bitmap bmp = Bitmap.createBitmap(mRgba2.cols(), mRgba2.rows(), Bitmap.Config.ARGB_8888);
        //Utils.matToBitmap(mRgba2, bmp);
       //bitmap = bmp; //resultBitmap;

        //TODO - new circle detection code: this uses the colour filtered Mat
        mat = mRgba2;
        Imgproc.HoughCircles(mat, circles,
                Imgproc.CV_HOUGH_GRADIENT, 1, minDist, 100,
                20, 0, 0);

        /* 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 */
            Imgproc.circle(mRgba2, center, radius, new Scalar(0,
                    200, 255), 4);

            /* circle's center outline */
            Imgproc.rectangle(mRgba2, new Point(x - 5, y - 5),
                    new Point(x + 5, y + 5),
                    new Scalar(0, 200, 255), -1);
        }
        Utils.matToBitmap(mRgba2, resultBitmap);

        bitmap = resultBitmap;

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mOpenCvCameraView.disableView();
                mOpenCvCameraView.setVisibility(SurfaceView.GONE);
                imageView.setVisibility(View.VISIBLE);
                imageView.setImageBitmap(bitmap);
            }
        });
    }
    return mRgba;
}

我的代码所做的是它将相机提要的快照作为Mat,然后使用该Mat,我对其进行一些图像处理并将除黑色之外的所有内容涂黑。生成的Mat是mRgba2变量,我转换为Bitmap并显示在ImageView上。我显示了这个位图,以确认我得到了我想要的结果。

在我知道我能够过滤掉我想要的颜色后,我会在其上运行GaussianBlur然后继续运行HoughCircles。但是,当我运行

Imgproc.HoughCircles(mat, circles,
        Imgproc.CV_HOUGH_GRADIENT, 1, minDist, 100,
        20, 0, 0);

行,我得到了

The source image must be 8-bit, single-channel in function CvSeq* cvHoughCircles(CvArr*, void*, int, double, double, double, double, int, int)

错误。

我知道我在给定的mat变量上运行HoughCircles的代码是有效的,因为我之前测试过它。现在,更改我提供给它的mat变量不会,我想知道我做了什么不同的代码不能工作。

非常感谢任何帮助。谢谢。

1 个答案:

答案 0 :(得分:2)

HoughCircles仅在灰度(CV8U)图像上运行。

更换

Imgproc.cvtColor(mat, mRgba2, Imgproc.COLOR_BGR2RGBA, 0);

Imgproc.cvtColor(mat, mRgba2, Imgproc.COLOR_BGR2GRAY, 0);

应该删除错误。

然后问题是检测给定颜色的圆圈。在您的情况下,这不会造成太大问题,因为您无论如何都在检测黑圈。而不是黑色圆圈,这将检测黑眼圈。

如果某些圆圈中的黑色不是黑色,则可以通过查看不同颜色空间中的像素值来单独过滤它们。