Domanda

I need to do color detection(ball tracking) for Augmented Reality. I want to use Qualcomms Vuforia SDK for AR and OpenCV for image processing. I found a color detection algorithm that works on desktop(OpenCV, C++) and tried to apply this to FrameMarkers(a Vuforia sample code) but no success yet.

I got a frame from Vuforia(I can only get RGB565 or GRAYSCALE frames.) and convert to OpenCV Mat object and apply same steps with desktop solution. But I got an error on HSV conversion side. Below is the code.

//HSV range for orange objects
const int H_MIN = 7;
const int S_MIN = 186;
const int V_MIN = 60;

const int H_MAX = 256;
const int S_MAX = 256;
const int V_MAX = 157;

const bool shouldUseMorphologicalOperators = true;

const int FRAME_WIDTH = 240;
const int FRAME_HEIGHT = 320;

const int MAX_NUM_OBJECTS = 50;
const int MIN_OBJECT_AREA = 20 * 20;
const int MAX_OBJECT_AREA = 320 * 240 / 1.5;


ObjectTracker::ObjectTracker()
{
    x=y=0;
}

ObjectTracker::~ObjectTracker()
{

}

void ObjectTracker::track(QCAR::Frame frame)
{
    int nImages = frame.getNumImages();
    for(int i = 0; i < nImages; i++)
    {
        const QCAR::Image *image = frame.getImage(i);
        if(image->getFormat() == QCAR::RGB565)
        {
            Mat RGB565 = Mat(image->getHeight(),image->getWidth(),CV_8UC2,(unsigned char *)image->getPixels());

            Mat HSV;
                    //I got error an error here
            cvtColor(RGB565,HSV,CV_RGB2HSV);


            Mat thresholdedImage;
            inRange(HSV,Scalar(H_MIN,S_MIN,V_MIN),Scalar(H_MAX,S_MAX,V_MAX),thresholdedImage);

            if(shouldUseMorphologicalOperators)
                applyMorphologicalOperator(thresholdedImage);

            trackFilteredObject(x,y,thresholdedImage,RGB565);

            //waitKey(30);
        }
    }

}

void ObjectTracker::applyMorphologicalOperator(Mat &thresholdedImage)
{
    //create structuring element that will be used to "dilate" and "erode" image
    //the element chosen here is 3px by 3px rectangle

    Mat erodeElement = getStructuringElement(MORPH_RECT,Size(3,3));
    //dilate with larger element so make sure object is nicely visible
    Mat dilateElement = getStructuringElement(MORPH_RECT,Size(8,8));

    erode(thresholdedImage,thresholdedImage,erodeElement);
    erode(thresholdedImage,thresholdedImage,erodeElement);

    dilate(thresholdedImage,thresholdedImage,dilateElement);
    dilate(thresholdedImage,thresholdedImage,dilateElement);
}

void ObjectTracker::trackFilteredObject(int &x,int &y,Mat &thresholdedImage,Mat &cameraFeed)
{
    Mat temp;
    thresholdedImage.copyTo(temp);
    //Two vectors needed for output of findContours
    vector< vector<Point> > contours;
    vector<Vec4i> hierarcy;
    //find contours of filtered image using openCV findContours function
    findContours(temp,contours,hierarcy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE);
    //use moments method to find out filtered object
    double refArea = 0;
    bool objectFound = false;
    if(hierarcy.size() > 0)
    {
        int nObjects = hierarcy.size();
        //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
        if(nObjects < MAX_NUM_OBJECTS )
        {
            for(int index = 0; index >= 0; index = hierarcy[index][0])
            {
                Moments moment = moments((cv::Mat)contours[index]);
                double area = moment.m00;

                //if the area is less than 20 px by 20 px then it is probably just noise
                //if the area is the same as the 3/2 of the image size, probably just a bad filter
                //we only want the object with the largest area so we safe a reference area each
                //iteration and compare it to the area in the next iteration.
                if(area > MIN_OBJECT_AREA && area < MAX_OBJECT_AREA && area > refArea)
                {
                    x = moment.m10/area;
                    y = moment.m01/area;
                    objectFound = true;
                    refArea = area;
                }
                else
                    objectFound = false;
            }

            //let user know you found an object
            if(objectFound ==true)
            {
                LOG("Object found");
                highlightObject(x,y,cameraFeed);
            }
        }
        else
        {
            LOG("Too much noise");
        }
    }
    else
        LOG("Object not found");
}

void ObjectTracker::highlightObject(int x,int y,Mat &frame)
{
}

How to do proper conversion from RGB565 to HSV color space?

È stato utile?

Soluzione

Convert it to RGB888 first using some code from this SO Question. If you have RGB888 your conversion to HSV should work fine.

EDIT: As mentioned in the Comment. In OpenCV you can do it like this:

use cvtColor(BGR565,RGB,CV_BGR5652BGR) to conver from RGB565 to RGB and then cvtColor(RGB,HSV,CV_RGB2HSV) to convert from RGB to HSV.

EDIT2: It seems that you have to use BGR5652BGR since there is no RGB5652RGB

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top