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