Home | History | Annotate | Download | only in device3
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ANDROID_SERVERS_DISTORTIONMAPPER_H
     18 #define ANDROID_SERVERS_DISTORTIONMAPPER_H
     19 
     20 #include <utils/Errors.h>
     21 #include <array>
     22 #include <mutex>
     23 
     24 #include "camera/CameraMetadata.h"
     25 
     26 namespace android {
     27 
     28 namespace camera3 {
     29 
     30 /**
     31  * Utilities to transform between raw (distorted) and warped (corrected) coordinate systems
     32  * for cameras that support geometric distortion
     33  */
     34 class DistortionMapper {
     35   public:
     36     DistortionMapper();
     37 
     38     /**
     39      * Check whether distortion correction is supported by the camera HAL
     40      */
     41     static bool isDistortionSupported(const CameraMetadata &deviceInfo);
     42 
     43     /**
     44      * Update static lens calibration info from camera characteristics
     45      */
     46     status_t setupStaticInfo(const CameraMetadata &deviceInfo);
     47 
     48     /**
     49      * Return whether distortion correction can be applied currently
     50      */
     51     bool calibrationValid() const;
     52 
     53     /**
     54      * Correct capture request if distortion correction is enabled
     55      */
     56     status_t correctCaptureRequest(CameraMetadata *request);
     57 
     58     /**
     59      * Correct capture result if distortion correction is enabled
     60      */
     61     status_t correctCaptureResult(CameraMetadata *request);
     62 
     63 
     64   public: // Visible for testing. Not guarded by mutex; do not use concurrently
     65     /**
     66      * Update lens calibration from capture results or equivalent
     67      */
     68     status_t updateCalibration(const CameraMetadata &result);
     69 
     70     /**
     71      * Transform from distorted (original) to corrected (warped) coordinates.
     72      * Coordinates are transformed in-place
     73      *
     74      *   coordPairs: A pointer to an array of consecutive (x,y) points
     75      *   coordCount: Number of (x,y) pairs to transform
     76      *   clamp: Whether to clamp the result to the bounds of the active array
     77      *   simple: Whether to do complex correction or just a simple linear map
     78      */
     79     status_t mapRawToCorrected(int32_t *coordPairs, int coordCount, bool clamp,
     80             bool simple = true);
     81 
     82     /**
     83      * Transform from distorted (original) to corrected (warped) coordinates.
     84      * Coordinates are transformed in-place
     85      *
     86      *   rects: A pointer to an array of consecutive (x,y, w, h) rectangles
     87      *   rectCount: Number of rectangles to transform
     88      *   clamp: Whether to clamp the result to the bounds of the active array
     89      *   simple: Whether to do complex correction or just a simple linear map
     90      */
     91     status_t mapRawRectToCorrected(int32_t *rects, int rectCount, bool clamp,
     92             bool simple = true);
     93 
     94     /**
     95      * Transform from corrected (warped) to distorted (original) coordinates.
     96      * Coordinates are transformed in-place
     97      *
     98      *   coordPairs: A pointer to an array of consecutive (x,y) points
     99      *   coordCount: Number of (x,y) pairs to transform
    100      *   clamp: Whether to clamp the result to the bounds of the precorrection active array
    101      *   simple: Whether to do complex correction or just a simple linear map
    102      */
    103     status_t mapCorrectedToRaw(int32_t* coordPairs, int coordCount, bool clamp,
    104             bool simple = true) const;
    105 
    106     /**
    107      * Transform from corrected (warped) to distorted (original) coordinates.
    108      * Coordinates are transformed in-place
    109      *
    110      *   rects: A pointer to an array of consecutive (x,y, w, h) rectangles
    111      *   rectCount: Number of rectangles to transform
    112      *   clamp: Whether to clamp the result to the bounds of the precorrection active array
    113      *   simple: Whether to do complex correction or just a simple linear map
    114      */
    115     status_t mapCorrectedRectToRaw(int32_t *rects, int rectCount, bool clamp,
    116             bool simple = true) const;
    117 
    118     struct GridQuad {
    119         // Source grid quad, or null
    120         const GridQuad *src;
    121         // x,y coordinates of corners, in
    122         // clockwise order
    123         std::array<float, 8> coords;
    124     };
    125 
    126     // Find which grid quad encloses the point; returns null if none do
    127     static const GridQuad* findEnclosingQuad(
    128             const int32_t pt[2], const std::vector<GridQuad>& grid);
    129 
    130     // Calculate 'horizontal' interpolation coordinate for the point and the quad
    131     // Assumes the point P is within the quad Q.
    132     // Given quad with points P1-P4, and edges E12-E41, and considering the edge segments as
    133     // functions of U: E12(u), where E12(0) = P1 and E12(1) = P2, then we want to find a u
    134     // such that the edge E12(u) -> E43(u) contains point P.
    135     // This can be determined by checking if the cross product of vector [E12(u)-E43(u)] and
    136     // vector [E12(u)-P] is zero. Solving the equation
    137     // [E12(u)-E43(u)] x [E12(u)-P] = 0 gives a quadratic equation in u; the solution in the range
    138     // 0 to 1 is the one chosen.
    139     // If calculateU is true, then an interpolation coordinate for edges E12 and E43 is found;
    140     // if it is false, then an interpolation coordinate for edges E14 and E23 is found.
    141     static float calculateUorV(const int32_t pt[2], const GridQuad& quad, bool calculateU);
    142 
    143   private:
    144     mutable std::mutex mMutex;
    145 
    146     // Number of quads in each dimension of the mapping grids
    147     constexpr static size_t kGridSize = 15;
    148     // Margin to expand the grid by to ensure it doesn't clip the domain
    149     constexpr static float kGridMargin = 0.05f;
    150     // Fuzziness for float inequality tests
    151     constexpr static float kFloatFuzz = 1e-4;
    152 
    153     // Metadata key lists to correct
    154 
    155     // Both capture request and result
    156     static const std::array<uint32_t, 3> kMeteringRegionsToCorrect;
    157 
    158     // Only capture request
    159     static const std::array<uint32_t, 1> kRequestRectsToCorrect;
    160 
    161     // Only capture result
    162     static const std::array<uint32_t, 1> kResultRectsToCorrect;
    163 
    164     // Only for capture results; don't clamp
    165     static const std::array<uint32_t, 2> kResultPointsToCorrectNoClamp;
    166 
    167     // Single implementation for various mapCorrectedToRaw methods
    168     template<typename T>
    169     status_t mapCorrectedToRawImpl(T* coordPairs, int coordCount, bool clamp, bool simple) const;
    170 
    171     // Simple linear interpolation option
    172     template<typename T>
    173     status_t mapCorrectedToRawImplSimple(T* coordPairs, int coordCount, bool clamp) const;
    174 
    175     status_t mapRawToCorrectedSimple(int32_t *coordPairs, int coordCount, bool clamp) const;
    176 
    177     // Utility to create reverse mapping grids
    178     status_t buildGrids();
    179 
    180 
    181     bool mValidMapping;
    182     bool mValidGrids;
    183 
    184     // intrisic parameters, in pixels
    185     float mFx, mFy, mCx, mCy, mS;
    186     // pre-calculated inverses for speed
    187     float mInvFx, mInvFy;
    188     // radial/tangential distortion parameters
    189     float mK[5];
    190 
    191     // pre-correction active array dimensions
    192     float mArrayWidth, mArrayHeight;
    193     // active array dimensions
    194     float mActiveWidth, mActiveHeight;
    195     // corner offsets between pre-correction and active arrays
    196     float mArrayDiffX, mArrayDiffY;
    197 
    198     std::vector<GridQuad> mCorrectedGrid;
    199     std::vector<GridQuad> mDistortedGrid;
    200 
    201 }; // class DistortionMapper
    202 
    203 } // namespace camera3
    204 
    205 } // namespace android
    206 
    207 #endif
    208