Android OpenCV颜色检测

时间:2015-07-07 23:36:15

标签: android opencv colors

目前我正在开发一款可以检测彩色圆圈的应用。我正在尝试按照this教程执行此操作,其中man使用Python检测图像上的红色圆圈。我编写了相同的代码,仅用于Java。

                    Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(),
                            CvType.CV_8UC3);

                    Mat hsv_image = new Mat();
                    Utils.bitmapToMat(bitmap, mat);
                    Imgproc.cvtColor(mat, hsv_image, Imgproc.COLOR_BGR2HSV);

                    Mat lower_red_hue_range = new Mat();
                    Mat upper_red_hue_range = new Mat();

                    Core.inRange(hsv_image, new Scalar(0, 100, 100), new Scalar(10, 255, 255), lower_red_hue_range);
                    Core.inRange(hsv_image, new Scalar(160, 100, 100), new Scalar(179, 255, 255), upper_red_hue_range);
                    Utils.matToBitmap(hsv_image, bitmap);
                mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
                image.setImageBitmap(mutableBitmap);

我使用的图像与教程中的图像相同: enter image description here

这是应用BGR2HSV的图像: enter image description here

当我使用较低的红色色调范围执行代码时,它会检测到蓝色圆圈。当我使用上部红色色调范围时,它会给我黑色bmp(没有检测到任何东西)。怎么会这样?我究竟做错了什么?这实际上是从python复制到Java。为什么结果不同呢? 提前谢谢。

2 个答案:

答案 0 :(得分:4)

您的matCvType.CV_8UC1图片,即您正在处理灰度图像。试试CvType.CV_8UC3

Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC3);

hsv_image应如下所示:

enter image description here

如何选择自定义范围:

您可能想要检测绿色圈子。 那么,在HSV中,范围是:

H in [0,360]
S,V in [0,100]

然而,对于CV_8UC3图像,每个分量H,S,V最多只能由256个值表示,因为它以1个字节存储。因此,在OpenCV中,CV_8UC3的范围H,S,V是:

H in [0,180] <- halved to fit in the range
S,V in [0,255] <- stretched to fit the range

因此,要从典型范围切换到OpenCV范围,您需要:

opencv_H = typical_H / 2;
opencv_S = typical_S * 2.55; 
opencv_V = typical_V * 2.55;

因此,绿色在120的色调值附近。色调可以在区间[0,360]中具有值。 然而,对于Mat3b HSV图像,H的范围是[0,180],即减半,因此它可以适合具有至多256个可能值的8位表示。 所以,你希望H值大约为120/2 = 60,比如从50到70。 您还可以将S,V的最小值设置为100,以防止非常暗(几乎是黑色)的颜色。

Mat green_hue_range
inRange(hsv_image, cv::Scalar(50, 100, 100), cv::Scalar(70, 255, 255), green_hue_range);

答案 1 :(得分:0)

使用以下代码并将颜色传递给Blob检测器,然后将图像传递给检测器

private Scalar converScalarRgba2HSV(Scalar rgba) {
Mat  pointMatHsv= new Mat();
Mat pointMatRgba = new Mat(1, 1, CvType.CV_8UC3, rgba);
Imgproc.cvtColor(pointMatRgba,pointMatHsv, Imgproc.COLOR_RGB2HSV_FULL, 4);

return new Scalar(pointMatHsv.get(0, 0));}

//斑点检测器

