简体   繁体   English

使用适用于Android的OpenCV在Vuforia框架上进行颜色检测

[英]Color detection on Vuforia frames with OpenCV for Android

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. 我想将高通Vuforia SDK用于AR和OpenCV进行图像处理。 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. 我发现了一种可在桌面(OpenCV,C ++)上运行的颜色检测算法,并试图将其应用于FrameMarkers(Vuforia示例代码),但尚未成功。

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. 我从Vuforia获得了一个框架(我只能获得RGB565或GREYSCALE框架。)并转换为OpenCV Mat对象,并使用桌面解决方案应用相同的步骤。 But I got an error on HSV conversion side. 但是我在HSV转换方面遇到了错误。 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? 如何从RGB565正确转换为HSV颜色空间?

Convert it to RGB888 first using some code from this SO Question . 首先使用此SO Question中的一些代码将其转换为RGB888。 If you have RGB888 your conversion to HSV should work fine. 如果您具有RGB888,则可以顺利转换为HSV。

EDIT : As mentioned in the Comment. 编辑 :如评论中所述。 In OpenCV you can do it like this: 在OpenCV中,您可以这样做:

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. 使用cvtColor(BGR565,RGB,CV_BGR5652BGR)从RGB565转换为RGB,然后使用cvtColor(RGB,HSV,CV_RGB2HSV)从RGB转换为HSV。

EDIT2 : It seems that you have to use BGR5652BGR since there is no RGB5652RGB EDIT2 :似乎您必须使用BGR5652BGR,因为没有RGB5652RGB

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM