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