Symbian3/SDK/Source/GUID-60DBA025-8FA0-5DF2-90D0-744A016998EE.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 12:39:03 +0100
changeset 8 ae94777fff8f
parent 7 51a74ef9ed63
child 13 48780e181b38
permissions -rw-r--r--
Week 23 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-60DBA025-8FA0-5DF2-90D0-744A016998EE" xml:lang="en"><title>Panoramic
Stitching Guide</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>This document introduces you to the panoramic stitching functionality. </p>
<section id="GUID-3333CA2A-EF84-5E7B-B9BE-8FF00523897F-GENID-1-10-1-19-1-1-5-1-6-1-11-1-4-1-3-1-4-1-3-1-2-2"><title>Purpose</title> <p>Panoramic
stitching involves combining a collection of images into a single image. </p> </section>
<section><title>Panoramic stitching overview</title> <p>The panorama image
is created by stitching a collection of several separate image into one large
image. The panoramic stitching process is done by, </p> <ul>
<li id="GUID-0DA59FD4-B817-5B51-8E83-F56FC42E1675"><p>image registration </p> </li>
<li id="GUID-74941275-9681-51AB-B1FB-4F0829B47075"><p>cylindrical projection
of images </p> </li>
<li id="GUID-70E87CA6-B8BC-5CE9-A545-FC3782A81A69"><p>image blending. </p> </li>
</ul> <p>The panoramic stitch can be done eihter interactively by using camera
viewfinder, for tracking the camera movements or by stitching pre-captured
images together. </p> <p><b>Introduction
about the panoramic stitching</b> </p> <p>The <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> stitches
a set of images into a single panorama image. The input to <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> is
a collection of high resolution images together with some guidance on the
relative positioning between the images expressed by <xref href="GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA.dita"><apiname>CPanoramaTransform</apiname></xref> instances. </p> <p>For
the panorama creation, the most common use is rendering a full size panorama
image to the device file system. </p> <p>The high level steps to use <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> are
shown below: </p> <ul>
<li id="GUID-EF02A22B-B4B1-5E97-97E7-F09DE26DA93A"><p>To construct <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>,
use <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-39BE88C3-C617-3AF8-A13D-CEC60AE798B1"><apiname>CImagePanorama::NewL()</apiname></xref> which loads the image panorama
plugin. </p> </li>
<li id="GUID-690408AF-782D-5E67-93BC-238EBCBD0C20"><p>To initialise <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>,
use <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-B6D24921-92B8-3FD8-B666-91C56E1E7984"><apiname>CImagePanorama::InitialiseL()</apiname></xref>. </p> </li>
<li id="GUID-3E167564-6974-571E-99A0-196A5A18133D"><p>To correct the lens
parameter use <xref href="GUID-90D79D23-97BC-3EE5-98DD-594DF6EFA0EE.dita"><apiname>TPanoramaLens</apiname></xref>. You need to correct the lens
for panorama stitching quality. The lens parameters are camera specific. </p> </li>
<li id="GUID-93217AEB-2AC5-5CCC-B5EE-36E8B99BAA85"><p>To add images to <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>,
use <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-B6591C30-F990-3D75-B9F3-922D41A5F1A1"><apiname>CImagePanorama::AddFileL()</apiname></xref>,<xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-19FBD32E-9B1F-38B0-963A-B361737818D2"><apiname>CImagePanorama::AddBufferL()</apiname></xref> or <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-66509DE8-2DBA-3FE0-8495-32E4256FA939"><apiname>CImagePanorama::AddImageL()</apiname></xref>, providing a hint on relative positioning or translation of the images through <xref href="GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA.dita"><apiname>CPanoramaTransform</apiname></xref>.
This transform only needs to be approximate. </p> </li>
<li id="GUID-B445F73C-2910-56DE-B03D-2637ECED0963"><p>To make the stitched
image available call <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-A098A70C-050C-3592-BC37-E849A81890F2"><apiname>CImagePanorama::RenderL()</apiname></xref>. </p> </li>
<li id="GUID-B68A2C77-F19A-5999-82C1-F433269DAACB"><p>The <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> instance
can then be deleted. </p> </li>
</ul> <p><b> Introduction
about the CVFTracker</b> </p> <p> <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> is used to
track viewfinder images to aid in capturing a panorama. The usage of <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> are
demonstrated as follows: </p> <ul>
<li id="GUID-3496F712-4FCD-5E89-BFEE-5AA6A22A1DA0"><p>The <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> output
is used for providing feedback and guidance to you, on how to move the camera
while capturing a panorama. </p> </li>
<li id="GUID-BDBC8A06-B2F8-507C-81F7-E2F344A94FEA"><p>The <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> is
used as an aid for the stitching process in the <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>.
The input to the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> is a rapid flow of raw images
from the viewfinder of the camera. The output is the movement of the camera. </p> </li>
</ul> <p>The high level steps to use the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> are
shown below: </p> <ul>
<li id="GUID-5C25D0C8-49E1-5514-A90C-2B8A026D20CC"><p>To create <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref>,
use the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-AE92A41F-388D-338C-A80E-C0B16DF3BDDC"><apiname>CVFTracker::NewL()</apiname></xref>. The <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-AE92A41F-388D-338C-A80E-C0B16DF3BDDC"><apiname>CVFTracker::NewL()</apiname></xref> is
used to load the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> plugin. </p> </li>
<li id="GUID-ECE3D707-B871-5EC5-A04D-CA2A632BECC6"><p>To initialise <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref>,
use <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-5E441486-3333-3B4F-81F3-3A86AE541CF8"><apiname>CVFTracker::InitialiseL()</apiname></xref>. </p> </li>
<li id="GUID-54FEF93A-68BB-5EFB-8DE4-21F6562DCF11"><p>To reset <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref>,
use <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-AE707DEA-4747-3A1A-8C6F-8163F1DF0584"><apiname>CVFTracker::Reset()</apiname></xref>. </p> </li>
<li id="GUID-32F88242-4EDD-54C7-8D7A-574015A197F4"><p>To perform the image
registration, use <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-AB58BBEB-5EAE-3E2A-A94E-F59334402A2B"><apiname>CVFTracker::RegisterImageL()</apiname></xref>. </p> </li>
<li id="GUID-01DDC476-9596-55A1-B296-13877DB41B67"><p>To destroy the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref>,
use <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-C2B64F7D-04D8-324A-BD84-C588503881BC"><apiname>CVFTracker::~CVFTracker()</apiname></xref>. </p> </li>
</ul> <p><b>Camera
requirements </b> </p> <p>The camera requirements for the <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> and <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> are
as follows, </p> <ul>
<li id="GUID-C83A6919-C7BB-55C9-9D60-80EDAE0D4458"><p>The camera must provide
low resolution images (in the order of 160 by 120 up to 320 by 240 resolution)
as the raw format at a high frame rate to the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> and
high resolution captured images to the <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>. </p> </li>
<li id="GUID-EF41F660-AAEE-5D31-A014-FD6C39C42C5E"><p>For the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref>,
it is better to have good frame rate than to have high resolution input images. </p> </li>
<li id="GUID-810B06D2-D45F-5E7C-BC62-88AEE0B0A071"><p>The use of large <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> images
can cause a lower frame rate on slow devices, and do not give accurate tracking
for the view finder. </p> </li>
<li id="GUID-DA5C3ED7-550D-5E4E-AD5A-E9119A56D8FB"><p>The optimal size of
images is a tradeoff between the panorama quality and the time for rendering
the panorama. </p> </li>
</ul> </section>
<section><title>How to use Panoramic Stitching</title> <p>This section contains
some code snippets to show, how Panoramic stitching is accessed in several
situations. </p> <p><b>Basic
stitching </b> </p> <p>The basic stitching is demonstrated by a simple example
of stitching four JPEG images into a single JPEG image providing an approximate
translation between each image: </p> <p> </p> <codeblock id="GUID-304B7755-B05B-5BAE-884A-44A0500ABF37" xml:space="preserve">

    TSize imageSize(1200, 1000);
    
    TDirection direction = EPanoramaDirectionRight;
        
    //Lens parameters or internal camera characteristics should be available for the 
    //specific camera module in use. Here we use default values.
      TPanoramaLens lens;
        
    //Create transform. A transform is an approximate offset between each image.
      CPanoramaTransform* panTrans = CPanoramaTransform::NewL();
      CleanupStack::PushL(panTrans);
    
    //Create panorama object.This stitches the individual images together.
      CImagePanorama* panImage = CImagePanorama::NewL();
      CleanupStack::PushL(panImage);
        
    //Create panorama engine and set the lens and size
      panImage-&gt;InitializeL(imageSize, lens, direction);
        
    //Each file added is provided with an approximate translation. 
    //In this case there are 4 images.
      panTrans-&gt;SetTranslationL(TPoint(0, 0), imageSize);
      panImage-&gt;AddFileL(KTestFileName1, *panTrans);
        
    panTrans-&gt;SetTranslationL(TPoint(900, -30), imageSize);
    panImage-&gt;AddFileL(KTestFileName2, *panTrans);
        
    panTrans-&gt;SetTranslationL(TPoint(900, 60), imageSize);
    panImage-&gt;AddFileL(KTestFileName3, *panTrans);
    
    panTrans-&gt;SetTranslationL(TPoint(400, -30), imageSize);
    panImage-&gt;AddFileL(KTestFileName4, *panTrans);
        
    //The image size can be obtained before rendering (if required)
      TSize size;
      panImage-&gt;CurrentImageSizeL(size);
    
    //view the output image
      panImage-&gt;RenderL(KTestBSOutputFileName);

    CleanupStack::PopAndDestroy(2); //panTrans, panImage

