Android OpenCV Color detection

前端 未结 2 1126
梦谈多话
梦谈多话 2020-12-21 06:32

Currently I\'m developing an app that will detect colored circles. I\'m trying to do this by following this tutorial, where guy detects red circles on image with Python. I\'

相关标签:
2条回答
  • 2020-12-21 06:53

    Your mat is of CvType.CV_8UC1 image, i.e. you are working on a grayscale image. Try with CvType.CV_8UC3

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

    hsv_image should look like this:

    enter image description here

    How to select a custom range:


    You may want to detect a green circle. Well, in HSV, tipically the range is:

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

    However, for CV_8UC3 images, each component H,S,V can be represented by only 256 values at most, since it's stored in 1 byte. So, in OpenCV, the ranges H,S,V for CV_8UC3 are:

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

    So to switch from typical range to OpenCV range you need to:

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

    So, green colors are around the value of hue of 120. The hue can have a value in the interval [0,360]. However, for Mat3b HSV images, the range for H is in [0,180], i.e. is halved so it can fit in a 8 bit representation with at most 256 possible values. So, you want the H value to be around 120 / 2 = 60, say from 50 to 70. You also set a minimum value for S,V to 100 in order to prevent very dark (almost black) colors.

    Mat green_hue_range
    inRange(hsv_image, cv::Scalar(50, 100, 100), cv::Scalar(70, 255, 255), green_hue_range);
    
    0 讨论(0)
  • 2020-12-21 07:08

    use the following code and pass color to Blob detector and then pass an image to the detector

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

    // Blob Detector

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

    now set detector

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

    now pass an image to a detector object

     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;
    

    Happy Codeing !!!

    0 讨论(0)
提交回复
热议问题