Object Tracking
Introduction to Object Tracking
Object Recognition and Tracking extends the capabilities of the Wikitude SDK to recognize and track arbitrary objects for augmented reality experiences. The feature is based on Wikitude's SLAM engine that is also used for Instant Tracking. Object Tracking let you detect objects, that were pre-defined by you. Suitable objects include
- Toys
- Monuments and statues
- Industrial objects
- Tools
- Household supplies
Simple Object Tracking
The Simple Object Tracking sample should just give you a rough idea of how object tracking works with the Wikitude Native SDK. We will track a toy fire truck and add a stroked cube as well as an occluder cube to demonstrate its use.
Object Tracking means that instead of tracking an image we track 3-dimensional objects, using information that has been extracted from a video of that object. This is why instead of a Wikitude Target Collection (.wtc
) we use a .wto
-file (Wikitude Object Target Collection) in this sample.
To use object tracking with the Wikitude Native SDK we have to make our Activity
implement the ObjectTrackerListener
interface and we will need to create an ObjectTracker
as well as a StrokedCube
and an OccluderCube
using the GLRenderer
class.
public class ObjectTrackingActivity extends Activity implements ObjectTrackerListener, ExternalRendering
After creating and initializing the Wikitude Native SDK object we create a TargetCollectionResource
that points to the firetruck_map.wto (Wikitude Object Target Collection) file and hand it over to the TrackerManager
's createObjectTracker
method to create the object tracker, passing the Activity
as the listener.
mTargetCollectionResource = mWikitudeSDK.getTrackerManager().createTargetCollectionResource("file:///android_asset/firetruck_map.wto", new TargetCollectionResourceLoadingCallback() {
@Override
public void onError(int errorCode, String errorMessage) {
Log.v(TAG, "Failed to load target collection resource. Reason: " + errorMessage);
}
@Override
public void onFinish() {
mWikitudeSDK.getTrackerManager().createObjectTracker(mTargetCollectionResource, ObjectTrackingActivity.this, null);
}
});
In the onObjectRecognized
method we allocate a SrokedCube
instance and an OccluderCube
instance and register it with the renderer under the name of the recognized target.
@Override
public void onObjectRecognized(ObjectTracker tracker, final ObjectTarget target) {
[...]
StrokedCube strokedCube = new StrokedCube();
OccluderCube occluderCube = new OccluderCube();
mGLRenderer.setRenderablesForKey(target.getName(), strokedCube, occluderCube);
}
Correspondingly, the cube instances are unregistered again when the target is lost.
@Override
public void onObjectLost(ObjectTracker tracker, final ObjectTarget target) {
[...]
mGLRenderer.removeRenderablesForKey(target.getName());
}
The cubes are updated within the onObjectTracked
method. The instances are retrieved from the renderer using the supplied target name and are subsequently updated using the information stored in the ObjectTarget
parameter. The 0.5 offset on the Y-axis accounts for the origin being on the bottom of the object rather than the center in this particular map.
@Override
public void onObjectTracked(ObjectTracker tracker, final ObjectTarget target) {
StrokedCube strokedCube = (StrokedCube)mGLRenderer.getRenderableForKey(target.getName());
if (strokedCube != null) {
strokedCube.projectionMatrix = target.getProjectionMatrix();
strokedCube.viewMatrix = target.getViewMatrix();
strokedCube.setYTranslate(0.5f);
strokedCube.setXScale(target.getTargetScale().getX());
strokedCube.setYScale(target.getTargetScale().getY());
strokedCube.setZScale(target.getTargetScale().getZ());
}
OccluderCube occluderCube = (OccluderCube)mGLRenderer.getOccluderForKey(target.getName());
if (occluderCube != null) {
occluderCube.projectionMatrix = target.getProjectionMatrix();
occluderCube.viewMatrix = target.getViewMatrix();
occluderCube.setYTranslate(0.5f);
occluderCube.setXScale(target.getTargetScale().getX());
occluderCube.setYScale(target.getTargetScale().getY());
occluderCube.setZScale(target.getTargetScale().getZ());
}
}
Finally, similar to the other samples we implement onTargetsLoaded
and onErrorLoadingTargets
to simply log to the console to provide information about the loading process.
@Override
public void onTargetsLoaded(ObjectTracker tracker) {
Log.v(TAG, "Object tracker loaded");
}
@Override
public void onErrorLoadingTargets(ObjectTracker tracker, int errorCode, final String errorMessage) {
Log.v(TAG, "Unable to load image tracker. Reason: " + errorMessage);
}
If you add all this to your code, an orange cube will be displayed around the fire truck if you look at it. Since the occluder cube is always at the same posititon as the cube, you can't see the cubes sides that are farther away from the camera since the occluder blocks the view.
Simple Object Tracking