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      */
77     status_t mapRawToCorrected(int32_t *coordPairs, int coordCount);
78 
79     /**
80      * Transform from distorted (original) to corrected (warped) coordinates.
81      * Coordinates are transformed in-place
82      *
83      *   rects: A pointer to an array of consecutive (x,y, w, h) rectangles
84      *   rectCount: Number of rectangles to transform
85      */
86     status_t mapRawRectToCorrected(int32_t *rects, int rectCount);
87 
88     /**
89      * Transform from corrected (warped) to distorted (original) coordinates.
90      * Coordinates are transformed in-place
91      *
92      *   coordPairs: A pointer to an array of consecutive (x,y) points
93      *   coordCount: Number of (x,y) pairs to transform
94      */
95     template<typename T>
96     status_t mapCorrectedToRaw(T* coordPairs, int coordCount) const;
97 
98     /**
99      * Transform from corrected (warped) to distorted (original) coordinates.
100      * Coordinates are transformed in-place
101      *
102      *   rects: A pointer to an array of consecutive (x,y, w, h) rectangles
103      *   rectCount: Number of rectangles to transform
104      */
105     status_t mapCorrectedRectToRaw(int32_t *rects, int rectCount) const;
106 
107     struct GridQuad {
108         // Source grid quad, or null
109         const GridQuad *src;
110         // x,y coordinates of corners, in
111         // clockwise order
112         std::array<float, 8> coords;
113     };
114 
115     // Find which grid quad encloses the point; returns null if none do
116     static const GridQuad* findEnclosingQuad(
117             const int32_t pt[2], const std::vector<GridQuad>& grid);
118 
119     // Calculate 'horizontal' interpolation coordinate for the point and the quad
120     // Assumes the point P is within the quad Q.
121     // Given quad with points P1-P4, and edges E12-E41, and considering the edge segments as
122     // functions of U: E12(u), where E12(0) = P1 and E12(1) = P2, then we want to find a u
123     // such that the edge E12(u) -> E43(u) contains point P.
124     // This can be determined by checking if the cross product of vector [E12(u)-E43(u)] and
125     // vector [E12(u)-P] is zero. Solving the equation
126     // [E12(u)-E43(u)] x [E12(u)-P] = 0 gives a quadratic equation in u; the solution in the range
127     // 0 to 1 is the one chosen.
128     // If calculateU is true, then an interpolation coordinate for edges E12 and E43 is found;
129     // if it is false, then an interpolation coordinate for edges E14 and E23 is found.
130     static float calculateUorV(const int32_t pt[2], const GridQuad& quad, bool calculateU);
131 
132   private:
133     mutable std::mutex mMutex;
134 
135     // Number of quads in each dimension of the mapping grids
136     constexpr static size_t kGridSize = 15;
137     // Margin to expand the grid by to ensure it doesn't clip the domain
138     constexpr static float kGridMargin = 0.05f;
139     // Fuzziness for float inequality tests
140     constexpr static float kFloatFuzz = 1e-4;
141 
142     // Metadata key lists to correct
143 
144     // Both capture request and result
145     static const std::array<uint32_t, 3> kMeteringRegionsToCorrect;
146 
147     // Only capture request
148     static const std::array<uint32_t, 1> kRequestRectsToCorrect;
149 
150     // Only capture result
151     static const std::array<uint32_t, 1> kResultRectsToCorrect;
152 
153     // Only for capture results
154     static const std::array<uint32_t, 2> kResultPointsToCorrect;
155 
156     // Utility to create reverse mapping grids
157     status_t buildGrids();
158 
159 
160     bool mValidMapping;
161     bool mValidGrids;
162 
163     // intrisic parameters, in pixels
164     float mFx, mFy, mCx, mCy, mS;
165     // pre-calculated inverses for speed
166     float mInvFx, mInvFy;
167     // radial/tangential distortion parameters
168     float mK[5];
169 
170     // pre-correction active array dimensions
171     int mArrayWidth, mArrayHeight;
172     // active array dimensions
173     int mActiveWidth, mActiveHeight;
174 
175     std::vector<GridQuad> mCorrectedGrid;
176     std::vector<GridQuad> mDistortedGrid;
177 
178 }; // class DistortionMapper
179 
180 } // namespace camera3
181 
182 } // namespace android
183 
184 #endif
185