Skip to content

Commit 64f6a47

Browse files
committed
add calib3d module
1 parent 24c3159 commit 64f6a47

19 files changed

+1277
-159
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
## 0.4.1
1+
## 0.5.0
22

33
* add `asyncarray`
4+
* add `calib3d` module
45

56
## 0.4.0
67

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ prebuilt binaries.
3434
| video | :white_check_mark: | :white_check_mark: | Video module |
3535
| videoio | :white_check_mark: | :white_check_mark: | VideoIO module |
3636
| asyncarray | :white_check_mark: | :white_check_mark: | AsyncArray module |
37-
| calib3d | :x: | :x: | Calib3D module |
37+
| calib3d | :white_check_mark: | :white_check_mark: | Calib3D module |
3838
| dnn | :x: | :x: | DNN module |
3939
| photo | :white_check_mark: | :white_check_mark: | Photo module |
4040
| cuda | :x: | :x: | CUDA module |

lib/src/calib3d/calib3d.dart

Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
library cv;
2+
3+
import 'dart:ffi' as ffi;
4+
5+
import 'package:ffi/ffi.dart';
6+
7+
import '../core/contours.dart';
8+
import '../core/point.dart';
9+
import '../core/rect.dart';
10+
import '../constants.g.dart';
11+
import '../core/extensions.dart';
12+
import '../core/base.dart';
13+
import '../core/core.dart';
14+
import '../core/mat.dart';
15+
import '../opencv.g.dart' as cvg;
16+
17+
final _bindings = cvg.CvNative(loadNativeLibrary());
18+
19+
class Fisheye {
20+
/// FisheyeUndistortImage transforms an image to compensate for fisheye lens distortion
21+
/// https://docs.opencv.org/3.4/db/d58/group__calib3d__fisheye.html#ga167df4b00a6fd55287ba829fbf9913b9
22+
static Mat undistortImage(
23+
InputArray distorted,
24+
InputArray K,
25+
InputArray D, {
26+
OutputArray? undistorted,
27+
InputArray? Knew,
28+
Size new_size = (0, 0),
29+
}) {
30+
return using<Mat>((arena) {
31+
Knew ??= Mat.empty();
32+
undistorted ??= Mat.empty();
33+
new_size = (0, 0);
34+
_bindings.Fisheye_UndistortImageWithParams(
35+
distorted.ptr,
36+
undistorted!.ptr,
37+
K.ptr,
38+
D.ptr,
39+
Knew!.ptr,
40+
new_size.toSize(arena).ref,
41+
);
42+
return undistorted!;
43+
});
44+
}
45+
46+
/// FisheyeUndistortPoints transforms points to compensate for fisheye lens distortion
47+
///
48+
/// For further details, please see:
49+
/// https://docs.opencv.org/master/db/d58/group__calib3d__fisheye.html#gab738cdf90ceee97b2b52b0d0e7511541
50+
static Mat undistortPoints(
51+
InputArray distorted,
52+
InputArray K,
53+
InputArray D, {
54+
OutputArray? undistorted,
55+
InputArray? R,
56+
InputArray? P,
57+
cvg.TermCriteria? criteria,
58+
}) {
59+
R ??= Mat.empty();
60+
P ??= Mat.empty();
61+
undistorted ??= Mat.empty();
62+
criteria = termCriteriaNew(TERM_MAX_ITER + TERM_EPS, 10, 1e-8);
63+
_bindings.Fisheye_UndistortPoints(distorted.ptr, undistorted.ptr, K.ptr, D.ptr, R.ptr, P.ptr);
64+
return undistorted;
65+
}
66+
67+
/// EstimateNewCameraMatrixForUndistortRectify estimates new camera matrix for undistortion or rectification.
68+
///
69+
/// For further details, please see:
70+
/// https://docs.opencv.org/master/db/d58/group__calib3d__fisheye.html#ga384940fdf04c03e362e94b6eb9b673c9
71+
static Mat estimateNewCameraMatrixForUndistortRectify(
72+
InputArray K,
73+
InputArray D,
74+
Size image_size,
75+
InputArray R, {
76+
OutputArray? P,
77+
double balance = 0.0,
78+
Size new_size = (0, 0),
79+
double fov_scale = 1.0,
80+
}) {
81+
return using<Mat>((arena) {
82+
P ??= Mat.empty();
83+
_bindings.Fisheye_EstimateNewCameraMatrixForUndistortRectify(
84+
K.ptr,
85+
D.ptr,
86+
image_size.toSize(arena).ref,
87+
R.ptr,
88+
P!.ptr,
89+
balance,
90+
new_size.toSize(arena).ref,
91+
fov_scale,
92+
);
93+
return P!;
94+
});
95+
}
96+
}
97+
98+
/// InitUndistortRectifyMap computes the joint undistortion and rectification transformation and represents the result in the form of maps for remap
99+
///
100+
/// For further details, please see:
101+
/// https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga7dfb72c9cf9780a347fbe3d1c47e5d5a
102+
(Mat map1, Mat map2) initUndistortRectifyMap(
103+
InputArray cameraMatrix,
104+
InputArray distCoeffs,
105+
InputArray R,
106+
InputArray newCameraMatrix,
107+
Size size,
108+
int m1type, {
109+
OutputArray? map1,
110+
OutputArray? map2,
111+
}) {
112+
return using<(Mat, Mat)>((arena) {
113+
map1 ??= Mat.empty();
114+
map2 ??= Mat.empty();
115+
_bindings.InitUndistortRectifyMap(
116+
cameraMatrix.ptr,
117+
distCoeffs.ptr,
118+
R.ptr,
119+
newCameraMatrix.ptr,
120+
size.toSize(arena).ref,
121+
m1type,
122+
map1!.ptr,
123+
map2!.ptr,
124+
);
125+
return (map1!, map2!);
126+
});
127+
}
128+
129+
/// GetOptimalNewCameraMatrixWithParams computes and returns the optimal new camera matrix based on the free scaling parameter.
130+
///
131+
/// For further details, please see:
132+
/// https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga7a6c4e032c97f03ba747966e6ad862b1
133+
(Mat, Rect validPixROI) getOptimalNewCameraMatrix(
134+
InputArray cameraMatrix,
135+
InputArray distCoeffs,
136+
Size imageSize,
137+
double alpha, {
138+
Size newImgSize = (0, 0),
139+
bool centerPrincipalPoint = false,
140+
}) {
141+
return using<(Mat, Rect)>((arena) {
142+
final validPixROI = arena<cvg.Rect>();
143+
final _p = _bindings.GetOptimalNewCameraMatrixWithParams(
144+
cameraMatrix.ptr,
145+
distCoeffs.ptr,
146+
imageSize.toSize(arena).ref,
147+
alpha,
148+
newImgSize.toSize(arena).ref,
149+
validPixROI,
150+
centerPrincipalPoint,
151+
);
152+
return (Mat.fromCMat(_p), Rect.fromNative(validPixROI.ref));
153+
});
154+
}
155+
156+
// CalibrateCamera finds the camera intrinsic and extrinsic parameters from several views of a calibration pattern.
157+
//
158+
// For further details, please see:
159+
// https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga3207604e4b1a1758aa66acb6ed5aa65d
160+
(double, Mat, Mat, Mat, Mat) calibrateCamera(
161+
Contours3f objectPoints,
162+
Contours2f imagePoints,
163+
Size imageSize,
164+
InputOutputArray cameraMatrix,
165+
InputOutputArray distCoeffs, {
166+
Mat? rvecs,
167+
Mat? tvecs,
168+
int flags = 0,
169+
cvg.TermCriteria? criteria,
170+
}) {
171+
return using<(double, Mat, Mat, Mat, Mat)>((arena) {
172+
rvecs ??= Mat.empty();
173+
tvecs ??= Mat.empty();
174+
criteria ??= termCriteriaNew(TERM_COUNT + TERM_EPS, 30, 1e-4);
175+
final rmsErr = _bindings.CalibrateCamera(
176+
objectPoints.ptr,
177+
imagePoints.ptr,
178+
imageSize.toSize(arena).ref,
179+
cameraMatrix.ptr,
180+
distCoeffs.ptr,
181+
rvecs!.ptr,
182+
tvecs!.ptr,
183+
flags,
184+
criteria!,
185+
);
186+
return (rmsErr, cameraMatrix, distCoeffs, rvecs!, tvecs!);
187+
});
188+
}
189+
190+
// Transforms an image to compensate for lens distortion.
191+
//
192+
// The function transforms an image to compensate radial and tangential lens distortion.
193+
//
194+
// The function is simply a combination of initUndistortRectifyMap (with unity R ) and remap (with bilinear interpolation). See the former function for details of the transformation being performed.
195+
//
196+
// Those pixels in the destination image, for which there is no correspondent pixels in the source image, are filled with zeros (black color).
197+
//
198+
// A particular subset of the source image that will be visible in the corrected image can be regulated by newCameraMatrix. You can use getOptimalNewCameraMatrix to compute the appropriate newCameraMatrix depending on your requirements.
199+
//
200+
// The camera matrix and the distortion parameters can be determined using calibrateCamera. If the resolution of images is different from the resolution used at the calibration stage, fx,fy,cx and cy need to be scaled accordingly, while the distortion coefficients remain the same.
201+
Mat undistort(
202+
InputArray src,
203+
InputArray cameraMatrix,
204+
InputArray distCoeffs, {
205+
OutputArray? dst,
206+
InputArray? newCameraMatrix,
207+
}) {
208+
dst ??= Mat.empty();
209+
newCameraMatrix ??= Mat.empty();
210+
_bindings.Undistort(src.ptr, dst.ptr, cameraMatrix.ptr, distCoeffs.ptr, newCameraMatrix.ptr);
211+
return dst;
212+
}
213+
214+
// UndistortPoints transforms points to compensate for lens distortion
215+
//
216+
// For further details, please see:
217+
// https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga55c716492470bfe86b0ee9bf3a1f0f7e
218+
Mat undistortPoints(
219+
InputArray src,
220+
InputArray cameraMatrix,
221+
InputArray distCoeffs, {
222+
OutputArray? dst,
223+
InputArray? R,
224+
InputArray? P,
225+
}) {
226+
R ??= Mat.empty();
227+
P ??= Mat.empty();
228+
dst ??= Mat.empty();
229+
_bindings.UndistortPoints(src.ptr, dst.ptr, cameraMatrix.ptr, distCoeffs.ptr, R.ptr, P.ptr);
230+
return dst;
231+
}
232+
233+
// FindChessboardCorners finds the positions of internal corners of the chessboard.
234+
//
235+
// For further details, please see:
236+
// https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga93efa9b0aa890de240ca32b11253dd4a
237+
(bool, Mat corners) findChessboardCorners(
238+
InputArray image,
239+
Size patternSize, {
240+
OutputArray? corners,
241+
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE,
242+
}) {
243+
return using<(bool, Mat)>((arena) {
244+
corners ??= Mat.empty();
245+
final r = _bindings.FindChessboardCorners(
246+
image.ptr,
247+
patternSize.toSize(arena).ref,
248+
corners!.ptr,
249+
flags,
250+
);
251+
return (r, corners!);
252+
});
253+
}
254+
255+
// Finds the positions of internal corners of the chessboard using a sector based approach.
256+
// https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html#gadc5bcb05cb21cf1e50963df26986d7c9
257+
(bool, Mat corners, Mat meta) findChessboardCornersSB(
258+
InputArray image,
259+
Size patternSize,
260+
int flags, {
261+
OutputArray? corners,
262+
OutputArray? meta,
263+
}) {
264+
return using<(bool, Mat, Mat)>((arena) {
265+
corners ??= Mat.empty();
266+
meta ??= Mat.empty();
267+
final b = _bindings.FindChessboardCornersSBWithMeta(
268+
image.ptr,
269+
patternSize.toSize(arena).ref,
270+
corners!.ptr,
271+
flags,
272+
meta!.ptr,
273+
);
274+
return (b, corners!, meta!);
275+
});
276+
}
277+
278+
// DrawChessboardCorners renders the detected chessboard corners.
279+
//
280+
// For further details, please see:
281+
// https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga6a10b0bb120c4907e5eabbcd22319022
282+
Mat drawChessboardCorners(
283+
InputOutputArray image,
284+
Size patternSize,
285+
InputArray corners,
286+
bool patternWasFound,
287+
) {
288+
return using<Mat>((arena) {
289+
_bindings.DrawChessboardCorners(image.ptr, patternSize.toSize(arena).ref, corners.ptr, patternWasFound);
290+
return image;
291+
});
292+
}
293+
294+
// EstimateAffinePartial2D computes an optimal limited affine transformation
295+
// with 4 degrees of freedom between two 2D point sets.
296+
//
297+
// For further details, please see:
298+
// https://docs.opencv.org/master/d9/d0c/group__calib3d.html#gad767faff73e9cbd8b9d92b955b50062d
299+
(Mat, Mat inliers) estimateAffinePartial2D(
300+
List<Point2f> from,
301+
List<Point2f> to, {
302+
int method = RANSAC,
303+
double ransacReprojThreshold = 3,
304+
int maxIters = 2000,
305+
double confidence = 0.99,
306+
int refineIters = 10,
307+
OutputArray? inliers,
308+
}) {
309+
inliers ??= Mat.empty();
310+
final _from = from.toNativeVecotr();
311+
final _to = to.toNativeVecotr();
312+
final p = _bindings.EstimateAffinePartial2DWithParams(
313+
_from,
314+
_to,
315+
inliers.ptr,
316+
method,
317+
ransacReprojThreshold,
318+
maxIters,
319+
confidence,
320+
refineIters,
321+
);
322+
_bindings.Point2fVector_Close(_from);
323+
_bindings.Point2fVector_Close(_to);
324+
return (Mat.fromCMat(p), inliers);
325+
}
326+
327+
// EstimateAffine2D Computes an optimal affine transformation between two 2D point sets.
328+
//
329+
// For further details, please see:
330+
// https://docs.opencv.org/4.0.0/d9/d0c/group__calib3d.html#ga27865b1d26bac9ce91efaee83e94d4dd
331+
(Mat, Mat inliers) estimateAffine2D(
332+
List<Point2f> from,
333+
List<Point2f> to, {
334+
int method = RANSAC,
335+
double ransacReprojThreshold = 3,
336+
int maxIters = 2000,
337+
double confidence = 0.99,
338+
int refineIters = 10,
339+
OutputArray? inliers,
340+
}) {
341+
inliers ??= Mat.empty();
342+
final _from = from.toNativeVecotr();
343+
final _to = to.toNativeVecotr();
344+
final p = _bindings.EstimateAffine2DWithParams(
345+
_from,
346+
_to,
347+
inliers.ptr,
348+
method,
349+
ransacReprojThreshold,
350+
maxIters,
351+
confidence,
352+
refineIters,
353+
);
354+
_bindings.Point2fVector_Close(_from);
355+
_bindings.Point2fVector_Close(_to);
356+
return (Mat.fromCMat(p), inliers);
357+
}

0 commit comments

Comments
 (0)