Question

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?

Was it helpful?

Solution

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top