public class ColorBlobDetector {
// Lower and Upper bounds for range checking in HSV color space
private Scalar mLowerBound = new Scalar(0);
private Scalar mUpperBound = new Scalar(0);
// Minimum contour area in percent for contours filtering
private static double mMinContourArea = 0.1;
// Color radius for range checking in HSV color space
private Scalar mColorRadius = new Scalar(25,50,50,0);
private Mat mSpectrum = new Mat();
private List<MatOfPoint> mContours = new ArrayList<MatOfPoint>();

Mat mPyrDownMat = new Mat();
Mat mHsvMat = new Mat();
Mat mMask = new Mat();
Mat mDilatedMask = new Mat();
Mat mHierarchy = new Mat();

public void setColorRadius(Scalar radius) {
    mColorRadius = radius;
}

public void setHsvColor(Scalar hsvColor) {
    double minH = (hsvColor.val[0] >= mColorRadius.val[0]) ? hsvColor.val[0]-mColorRadius.val[0] : 0;
    double maxH = (hsvColor.val[0]+mColorRadius.val[0] <= 255) ? hsvColor.val[0]+mColorRadius.val[0] : 255;

    mLowerBound.val[0] = minH;
    mUpperBound.val[0] = maxH;

    mLowerBound.val[1] = hsvColor.val[1] - mColorRadius.val[1];
    mUpperBound.val[1] = hsvColor.val[1] + mColorRadius.val[1];

    mLowerBound.val[2] = hsvColor.val[2] - mColorRadius.val[2];
    mUpperBound.val[2] = hsvColor.val[2] + mColorRadius.val[2];

    mLowerBound.val[3] = 0;
    mUpperBound.val[3] = 255;

    Mat spectrumHsv = new Mat(1, (int)(maxH-minH), CvType.CV_8UC3);

    for (int j = 0; j < maxH-minH; j++) {
        byte[] tmp = {(byte)(minH+j), (byte)255, (byte)255};
        spectrumHsv.put(0, j, tmp);
    }

    Imgproc.cvtColor(spectrumHsv, mSpectrum, Imgproc.COLOR_HSV2RGB_FULL, 4);
}

public Mat getSpectrum() {
    return mSpectrum;
}

public void setMinContourArea(double area) {
    mMinContourArea = area;
}

public void process(Mat rgbaImage) {
    Imgproc.pyrDown(rgbaImage, mPyrDownMat);
    Imgproc.pyrDown(mPyrDownMat, mPyrDownMat);

    Imgproc.cvtColor(mPyrDownMat, mHsvMat, Imgproc.COLOR_RGB2HSV_FULL);

    Core.inRange(mHsvMat, mLowerBound, mUpperBound, mMask);
    Imgproc.dilate(mMask, mDilatedMask, new Mat());

    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();

    Imgproc.findContours(mDilatedMask, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    // Find max contour area
    double maxArea = 0;
    Iterator<MatOfPoint> each = contours.iterator();
    while (each.hasNext()) {
        MatOfPoint wrapper = each.next();
        double area = Imgproc.contourArea(wrapper);
        if (area > maxArea)
            maxArea = area;
    }

    // Filter contours by area and resize to fit the original image size
    mContours.clear();
    each = contours.iterator();
    while (each.hasNext()) {
        MatOfPoint contour = each.next();
        if (Imgproc.contourArea(contour) > mMinContourArea*maxArea) {
            Core.multiply(contour, new Scalar(4,4), contour);
            mContours.add(contour);
        }
    }
}

public List<MatOfPoint> getContours() {
    return mContours;
}}

现在设置检测器

public void initDetector() {

    mDetector = new ColorBlobDetector();
    mSpectrum = new Mat();
    mBlobColorRgba = new Scalar(255);
    mBlobColorHsv = new Scalar(255);
    SPECTRUM_SIZE = new org.opencv.core.Size(500, 64);
    CONTOUR_COLOR = new Scalar(0, 255, 0, 255);


    mDetector.setHsvColor(converScalarRgba2HSV(new Scalar(0,255,255,255)));

    Imgproc.resize(mDetector.getSpectrum(), mSpectrum, SPECTRUM_SIZE, 0, 0, Imgproc.INTER_LINEAR_EXACT);

    mIsColorSelected = true;

}

现在将图像传递到检测器对象

 Mat mRgba = new Mat(inputFrame.height(), inputFrame.width(), CvType.CV_8UC4);
    mRgba = inputFrame;

        mDetector.process(mRgba);
        List<MatOfPoint> contours = mDetector.getContours();

        Log.e(TAG, "Contours count: " + contours.size());
       drawContours(mRgba, contours, -1, CONTOUR_COLOR);
       return mRgba;

快乐编码!!!