Skip to content

Commit 0105f8f

Browse files
committed
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
2 parents 049b50d + 2255973 commit 0105f8f

File tree

16 files changed

+1338
-133
lines changed

16 files changed

+1338
-133
lines changed

doc/py_tutorials/py_calib3d/py_epipolar_geometry/py_epipolar_geometry.markdown

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ from matplotlib import pyplot as plt
7979
img1 = cv.imread('myleft.jpg',0) #queryimage # left image
8080
img2 = cv.imread('myright.jpg',0) #trainimage # right image
8181

82-
sift = cv.SIFT()
82+
sift = cv.SIFT_create()
8383

8484
# find the keypoints and descriptors with SIFT
8585
kp1, des1 = sift.detectAndCompute(img1,None)
@@ -93,14 +93,12 @@ search_params = dict(checks=50)
9393
flann = cv.FlannBasedMatcher(index_params,search_params)
9494
matches = flann.knnMatch(des1,des2,k=2)
9595

96-
good = []
9796
pts1 = []
9897
pts2 = []
9998

10099
# ratio test as per Lowe's paper
101100
for i,(m,n) in enumerate(matches):
102101
if m.distance < 0.8*n.distance:
103-
good.append(m)
104102
pts2.append(kp2[m.trainIdx].pt)
105103
pts1.append(kp1[m.queryIdx].pt)
106104
@endcode

doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.markdown

Lines changed: 179 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -84,57 +84,198 @@ This tutorial's code is shown below. You can also download it
8484
Explanation
8585
-----------
8686

87-
-# Most of the material shown here is trivial (if you have any doubt, please refer to the tutorials in
88-
previous sections). Let's check the general structure of the C++ program:
87+
@add_toggle_cpp
88+
Most of the material shown here is trivial (if you have any doubt, please refer to the tutorials in
89+
previous sections). Let's check the general structure of the C++ program:
90+
91+
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp main
92+
93+
-# Load an image (can be BGR or grayscale)
94+
-# Create two windows (one for dilation output, the other for erosion)
95+
-# Create a set of two Trackbars for each operation:
96+
- The first trackbar "Element" returns either **erosion_elem** or **dilation_elem**
97+
- The second trackbar "Kernel size" return **erosion_size** or **dilation_size** for the
98+
corresponding operation.
99+
-# Call once erosion and dilation to show the initial image.
100+
101+
102+
Every time we move any slider, the user's function **Erosion** or **Dilation** will be
103+
called and it will update the output image based on the current trackbar values.
104+
105+
Let's analyze these two functions:
106+
107+
#### The erosion function
108+
109+
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp erosion
110+
111+
The function that performs the *erosion* operation is @ref cv::erode . As we can see, it
112+
receives three arguments:
113+
- *src*: The source image
114+
- *erosion_dst*: The output image
115+
- *element*: This is the kernel we will use to perform the operation. If we do not
116+
specify, the default is a simple `3x3` matrix. Otherwise, we can specify its
117+
shape. For this, we need to use the function cv::getStructuringElement :
118+
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp kernel
119+
120+
We can choose any of three shapes for our kernel:
121+
122+
- Rectangular box: MORPH_RECT
123+
- Cross: MORPH_CROSS
124+
- Ellipse: MORPH_ELLIPSE
125+
126+
Then, we just have to specify the size of our kernel and the *anchor point*. If not
127+
specified, it is assumed to be in the center.
128+
129+
That is all. We are ready to perform the erosion of our image.
130+
131+
#### The dilation function
132+
133+
The code is below. As you can see, it is completely similar to the snippet of code for **erosion**.
134+
Here we also have the option of defining our kernel, its anchor point and the size of the operator
135+
to be used.
136+
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp dilation
137+
@end_toggle
138+
139+
@add_toggle_java
140+
Most of the material shown here is trivial (if you have any doubt, please refer to the tutorials in
141+
previous sections). Let's check however the general structure of the java class. There are 4 main
142+
parts in the java class:
143+
144+
- the class constructor which setups the window that will be filled with window components
145+
- the `addComponentsToPane` method, which fills out the window
146+
- the `update` method, which determines what happens when the user changes any value
147+
- the `main` method, which is the entry point of the program
148+
149+
In this tutorial we will focus on the `addComponentsToPane` and `update` methods. However, for completion the
150+
steps followed in the constructor are:
151+
152+
-# Load an image (can be BGR or grayscale)
153+
-# Create a window
154+
-# Add various control components with `addComponentsToPane`
155+
-# show the window
156+
157+
The components were added by the following method:
158+
159+
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java components
160+
161+
In short we
162+
163+
-# create a panel for the sliders
164+
-# create a combo box for the element types
165+
-# create a slider for the kernel size
166+
-# create a combo box for the morphology function to use (erosion or dilation)
167+
168+
The action and state changed listeners added call at the end the `update` method which updates
169+
the image based on the current slider values. So every time we move any slider, the `update` method is triggered.
89170

