Мне нужно сделать определение цвета (отслеживание шара) для дополненной реальности. Я хочу использовать Qualcomms Vuforia SDK для AR и OpenCV для обработки изображений. Я нашел алгоритм определения цвета, который работает на рабочем столе (OpenCV, C ++), и попытался применить его к FrameMarkers (образец кода Vuforia), но пока безуспешно.
Я получил кадр от Vuforia (я могу получить только кадры RGB565 или GRAYSCALE.) И преобразовал его в объект OpenCV Mat и применил те же шаги с настольным решением. Но я получил ошибку на стороне преобразования HSV. Ниже приведен код.
//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)
{
}
Как правильно преобразовать RGB565 в цветовое пространство HSV?
Сначала преобразуйте его в RGB888, используя некоторый код из этого ТАК Вопрос.
Если у вас RGB888, ваше преобразование в HSV должно работать нормально.
РЕДАКТИРОВАТЬ: Как упомянуто в комментарии. В OpenCV вы можете сделать это так:
использование cvtColor(BGR565,RGB,CV_BGR5652BGR)
конвертировать из RGB565 в RGB, а затем cvtColor(RGB,HSV,CV_RGB2HSV)
конфертировать из RGB в HSV.
EDIT2: Кажется, что вы должны использовать BGR5652BGR, так как нет RGB5652RGB
Других решений пока нет …