2015-04-25 2 views
2

Я думаю, проще всего объяснить проблему с изображением: two cubesРасчет расстояния между 2 гомография плоскостей, которые разделяют плоскость заземления

У меня есть два кубика (одинакового размера), которые возлагают на стол. Одна из них отмечена зеленым цветом (для удобства отслеживания). Я хочу рассчитать относительное положение (x, y) левого куба в правый куб (красная линия на изображении) в блоке размера куба.

Возможно ли это? Я знаю, что проблема будет простой, если эти две зеленые стороны будут иметь общую плоскость - например, верхнюю часть куба, но я не могу использовать ее для отслеживания. Я бы просто вычислил гомографию на один квадрат и умножался на другой угол куба.

Должен ли я «вращать» матрицу гомологии, умножая матрицу вращения 90deegre на получение «наземной» гомографии? Я планирую заниматься обработкой в ​​сценарии смартфонов, поэтому, возможно, гироскоп, внутренние параметры камеры могут иметь любую ценность.

+0

вы должны откалибровать камеру на плоскость заземления ... для этого у вас должно быть 4 известных точки заземления. если вы хотите измерить в единицах размера куба, было бы легче всего узнать 4 точки куба, которые лежат на плоскости земли в пиксельных координатах. к сожалению, вы видите 3 на изображении. возможно, вы можете приблизиться. 1 или просто использовать 4 на верхней плоскости ... – Micka

ответ

0

Это возможно. Предположим (или укажите), что таблица является плоскостью z = 0 и что ваш первый ящик находится в начале этой плоскости. Это означает, что зеленые углы левого окна имеют (таблицы) координаты (0,0,0), (1,0,0), (0,0,1) и (1,0,1). (Ваша коробка имеет размер 1). У вас также есть пиксельные координаты этих точек. Если вы дадите эти 2d и 3d-значения (а также внутренности и искажения камеры) cv :: solvePnP, вы получите относительную Позу камеры к своей коробке (и плоскости).

На следующем шаге вам нужно пересечь плоскость стола с лучом, который идет от центра вашей камеры через нижний правый угловой пиксел второй зеленой коробки. Это пересечение будет выглядеть как (x, y, 0), а [x-1, y] будет переводом между правыми углами ваших ящиков.

0

Если у вас есть вся информация (встроенные камеры), вы можете сделать это так, как ответил FooBar.

Но вы можете использовать информацию о том, что точки лежат на одной плоскости, даже более непосредственно с омографией (нет необходимости расчета лучей и т.д.):

вычислит гомографию между плоскостью изображения и заземлением. К сожалению, вам нужны 4-точечные соответствия, но на изображении есть только 3 точки куба, касаясь плоскости земли. Вместо этого вы можете использовать верхнюю плоскость кубов, где можно измерить то же расстояние.

первый код:

int main() 
{ 
    // calibrate plane distance for boxes 
    cv::Mat input = cv::imread("../inputData/BoxPlane.jpg"); 


    // if we had 4 known points on the ground plane, we could use the ground plane but here we instead use the top plane 
    // points on real world plane: height = 1: // so it's not measured on the ground plane but on the "top plane" of the cube 
    std::vector<cv::Point2f> objectPoints; 
    objectPoints.push_back(cv::Point2f(0,0)); // top front 
    objectPoints.push_back(cv::Point2f(1,0)); // top right 
    objectPoints.push_back(cv::Point2f(0,1)); // top left 
    objectPoints.push_back(cv::Point2f(1,1)); // top back 

    // image points: 
    std::vector<cv::Point2f> imagePoints; 
    imagePoints.push_back(cv::Point2f(141,302));// top front 
    imagePoints.push_back(cv::Point2f(334,232));// top right 
    imagePoints.push_back(cv::Point2f(42,231)); // top left 
    imagePoints.push_back(cv::Point2f(223,177));// top back 

    cv::Point2f pointToMeasureInImage(741,200); // bottom right of second box 


    // for transform we need the point(s) to be in a vector 
    std::vector<cv::Point2f> sourcePoints; 
    sourcePoints.push_back(pointToMeasureInImage); 
    //sourcePoints.push_back(pointToMeasureInImage); 
    sourcePoints.push_back(cv::Point2f(718,141)); 
    sourcePoints.push_back(imagePoints[0]); 


    // list with points that correspond to sourcePoints. This is not needed but used to create some ouput 
    std::vector<int> distMeasureIndices; 
    distMeasureIndices.push_back(1); 
    //distMeasureIndices.push_back(0); 
    distMeasureIndices.push_back(3); 
    distMeasureIndices.push_back(2); 


    // draw points for visualization 
    for(unsigned int i=0; i<imagePoints.size(); ++i) 
    { 
     cv::circle(input, imagePoints[i], 5, cv::Scalar(0,255,255)); 
    } 
    //cv::circle(input, pointToMeasureInImage, 5, cv::Scalar(0,255,255)); 
    //cv::line(input, imagePoints[1], pointToMeasureInImage, cv::Scalar(0,255,255), 2); 

    // compute the relation between the image plane and the real world top plane of the cubes 
    cv::Mat homography = cv::findHomography(imagePoints, objectPoints); 



    std::vector<cv::Point2f> destinationPoints; 
    cv::perspectiveTransform(sourcePoints, destinationPoints, homography); 

    // compute the distance between some defined points (here I use the input points but could be something else) 
    for(unsigned int i=0; i<sourcePoints.size(); ++i) 
    { 
     std::cout << "distance: " << cv::norm(destinationPoints[i] - objectPoints[distMeasureIndices[i]]) << std::endl; 

     cv::circle(input, sourcePoints[i], 5, cv::Scalar(0,255,255)); 
     // draw the line which was measured 
     cv::line(input, imagePoints[distMeasureIndices[i]], sourcePoints[i], cv::Scalar(0,255,255), 2); 
    } 


    // just for fun, measure distances on the 2nd box: 
    float distOn2ndBox = cv::norm(destinationPoints[0]-destinationPoints[1]); 
    std::cout << "distance on 2nd box: " << distOn2ndBox << " which should be near 1.0" << std::endl; 
    cv::line(input, sourcePoints[0], sourcePoints[1], cv::Scalar(255,0,255), 2); 


    cv::imshow("input", input); 
    cv::waitKey(0); 
    return 0; 
} 

Вот вывод, который я хочу объяснить:

distance: 2.04674 
distance: 2.82184 
distance: 1 
distance on 2nd box: 0.882265 which should be near 1.0 

эти расстояния:

1. the yellow bottom one from one box to the other 
2. the yellow top one 
3. the yellow one on the first box 
4. the pink one 

так красная линия (вы просили) должна иметь длину почти ровно 2 x длины стороны куба. Но у нас есть некоторая ошибка, как вы можете видеть.

enter image description here

/лучше более корректных ваши позиции пикселя пред гомография вычисления, тем более точные результаты.

Вам нужна модель камеры-обскуры, поэтому неиспользуйте свою камеру (в реальном мире).

помните, что вы могли бы вычислить расстояния на плоскости земли, если бы у вас было 4 линейных точки, видимых там (которые не лежат на одной линии)!

Смежные вопросы