90-
- Load an image (can be BGR or grayscale)
91-
- Create two windows (one for dilation output, the other for erosion)
92-
- Create a set of two Trackbars for each operation:
93-
- The first trackbar "Element" returns either **erosion_elem** or **dilation_elem**
94-
- The second trackbar "Kernel size" return **erosion_size** or **dilation_size** for the
95-
corresponding operation.
96-
- Every time we move any slider, the user's function **Erosion** or **Dilation** will be
97-
called and it will update the output image based on the current trackbar values.
171+
#### Updating the image
98172

99-
Let's analyze these two functions:
173+
To update the image we used the following implementation:
100174

101-
-# **erosion:**
102-
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp erosion
175+
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java update
103176

104-
- The function that performs the *erosion* operation is @ref cv::erode . As we can see, it
105-
receives three arguments:
106-
- *src*: The source image
107-
- *erosion_dst*: The output image
108-
- *element*: This is the kernel we will use to perform the operation. If we do not
109-
specify, the default is a simple `3x3` matrix. Otherwise, we can specify its
110-
shape. For this, we need to use the function cv::getStructuringElement :
111-
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp kernel
177+
In other words we
112178

113-
We can choose any of three shapes for our kernel:
179+
-# get the structuring element the user chose
180+
-# execute the **erosion** or **dilation** function based on `doErosion`
181+
-# reload the image with the morphology applied
182+
-# repaint the frame
114183

115-
- Rectangular box: MORPH_RECT
116-
- Cross: MORPH_CROSS
117-
- Ellipse: MORPH_ELLIPSE
184+
Let's analyze the `erode` and `dilate` methods:
118185

119-
Then, we just have to specify the size of our kernel and the *anchor point*. If not
120-
specified, it is assumed to be in the center.
186+
#### The erosion method
121187

122-
- That is all. We are ready to perform the erosion of our image.
123-
@note Additionally, there is another parameter that allows you to perform multiple erosions
124-
(iterations) at once. However, We haven't used it in this simple tutorial. You can check out the
125-
reference for more details.
188+
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java erosion
126189

127-
-# **dilation:**
190+
The function that performs the *erosion* operation is @ref cv::erode . As we can see, it
191+
receives three arguments:
192+
- *src*: The source image
193+
- *erosion_dst*: The output image
194+
- *element*: This is the kernel we will use to perform the operation. For specifying the shape, we need to use
195+
the function cv::getStructuringElement :
196+
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java kernel
128197

129-
The code is below. As you can see, it is completely similar to the snippet of code for **erosion**.
130-
Here we also have the option of defining our kernel, its anchor point and the size of the operator
131-
to be used.
132-
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp dilation
198+
We can choose any of three shapes for our kernel:
199+
200+
- Rectangular box: CV_SHAPE_RECT
201+
- Cross: CV_SHAPE_CROSS
202+
- Ellipse: CV_SHAPE_ELLIPSE
203+
204+
Together with the shape we specify the size of our kernel and the *anchor point*. If the anchor point is not
205+
specified, it is assumed to be in the center.
206+
207+
That is all. We are ready to perform the erosion of our image.
208+
209+
#### The dilation function
210+
211+
The code is below. As you can see, it is completely similar to the snippet of code for **erosion**.
212+
Here we also have the option of defining our kernel, its anchor point and the size of the operator
213+
to be used.
214+
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java dilation
215+
@end_toggle
216+
217+
@add_toggle_python
218+
Most of the material shown here is trivial (if you have any doubt, please refer to the tutorials in
219+
previous sections). Let's check the general structure of the python script:
220+
221+
@snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py main
222+
223+
-# Load an image (can be BGR or grayscale)
224+
-# Create two windows (one for erosion output, the other for dilation) with a set of trackbars each
225+
- The first trackbar "Element" returns the value for the morphological type that will be mapped
226+
(1 = rectangle, 2 = cross, 3 = ellipse)
227+
- The second trackbar "Kernel size" returns the size of the element for the
228+
corresponding operation
229+
-# Call once erosion and dilation to show the initial image
230+
231+
Every time we move any slider, the user's function **erosion** or **dilation** will be
232+
called and it will update the output image based on the current trackbar values.
233+
234+
Let's analyze these two functions:
235+
236+
#### The erosion function
237+
238+
@snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py erosion
239+
240+
The function that performs the *erosion* operation is @ref cv::erode . As we can see, it
241+
receives two arguments and returns the processed image:
242+
- *src*: The source image
243+
- *element*: The kernel we will use to perform the operation. We can specify its
244+
shape by using the function cv::getStructuringElement :
245+
@snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py kernel
246+
247+
We can choose any of three shapes for our kernel:
248+
249+
- Rectangular box: MORPH_RECT
250+
- Cross: MORPH_CROSS
251+
- Ellipse: MORPH_ELLIPSE
252+
253+
Then, we just have to specify the size of our kernel and the *anchor point*. If the anchor point not
254+
specified, it is assumed to be in the center.
255+
256+
That is all. We are ready to perform the erosion of our image.
257+
258+
#### The dilation function
259+
260+
The code is below. As you can see, it is completely similar to the snippet of code for **erosion**.
261+
Here we also have the option of defining our kernel, its anchor point and the size of the operator
262+
to be used.
263+
264+
@snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py dilation
265+
@end_toggle
266+
267+
@note Additionally, there are further parameters that allow you to perform multiple erosions/dilations
268+
(iterations) at once and also set the border type and value. However, We haven't used those
269+
in this simple tutorial. You can check out the reference for more details.
133270