</codeblock> <p>The main steps for using <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> are
as follows, </p> <ol id="GUID-D6872BA3-A3DF-566A-83AF-527870CBE997">
<li id="GUID-FB378114-769F-5404-BD20-8886D538191F"><p>create <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>  </p> </li>
<li id="GUID-D8A28AFC-4D37-59C4-91D9-92F4898F2302"><p>some approximate transform
information for each image pair </p> </li>
<li id="GUID-146D95D7-14DE-57CA-96DA-45959EB895A4"><p>add each images to <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>  </p> </li>
<li id="GUID-FF479A52-24E3-5D0B-A821-44127DA5B60C"><p>render the output (for
example to the file) </p> </li>
<li id="GUID-0ADBEE3F-AA60-5787-92A0-C421D4EA8731"><p>delete the objects used. </p> </li>
</ol> <p> <b>Note:</b> The following points must be noted by you: </p> <ul>
<li id="GUID-D3EB4190-4B2B-5760-8E6C-D19DAFF439DF"><p>The lens parameters
are not resolution dependant. It is enough to calibrate once for each camera
model and no need to recalibrate for each resolution. For best accuracy, use
the highest resolution possible when calibrating with a calibration tool. </p> <p>The
approximate translations in x co-ordinate and y co-ordinate ( as dx, dy) must
be compliant with the value of direction. </p> </li>
</ul> <p><b>A
camera application example</b> </p> <p>The <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> is
used in a camera application. The example is more complicated than the previous
example. In this example <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> provides the approximate
transform between the captured images. </p> <p><b>Viewfinder
image tracking </b> </p> <p>The <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> generates
panorama images. The application starts the process and then use the camera
for capturing the images. The <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> will give an indication
when to capture the high resolution images, which will later be stitched into
a panorama image. </p> <p>The <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> plays an important
role for getting the camera movement. The high level steps to use the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> in
the <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> for a camera application, are shown
below: </p> <ol id="GUID-B6357C9E-1510-53C8-856B-2C06C7A6A69C">
<li id="GUID-54C90419-08DE-5406-BBF1-37C0B59FCA26"><p>To create the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> object
and load the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> plugin, use <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-AE92A41F-388D-338C-A80E-C0B16DF3BDDC"><apiname>CVFTracker::NewL()</apiname></xref>. </p> </li>
<li id="GUID-D3E16606-ED81-5702-9F4F-9B19754D4768"><p>To create <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> object
and load the <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> plugin, use <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-39BE88C3-C617-3AF8-A13D-CEC60AE798B1"><apiname>CImagePanorama::NewL()</apiname></xref>. </p> </li>
<li id="GUID-E5C6B072-64FE-554F-BAC4-8850E15B841D"><p>To create the <xref href="GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA.dita"><apiname>CPanoramaTransform</apiname></xref> object
and set or get the values, use the <xref href="GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA.dita#GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA/GUID-ADB1D55B-CEA7-3151-B6E2-14F165F8BB9F"><apiname>CPanoramaTransform::NewL()</apiname></xref>. </p> </li>
<li id="GUID-FD68A411-E492-5492-88FD-E7A7307113F7"><p>To create and set the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref>, <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref>,
and <xref href="GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA.dita"><apiname>CPanoramaTransform</apiname></xref> functions for the Image Processor
Adaptation Plug-in objects, use <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-5E441486-3333-3B4F-81F3-3A86AE541CF8"><apiname>CVFTracker::InitialiseL()</apiname></xref> and <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-B6D24921-92B8-3FD8-B666-91C56E1E7984"><apiname>CImagePanorama::InitialiseL()</apiname></xref> respectively.</p> </li>
<li id="GUID-A605F836-474D-55D4-A326-9AC8B0F8F86B"><p>To get a translation
value from a viewfinder image, register an image by using <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-AB58BBEB-5EAE-3E2A-A94E-F59334402A2B"><apiname>CVFTracker::RegisterImageL()</apiname></xref>.
This will return translation information as a CPanoramaTransform object. </p> </li>
<li id="GUID-8E6E35D9-B20A-5BA2-987F-1A3447DEA146"><p>Check the right time
to capture the next image by using <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-945FF7AD-31E5-3C6A-AD89-F1A5FC225B9D"><apiname>CVFTracker::IsTimeToCapture()</apiname></xref>. </p> </li>
<li id="GUID-A490A649-B910-5E1C-B317-EC5627547EF7"><p>Reset the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> for
the next image, using <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita#GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352/GUID-AE707DEA-4747-3A1A-8C6F-8163F1DF0584"><apiname>CVFTracker::Reset()</apiname></xref>. </p> <p>In order
to capture many images to be stitched into a single panorama image, repeat
the steps 5, 6 and 7. </p> </li>
</ol> <fig id="GUID-7F48B2F5-D65B-52EC-8412-F3F56A5EE8E8">
<image href="GUID-470FAFE8-2246-5E91-9F01-6CC95F975E54_d0e304255_href.jpg" placement="inline"/>
</fig> <p><b>Panorama
stitching </b> </p> <p>The <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> helps to decide when
to capture each of the full resolution images using the camera. The images
can then be passed to CImagePanorama and the stitching is done. The high level
steps to do panorama stitching are listed below: </p> <ol id="GUID-763005A3-4098-534F-9CA1-E2F8654C95BD">
<li id="GUID-6866E73F-F1F7-53C8-BA64-8AF448318C53"><p>Capture the next image
using the camera, then add the image to the <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> by
using <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-66509DE8-2DBA-3FE0-8495-32E4256FA939"><apiname>CImagePanorama::AddImageL()</apiname></xref> or <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-201D0607-2D25-3B1D-B449-7A61419BB0C8"><apiname>CImagePanorama::AddFileL</apiname></xref>,
passing in the <xref href="GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA.dita"><apiname>CPanoramaTransform</apiname></xref> object obtained from
the CVFTracker. </p> </li>
<li id="GUID-BC35AEEF-206E-5830-909E-07F645C2E063"><p>When all images have
been captured you can render the stitched image to file, image buffer, CFbsBitmap
or image frame using <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita#GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4/GUID-A098A70C-050C-3592-BC37-E849A81890F2"><apiname>CImagePanorama::RenderL()</apiname></xref>. </p> </li>
</ol> <fig id="GUID-B5F7149F-1FB9-535E-9212-7C9E23B9347B">
<image href="GUID-A8C80AA1-42CF-5866-B223-FCE1AEC9DF63_d0e304305_href.jpg" placement="inline"/>
</fig> <p><b>User Interface</b> </p> <p>Provide a good user interface (UI) application
for the <xref href="GUID-4DBD1F07-42C5-3CD7-B809-A391F315E0D4.dita"><apiname>CImagePanorama</apiname></xref> is crucial. An example of UI design
is described below, which gives you a robust and easy application for generating
panorama images. </p> <p><b>How
to shoot a panorama </b> </p> <p>The steps to be followed for shooting a panorama
images: </p> <ol id="GUID-8FD3D305-BEAF-5414-BD49-5728C2504256">
<li id="GUID-92642922-D0A0-57CD-80A6-03722941E52C"><p>You need to press the
start button of the camera and need to sweep the camera towards the wanted
scene. </p> <p> <b>Note:</b> You must try not to move the mobile phone, but
only rotate it. You see in the below diagram the camera is sweep in a clockwise
direction from left-to-right. The rotation is made around the imagined axis
through mobile (axis of rotation in the image). A panorama image covers approximately
a 100 degree field of view. </p> <fig id="GUID-8562E235-6D10-5097-A888-E27EE6D4E498">
<image href="GUID-7B3578A0-7E2E-508A-A355-A39AEE0307AD_d0e304342_href.jpg" placement="inline"/>
</fig> </li>
<li id="GUID-16CA0CFB-9D17-573C-9D7B-FEDBCFF4044C"><p> <b>Application Start</b>  </p> <p>When
you launch the application the UI appears as shown in the below diagram. </p> <fig id="GUID-4A6082E2-1B7F-5A48-8FC5-7BC2786987B7">
<image href="GUID-0E55E007-913C-56DA-8BEF-7EC00FFCCE51_d0e304358_href.jpg" placement="inline"/>
</fig> <p>Here the screen area shows the viewfinder image. When you sweep
the mobile, several images are captured and then the images are stitched to
create a panorama image. </p> </li>
<li id="GUID-FE8D49DB-26CC-5546-A05D-B46045894313"><p> <b>Capture a panorama
image during tracking</b>  </p> <p>When you choose to capture a panorama image
the UI changes, which is shown in the below diagram. </p> <fig id="GUID-930C8F54-4C13-50AC-B700-9D889FFE9DC7">
<image href="GUID-9AB5481B-C321-56C9-937D-2397AA80DE8E_d0e304377_href.jpg" placement="inline"/>
</fig> <p>In the above diagram you see three different boxes named 1, 2 and
3 which represent the position of the camera. The blue box representation
changes according to the rotation of the mobile phone. </p> <p>The boxes shown
in the above diagram is for illustrative purpose, so that it can be down scaled
for viewfinder image size. The total panorama coverage area box is estimated
by the number of images for capturing and the overlapping area size. </p> <p>The
code snippets below shows the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> tracking. </p> <codeblock id="GUID-73381F9D-53D9-505A-888D-464A83B0A352" xml:space="preserve">

    _LIT(KFileOutput, "c:\\ICLExample\\viewfinder%d.mbm");
    _LIT(KFileCapturedImage, "c:\\ICLExample\\pancapture%d.jpg");
    TInt i = 0;

    TSize imageSize(1200,1000);
 CFbsBitmap* bmp = new (ELeave) CFbsBitmap;
 CleanupStack::PushL(bmp);

    // get 1st viewfinder image from camera into bmp (detail excluded)
             TSize bmpSize = bmp-&gt;SizeInPixels();

       CPanoramaTransform* panTrans = CPanoramaTransform::NewL();//create panorama transoform
       CleanupStack::PushL(panTrans);

       CVFTracker* vfTracker = CVFTracker::NewL(); //create VFTracker and load the plugin
       CleanupStack::PushL(vfTracker);
        
       vfTracker-&gt;InitializeL(bmpSize); //Create VFTracker and set size

       CImagePanorama* panImage = CImagePanorama::NewL(); //create CImagePanorama object
       CleanupStack::PushL(panImage);
        
       TDirection direction = EPanoramaDirectionRight; //assign direction
        
    // Lens parameters or internal camera characteristics should be available for the 
    // specific camera module in use. Here we use default values.
       TPanoramaLens lens;
       panImage-&gt;InitializeL(imageSize, lens, direction); //initialise size, lens, direction and create panorama engine

    // get the first captured image from the camera as a starting point - its name is given in capturedFileName
       TFileName capturedFileName;
    capturedFileName.Format(KFileCapturedImage(),i);
       panImage-&gt;AddFileL(capturedFileName, *panTrans); //add the captured image

    do 
        {
        // give the next camera viewfinder image to the tracker    (details ommitted)
           vfTracker-&gt;RegisterImageL(*bmp, *panTrans); // register viewfinder image
        
        // check if we have a good overlap with the previous image
           if(vfTracker-&gt;IsTimeToCapture(direction, KPanoramaDefaultOverlap)) 
              {
              // capture the next image from the camera (details ommitted)
              capturedFileName.Format(KFileCapturedImage(),i);
            
                 panImage-&gt;AddFileL(capturedFileName, *panTrans); //add the captured image
                 vfTracker-&gt;Reset(); //reset the VFTracker object
              }         
        if ( err != KErrNone )  // some termination condition usually a signal from user
            {
            // no more viewfinder images
            break;
            }
        }
    while (1);    
    panImage-&gt;RenderL(KTestVFTOutputFileName); // render the stitched image
    CleanupStack::PopAndDestroy(4,bmp); //panTrans, vfTracker, panImage, bmp
