EstimateRPCSensorModelExample.cxx 4.93 KB
Newer Older
1
/*
Julien Michel's avatar
Julien Michel committed
2
 * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
20 21 22 23 24 25 26 27 28


// \index{otb::GCPsToRPCSensorModelImageFilter}
// \index{otb::GCPsToRPCSensorModelImageFilter!header}
//
//
// The following example illustrates the application of estimation
// of a sensor model to an image (limited to a RPC sensor model for now).

Julien Malik's avatar
Julien Malik committed
29
// The \doxygen{otb}{GCPsToRPCSensorModelImageFilter} estimates a RPC
OTB Bot's avatar
OTB Bot committed
30 31
// sensor model from a list of user defined GCPs. Internally, it uses
// an ossimRpcSolver, which performs the estimation using the well
32 33 34 35 36
// known least-square method.

// Let's look at the minimal code required to use this
// algorithm. First, the following header defining the
// \doxygen{otb}{GCPsToRPCSensorModelImageFilter} class must be
OTB Bot's avatar
OTB Bot committed
37
// included.
38

39
#include <ios>
40 41 42 43
#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbGCPsToRPCSensorModelImageFilter.h"

OTB Bot's avatar
OTB Bot committed
44
int main(int argc, char* argv[])
45
{
OTB Bot's avatar
OTB Bot committed
46
  if (argc < 3)
47 48
  {
    std::cerr << "Usage: " << argv[0] << " infname outfname a1x a1y b1x b1y b1z ... aNx aNy bNx bNy bNz" << std::endl;
49
    return EXIT_FAILURE;
50
  }
OTB Bot's avatar
OTB Bot committed
51
  else if ((argc - 3) % 5 != 0)
52
  {
OTB Bot's avatar
OTB Bot committed
53
    std::cerr << "Inconsistent GCPs description!" << std::endl;
54
    return EXIT_FAILURE;
55
  }
56

57 58
  const char* infname  = argv[1];
  const char* outfname = argv[2];
59 60 61 62

  //  We declare the image type based on a particular pixel type and
  //  dimension. In this case the \code{float} type is used for the pixels.

63 64
  using ImageType  = otb::Image<float, 2>;
  using ReaderType = otb::ImageFileReader<ImageType>;
OTB Bot's avatar
OTB Bot committed
65

66
  using GCPsToSensorModelFilterType = otb::GCPsToRPCSensorModelImageFilter<ImageType>;
OTB Bot's avatar
OTB Bot committed
67

68 69
  using Point2DType = GCPsToSensorModelFilterType::Point2DType;
  using Point3DType = GCPsToSensorModelFilterType::Point3DType;
70 71 72 73 74 75 76

  // We instantiate reader and writer types
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(infname);

  //  The \doxygen{otb}{GCPsToRPCSensorModelImageFilter} is instantiated.

77
  GCPsToSensorModelFilterType::Pointer rpcEstimator = GCPsToSensorModelFilterType::New();
78
  rpcEstimator->SetInput(reader->GetOutput());
OTB Bot's avatar
OTB Bot committed
79

80
  // We retrieve the command line parameters and put them in the
OTB Bot's avatar
OTB Bot committed
81
  // correct variables. Firstly, We determine the number of GCPs
82 83 84
  // set from the command line parameters and they are stored in:
  // \begin{itemize}
  // \item \doxygen{otb}{Point3DType} : Store the sensor point (3D ground point)
85
  // \item \doxygen{otb}{Point2DType} : Pixel associated in the image (2D physical coordinates)
86 87 88 89 90 91

  // Here we do not use DEM or MeanElevation. It is also possible to give a 2D
  // ground point and use the DEM or MeanElevation to get
  // the corresponding elevation.
  // \end{itemize}

OTB Bot's avatar
OTB Bot committed
92 93 94 95 96
  unsigned int nbGCPs = (argc - 3) / 5;

  std::cout << "Receiving " << nbGCPs << " from command line." << std::endl;

  for (unsigned int gcpId = 0; gcpId < nbGCPs; ++gcpId)
97
  {
98
    Point2DType sensorPoint;
OTB Bot's avatar
OTB Bot committed
99 100
    sensorPoint[0] = atof(argv[3 + gcpId * 5]);
    sensorPoint[1] = atof(argv[4 + gcpId * 5]);
101 102

    Point3DType geoPoint;
OTB Bot's avatar
OTB Bot committed
103 104 105 106
    geoPoint[0] = atof(argv[5 + 5 * gcpId]);
    geoPoint[1] = atof(argv[6 + 5 * gcpId]);
    geoPoint[2] = atof(argv[7 + 5 * gcpId]);

107
    std::cout << "Adding GCP sensor: " << sensorPoint << " <-> geo: " << geoPoint << std::endl;
108

OTB Bot's avatar
OTB Bot committed
109
    rpcEstimator->AddGCP(sensorPoint, geoPoint);
110
  }
111

OTB Bot's avatar
OTB Bot committed
112
  // Note that the \doxygen{otb}{GCPsToRPCSensorModelImageFilter} needs
113
  // at least 20 GCPs to estimate a proper RPC sensor model,
OTB Bot's avatar
OTB Bot committed
114
  // although no warning will be reported to the user if
115
  // the number of GCPs is lower than 20.
116
  // Actual estimation of the sensor model takes place in the
OTB Bot's avatar
OTB Bot committed
117
  // \code{GenerateOutputInformation()} method.
118 119

  rpcEstimator->GetOutput()->UpdateOutputInformation();
OTB Bot's avatar
OTB Bot committed
120 121 122 123

  // The result of the RPC model estimation and the residual ground
  // error is then save in a txt file. Note that This filter does
  // not modify the image buffer, but only the metadata.
124 125 126 127 128

  std::ofstream ofs;
  ofs.open(outfname);

  // Set floatfield to format properly
129
  ofs.setf(std::ios::fixed, std::ios::floatfield);
130 131
  ofs.precision(10);

132 133
  ofs << (ImageType::Pointer)rpcEstimator->GetOutput() << std::endl;
  ofs << "Residual ground error: " << rpcEstimator->GetRMSGroundError() << std::endl;
134 135
  ofs.close();

136 137
  // The output image can be now given to the \doxygen{otb}{orthorectificationFilter}.
  // Note that this filter allows also to import GCPs from the image
OTB Bot's avatar
OTB Bot committed
138
  // metadata, if any.
139 140 141

  return EXIT_SUCCESS;
}