134271
Results
135272
-------
136273

137-
Compile the code above and execute it with an image as argument. For instance, using this image:
274+
Compile the code above and execute it (or run the script if using python) with an image as argument.
275+
If you do not provide an image as argument the default sample image
276+
([LinuxLogo.jpg](https://github.com/opencv/opencv/tree/master/samples/data/LinuxLogo.jpg)) will be used.
277+
278+
For instance, using this image:
138279

139280
![](images/Morphology_1_Tutorial_Original_Image.jpg)
140281

@@ -143,3 +284,4 @@ naturally. Try them out! You can even try to add a third Trackbar to control the
143284
iterations.
144285

145286
![](images/Morphology_1_Result.jpg)
287+
(depending on the programming language the output might vary a little or be only 1 window)

modules/calib3d/doc/calib3d.bib

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ @article{penate2013exhaustive
4040
publisher={IEEE}
4141
}
4242

43+
@inproceedings{Terzakis20,
44+
author = {Terzakis, George and Lourakis, Manolis},
45+
year = {2020},
46+
month = {09},
47+
pages = {},
48+
title = {A Consistently Fast and Globally Optimal Solution to the Perspective-n-Point Problem}
49+
}
50+
4351
@inproceedings{strobl2011iccv,
4452
title={More accurate pinhole camera calibration with imperfect planar target},
4553
author={Strobl, Klaus H. and Hirzinger, Gerd},

modules/calib3d/include/opencv2/calib3d.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ enum SolvePnPMethod {
471471
//!< - point 1: [ squareLength / 2, squareLength / 2, 0]
472472
//!< - point 2: [ squareLength / 2, -squareLength / 2, 0]
473473
//!< - point 3: [-squareLength / 2, -squareLength / 2, 0]
474+
SOLVEPNP_SQPNP = 8, //!< SQPnP: A Consistently Fast and Globally OptimalSolution to the Perspective-n-Point Problem @cite Terzakis20
474475
#ifndef CV_DOXYGEN
475476
SOLVEPNP_MAX_COUNT //!< Used for count
476477
#endif
@@ -946,6 +947,9 @@ It requires 4 coplanar object points defined in the following order:
946947
- point 1: [ squareLength / 2, squareLength / 2, 0]
947948
- point 2: [ squareLength / 2, -squareLength / 2, 0]
948949
- point 3: [-squareLength / 2, -squareLength / 2, 0]
950+
- **SOLVEPNP_SQPNP** Method is based on the paper "A Consistently Fast and Globally Optimal Solution to the
951+
Perspective-n-Point Problem" by G. Terzakis and M.Lourakis (@cite Terzakis20). It requires 3 or more points.
952+
949953
950954
The function estimates the object pose given a set of object points, their corresponding image
951955
projections, as well as the camera intrinsic matrix and the distortion coefficients, see the figure below
@@ -1069,6 +1073,7 @@ a 3D point expressed in the world frame into the camera frame:
10691073
- point 1: [ squareLength / 2, squareLength / 2, 0]
10701074
- point 2: [ squareLength / 2, -squareLength / 2, 0]
10711075
- point 3: [-squareLength / 2, -squareLength / 2, 0]
1076+
- With **SOLVEPNP_SQPNP** input points must be >= 3
10721077
*/
10731078
CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints,
10741079
InputArray cameraMatrix, InputArray distCoeffs,
@@ -2598,10 +2603,10 @@ CV_EXPORTS void convertPointsHomogeneous( InputArray src, OutputArray dst );
25982603
floating-point (single or double precision).
25992604
@param points2 Array of the second image points of the same size and format as points1 .
26002605
@param method Method for computing a fundamental matrix.
2601-
- **CV_FM_7POINT** for a 7-point algorithm. \f$N = 7\f$
2602-
- **CV_FM_8POINT** for an 8-point algorithm. \f$N \ge 8\f$
2603-
- **CV_FM_RANSAC** for the RANSAC algorithm. \f$N \ge 8\f$
2604-
- **CV_FM_LMEDS** for the LMedS algorithm. \f$N \ge 8\f$
2606+
- @ref FM_7POINT for a 7-point algorithm. \f$N = 7\f$
2607+
- @ref FM_8POINT for an 8-point algorithm. \f$N \ge 8\f$
2608+
- @ref FM_RANSAC for the RANSAC algorithm. \f$N \ge 8\f$
2609+
- @ref FM_LMEDS for the LMedS algorithm. \f$N \ge 8\f$
26052610
@param ransacReprojThreshold Parameter used only for RANSAC. It is the maximum distance from a point to an epipolar
26062611
line in pixels, beyond which the point is considered an outlier and is not used for computing the
26072612
final fundamental matrix. It can be set to something like 1-3, depending on the accuracy of the

modules/calib3d/src/solvepnp.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "p3p.h"
4848
#include "ap3p.h"
4949
#include "ippe.hpp"
50+
#include "sqpnp.hpp"
5051
#include "calib3d_c_api.h"
5152

5253
#include "usac.hpp"
@@ -796,7 +797,8 @@ int solvePnPGeneric( InputArray _opoints, InputArray _ipoints,
796797

797798
Mat opoints = _opoints.getMat(), ipoints = _ipoints.getMat();
798799
int npoints = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F));
799-
CV_Assert( ( (npoints >= 4) || (npoints == 3 && flags == SOLVEPNP_ITERATIVE && useExtrinsicGuess) )
800+
CV_Assert( ( (npoints >= 4) || (npoints == 3 && flags == SOLVEPNP_ITERATIVE && useExtrinsicGuess)
801+
|| (npoints >= 3 && flags == SOLVEPNP_SQPNP) )
800802
&& npoints == std::max(ipoints.checkVector(2, CV_32F), ipoints.checkVector(2, CV_64F)) );
801803

802804
opoints = opoints.reshape(3, npoints);
@@ -981,6 +983,14 @@ int solvePnPGeneric( InputArray _opoints, InputArray _ipoints,
981983
}
982984
} catch (...) { }
983985
}
986+
else if (flags == SOLVEPNP_SQPNP)
987+
{
988+
Mat undistortedPoints;
989+
undistortPoints(ipoints, undistortedPoints, cameraMatrix, distCoeffs);
990+
991+
sqpnp::PoseSolver solver;
992+
solver.solve(opoints, undistortedPoints, vec_rvecs, vec_tvecs);
993+
}
984994
/*else if (flags == SOLVEPNP_DLS)
985995
{
986996
Mat undistortedPoints;
@@ -1008,7 +1018,8 @@ int solvePnPGeneric( InputArray _opoints, InputArray _ipoints,
10081018
vec_tvecs.push_back(tvec);
10091019
}*/
10101020
else
1011-
CV_Error(CV_StsBadArg, "The flags argument must be one of SOLVEPNP_ITERATIVE, SOLVEPNP_P3P, SOLVEPNP_EPNP or SOLVEPNP_DLS");
1021+
CV_Error(CV_StsBadArg, "The flags argument must be one of SOLVEPNP_ITERATIVE, SOLVEPNP_P3P, "
1022+
"SOLVEPNP_EPNP, SOLVEPNP_DLS, SOLVEPNP_UPNP, SOLVEPNP_AP3P, SOLVEPNP_IPPE, SOLVEPNP_IPPE_SQUARE or SOLVEPNP_SQPNP");
10121023

10131024
CV_Assert(vec_rvecs.size() == vec_tvecs.size());
10141025

0 commit comments

Comments
 (0)