</codeblock> <p>The <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> is passed each viewfinder
images which it checks and determines whether it is right time to capture
the next image. In return it provides translation information <codeph>CPanoramaTransform::GetTranslation()</codeph> which
indicates the shift of the current viewfinder image. </p> <p>The extracted
information is used to draw the blue rectangle on the screen. If it is time
to capture, then it triggers the capturing function and restarts the <xref href="GUID-0D12EA24-3BF5-3BEA-B0EA-CEB89D49D352.dita"><apiname>CVFTracker</apiname></xref> again
for next image. </p> <p> <b>Note:</b> The box representation is used in the
UI, to help you to take better panorama images. In addition a vibration effect
can be used to provide additional feedback on when to capture an image. For
example, when you sweep the mobile phone, it is in tracking mode so it vibrates.
When the mobile phone is ready to capture, the vibration stops to let you
know that it must be static for capturing an accurate second image. Then when
it vibrates again, you must rotate the mobile and until it stop. </p> </li>
<li id="GUID-C7848E42-74B4-56D2-BB7B-2F20A4D30D32"><p> <b>User interface updating
details </b>  </p> <p>The UI design detail is shown in step by step process.
They are as follows: </p> <ul>
<li id="GUID-99D23225-ECF9-5A34-ADAA-4E0A2326D768"><p>The total panorama coverage
area is divided into four different image areas: </p> <fig id="GUID-0808E657-6313-510C-9EB6-F4D49722229B">
<image href="GUID-023D30F0-C1E8-5E09-92AD-C5A7963DCF70_d0e304438_href.jpg" placement="inline"/>
</fig> </li>
<li id="GUID-D06A8B59-81EE-5420-A3AE-FB036B7CE3F4"><p>When you choose to capture
a panorama image the following steps are performed. The first image is captured
at position 0. The UI looks as follows: </p> <fig id="GUID-A17F50EC-3241-56CA-B96A-59515EAF161B">
<image href="GUID-C2D99C88-09C7-55FA-AF95-3F689BA27484_d0e304448_href.jpg" placement="inline"/>
</fig> </li>
<li id="GUID-BF4A2D67-EF8D-5F72-B2C2-9DC79E319023"><p>When you rotate the
mobile phone clockwise, the blue box moves to the right using the translation
information from <xref href="GUID-27BD164A-9283-3BE0-A0BF-A475539D86EA.dita"><apiname>CPanoramaTransform</apiname></xref>. At the same time the
vibrator is set on to give direct feedback for the tracking process. When
the blue box and the grey box (which represent the position to capture the
next image) coincide, the blue box turns into a filled blue box and the vibrator
stops. You then known that the next image is captured. At this moment the
camera must be steady. </p> <p>After second image is captured the blue box
is moving again and vibrator is set-on. The UI looks as follows: </p> <fig id="GUID-C6E583BB-EE47-52EE-BBFB-D7EE37156C12">
<image href="GUID-B985B750-9B42-55ED-B7E4-41B06B44C365_d0e304465_href.jpg" placement="inline"/>
</fig> <p>Again, you rotate the mobile clockwise until the two boxes coincide
and vibrator stops; third image then captured. After this, the UI looks as
follows: </p> <fig id="GUID-FD9D81DA-E675-5C9C-BA6E-4E7DCE6F46D9">
<image href="GUID-9E12593C-38EF-5052-A2E8-0AB25EEFF4D0_d0e304473_href.jpg" placement="inline"/>
</fig> <p>You rotate the mobile phone until the boxes coincide and the fourth
(last) image is captured. </p> <p> <b>Note:</b> If the mobile phone rotation
deviates from chosen (clockwise) direction or translates up and down, the
blue box indicates this, and you must correct the mobile phone for the wrong
movement. </p> <p>At this point the stitched image can be saved or you can
reset the camera, to create another panorama image: </p> <fig id="GUID-1A527BEA-0C50-5910-9525-75336C02B2C9">
<image href="GUID-8E2303E9-DB60-5F38-A4D4-8BF8F7A1EF9F_d0e304490_href.jpg" placement="inline"/>
</fig> </li>
</ul> </li>
</ol> <p><b>Camera
calibration </b> </p> <p>In order to produce good panorama images, the internal
characteristics of the camera is calibrated by the <xref href="GUID-E361A378-76EB-36C9-A949-A5D31D4D1C4C.dita"><apiname>TPanoramaLens()</apiname></xref>.
The lens parameter such as the distance, the focal length, the principal point,
the skew, the width and the height are called the intrinsic parameters. </p> <p>The
camera module supplier should be able to provide this information or there
are a number of tools to get the camera parameters. A free tool that can be
used is the calibration functions in <xref href="http://en.wikipedia.org/wiki/Opencv" scope="external">OpenCV</xref>. Typically these tools need an input of images
of a special reference pattern, for example a checker board like grid, photographed
from many directions. From that the tools automatically generate all the desired
lens parameters. </p> </section>
</conbody></concept>