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