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