17

My goal is to overlay a standard UIKit view (for the moment, I'm just creating a UILabel but eventually I'll have custom content) over a detected shape using image tracking and the Vuforia AR SDK. I have something that works, but with a "fudge" term that I cannot account for. I'd like to understand where my error is, so I can either justify the existence of this correction or use a different algorithm that's known to be valid.

My project is based on the ImageTargets sample project in the Vuforia SDK. Where their EAGLView iterates over the results to render the OpenGL teapots, I've replaced this with a call out to my ObjC++ class TrackableObjectController. For each trackable result, it does this:

- (void)augmentedRealityView:(EAGLView *)view foundTrackableResult:(const QCAR::TrackableResult *)trackableResult
{
    // find out where the target is in Core Animation space
    const QCAR::ImageTarget* imageTarget = static_cast<const QCAR::ImageTarget*>(&(trackableResult->getTrackable()));
    TrackableObject *trackable = [self trackableForName: TrackableName(imageTarget)];
    trackable.tracked = YES;
    QCAR::Vec2F size = imageTarget->getSize();
    QCAR::Matrix44F modelViewMatrix = QCAR::Tool::convertPose2GLMatrix(trackableResult->getPose());
    CGFloat ScreenScale = [[UIScreen mainScreen] scale];
    float xscl = qUtils.viewport.sizeX/ScreenScale/2;
    float yscl = qUtils.viewport.sizeY/ScreenScale/2;
    QCAR::Matrix44F projectedTransform = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
    QCAR::Matrix44F qcarTransform = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
    /* this sizeFudge constant is here to put the label in the correct place in this demo; I had thought that
     * the problem was related to the units used (I defined the length of the target in mm in the Target Manager;
     * the fact that I've got to multiply by ten here could be indicative of the app interpreting length in cm).
     * That turned out not to be the case, when I changed the reported length of the target it stopped drawing the
     * label at the correct size. Currently, therefore, the app and the target database are both using mm, but
     * there's the following empirically-divised fudge factor to get the app to position the correctly-sized view
     * in the correct position relative to the detected object.
     */
    const double sizeFudge = 10.0;
    ShaderUtils::translatePoseMatrix(sizeFudge * size.data[0] / 2, sizeFudge * size.data[1] / 2, 0, projectedTransform.data);
    ShaderUtils::scalePoseMatrix(xscl, -yscl, 1.0, projectedTransform.data); // flip along y axis
    ShaderUtils::multiplyMatrix(projectedTransform.data, qUtils.projectionMatrix.data, qcarTransform.data);
    ShaderUtils::multiplyMatrix(qcarTransform.data, modelViewMatrix.data, qcarTransform.data);
    CATransform3D transform = *((CATransform3D*)qcarTransform.data); // both are array[16] of float
    transform = CATransform3DScale(transform,1,-1,0); //needs flipping to draw
    trackable.transform = transform;
}

There is then other code, called on the main thread, that looks at my TrackableObject instances, applies the computed CATransform3D to the overlay view's layer and sets the overlay view as a subview of the EAGLView.

My problem is, as the comment in the code sample has given away, with this sizeFudge factor. Apart from this factor, the code I have does the same thing as this answer; but that's putting my view in the wrong place.

Empirically I find that if I do not include the sizeFudge term, then my overlay view tracks the orientation and translation of the tracked object well but is offset down and to the right on the iPad screen—this is a translation difference, so it makes sense that changing the term used for . I first thought that the problem was the size of the object as specified in Vuforia's Target Manager. This turns out not to be the case; if I create a target ten times the size then the overlay view is drawn in the same, incorrect place but ten times smaller (as the AR assumes the object it's tracking is further away, I suppose).

It's only translating the pose here that gets me where I want to be, but this is unsatisfactory as it doesn't make any sense to me. Can anyone please explain the correct way to translate from a OpenGL coordinates as supplied by Vuforia to a CATransform3D that doesn't rely on magic numbers?

** Some more data **

The problem is more complicated than I thought when I wrote this question. The location of the label actually seems to depend on the distance from the iPad to the tracked object, though not linearly. There's also an apparent systematic error.

Here's a chart constructed by moving the iPad to a certain distance away from the target (located over the black square), and marking with a pen where the centre of the view appeared. Points above and to the left of the square have the translation fudge as described above, points below and to the right have sizeFudge==0. Hopefully the relationship between distance and offset shown here clue someone with more knowledge of 3D graphics than me into what the problem with the transform is.

Chart as described in the previous paragraph.

4

1 回答 1

1

这可能首先与您的视图设置有关。奇怪的偏移量可能是由于宽度和高度的错误方式或任何其他可能的不正确值(例如在 iPad 上使用 iPhone 屏幕比例)引起的。

你的应用是风景吗?如果是这样,那就试试纵向吧。我过去注意到应用程序似乎总是以纵向屏幕尺寸启动(尽管我还没有证实这一点),所以如果您的视图设置发生在屏幕是“正确的方式”之前,您将得到不匹配。

你也可以试着计算出它到底差了多少。而不是乘以 size.data 作为一种技巧:添加另一个翻译并调整数字直到它是正确的。这些数字可能会让您更好地了解正在发生的事情。*10 可能只是侥幸,并没有多大意义。

于 2013-03-18T10:40:52.317 回答