1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00

Merge pull request #29101 from asmorkalov:as/geometry_module

Moved geometry transformations from imgproc to 3d, future geometry module #29101

The first step of 2d geometry operations migration to the future geometry module.
I created 2d.hpp to isolate the moved functions for now. I propose to create geometry.hpp when the module is renamed and include all things there.

OpenCV contrib: https://github.com/opencv/opencv_contrib/pull/4126

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [ ] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Alexander Smorkalov
2026-05-28 21:09:52 +03:00
committed by GitHub
parent ccb808ba55
commit aac582119c
59 changed files with 1471 additions and 1415 deletions
+1 -1
View File
@@ -404,7 +404,7 @@ DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 250
DOT_GRAPH_MAX_NODES = 300
MAX_DOT_GRAPH_DEPTH = 0
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
+1
View File
@@ -8,6 +8,7 @@
#include "opencv2/core.hpp"
#include "opencv2/core/utils/logger.hpp"
#include "opencv2/3d/2d.hpp"
#include "opencv2/3d/depth.hpp"
#include "opencv2/3d/odometry.hpp"
#include "opencv2/3d/odometry_frame.hpp"
+811
View File
@@ -0,0 +1,811 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#ifndef OPENCV_2D_HPP
#define OPENCV_2D_HPP
#include "opencv2/core.hpp"
#include "opencv2/core/utils/logger.hpp"
namespace cv {
//! @addtogroup imgproc_shape
//! @{
//! types of intersection between rectangles
enum RectanglesIntersectTypes {
INTERSECT_NONE = 0, //!< No intersection
INTERSECT_PARTIAL = 1, //!< There is a partial intersection
INTERSECT_FULL = 2 //!< One of the rectangle is fully enclosed in the other
};
//! Variants of Line Segment %Detector
enum LineSegmentDetectorModes {
LSD_REFINE_NONE = 0, //!< No refinement applied
LSD_REFINE_STD = 1, //!< Standard refinement is applied. E.g. breaking arches into smaller straighter line approximations.
LSD_REFINE_ADV = 2 //!< Advanced refinement. Number of false alarms is calculated, lines are
//!< refined through increase of precision, decrement in size, etc.
};
//! @addtogroup imgproc_subdiv2d
//! @{
class CV_EXPORTS_W Subdiv2D
{
public:
/** Subdiv2D point location cases */
enum { PTLOC_ERROR = -2, //!< Point location error
PTLOC_OUTSIDE_RECT = -1, //!< Point outside the subdivision bounding rect
PTLOC_INSIDE = 0, //!< Point inside some facet
PTLOC_VERTEX = 1, //!< Point coincides with one of the subdivision vertices
PTLOC_ON_EDGE = 2 //!< Point on some edge
};
/** Subdiv2D edge type navigation (see: getEdge()) */
enum { NEXT_AROUND_ORG = 0x00,
NEXT_AROUND_DST = 0x22,
PREV_AROUND_ORG = 0x11,
PREV_AROUND_DST = 0x33,
NEXT_AROUND_LEFT = 0x13,
NEXT_AROUND_RIGHT = 0x31,
PREV_AROUND_LEFT = 0x20,
PREV_AROUND_RIGHT = 0x02
};
/** creates an empty Subdiv2D object.
* To create a new empty Delaunay subdivision you need to use the #initDelaunay function.
*/
CV_WRAP Subdiv2D();
/** @overload
*
* @param rect Rectangle that includes all of the 2D points that are to be added to the subdivision.
*
* The function creates an empty Delaunay subdivision where 2D points can be added using the function
* insert() . All of the points to be added must be within the specified rectangle, otherwise a runtime
* error is raised.
*/
CV_WRAP Subdiv2D(Rect rect);
/** @overload */
CV_WRAP Subdiv2D(Rect2f rect2f);
/** @overload
*
* @brief Creates a new empty Delaunay subdivision
*
* @param rect Rectangle that includes all of the 2D points that are to be added to the subdivision.
*
*/
CV_WRAP void initDelaunay(Rect rect);
/** @overload
*
* @brief Creates a new empty Delaunay subdivision
*
* @param rect Rectangle that includes all of the 2d points that are to be added to the subdivision.
*
*/
CV_WRAP_AS(initDelaunay2f) CV_WRAP void initDelaunay(Rect2f rect);
/** @brief Insert a single point into a Delaunay triangulation.
*
* @param pt Point to insert.
*
* The function inserts a single point into a subdivision and modifies the subdivision topology
* appropriately. If a point with the same coordinates exists already, no new point is added.
* @returns the ID of the point.
*
* @note If the point is outside of the triangulation specified rect a runtime error is raised.
*/
CV_WRAP int insert(Point2f pt);
/** @brief Insert multiple points into a Delaunay triangulation.
*
* @param ptvec Points to insert.
*
* The function inserts a vector of points into a subdivision and modifies the subdivision topology
* appropriately.
*/
CV_WRAP void insert(const std::vector<Point2f>& ptvec);
/** @brief Returns the location of a point within a Delaunay triangulation.
*
* @param pt Point to locate.
* @param edge Output edge that the point belongs to or is located to the right of it.
* @param vertex Optional output vertex the input point coincides with.
*
* The function locates the input point within the subdivision and gives one of the triangle edges
* or vertices.
*
* @returns an integer which specify one of the following five cases for point location:
* - The point falls into some facet. The function returns #PTLOC_INSIDE and edge will contain one of
* edges of the facet.
* - The point falls onto the edge. The function returns #PTLOC_ON_EDGE and edge will contain this edge.
* - The point coincides with one of the subdivision vertices. The function returns #PTLOC_VERTEX and
* vertex will contain a pointer to the vertex.
* - The point is outside the subdivision reference rectangle. The function returns #PTLOC_OUTSIDE_RECT
* and no pointers are filled.
* - One of input arguments is invalid. A runtime error is raised or, if silent or "parent" error
* processing mode is selected, #PTLOC_ERROR is returned.
*/
CV_WRAP int locate(Point2f pt, CV_OUT int& edge, CV_OUT int& vertex);
/** @brief Finds the subdivision vertex closest to the given point.
*
* @param pt Input point.
* @param nearestPt Output subdivision vertex point.
*
* The function is another function that locates the input point within the subdivision. It finds the
* subdivision vertex that is the closest to the input point. It is not necessarily one of vertices
* of the facet containing the input point, though the facet (located using locate() ) is used as a
* starting point.
*
* @returns vertex ID.
*/
CV_WRAP int findNearest(Point2f pt, CV_OUT Point2f* nearestPt = 0);
/** @brief Returns a list of all edges.
*
* @param edgeList Output vector.
*
* The function gives each edge as a 4 numbers vector, where each two are one of the edge
* vertices. i.e. org_x = v[0], org_y = v[1], dst_x = v[2], dst_y = v[3].
*/
CV_WRAP void getEdgeList(CV_OUT std::vector<Vec4f>& edgeList) const;
/** @brief Returns a list of the leading edge ID connected to each triangle.
*
* @param leadingEdgeList Output vector.
*
* The function gives one edge ID for each triangle.
*/
CV_WRAP void getLeadingEdgeList(CV_OUT std::vector<int>& leadingEdgeList) const;
/** @brief Returns a list of all triangles.
*
* @param triangleList Output vector.
*
* The function gives each triangle as a 6 numbers vector, where each two are one of the triangle
* vertices. i.e. p1_x = v[0], p1_y = v[1], p2_x = v[2], p2_y = v[3], p3_x = v[4], p3_y = v[5].
*/
CV_WRAP void getTriangleList(CV_OUT std::vector<Vec6f>& triangleList) const;
/** @brief Returns a list of all Voronoi facets.
*
* @param idx Vector of vertices IDs to consider. For all vertices you can pass empty vector.
* @param facetList Output vector of the Voronoi facets.
* @param facetCenters Output vector of the Voronoi facets center points.
*
*/
CV_WRAP void getVoronoiFacetList(const std::vector<int>& idx, CV_OUT std::vector<std::vector<Point2f> >& facetList,
CV_OUT std::vector<Point2f>& facetCenters);
/** @brief Returns vertex location from vertex ID.
*
* @param vertex vertex ID.
* @param firstEdge Optional. The first edge ID which is connected to the vertex.
* @returns vertex (x,y)
*
*/
CV_WRAP Point2f getVertex(int vertex, CV_OUT int* firstEdge = 0) const;
/** @brief Returns one of the edges related to the given edge.
*
* @param edge Subdivision edge ID.
* @param nextEdgeType Parameter specifying which of the related edges to return.
* The following values are possible:
* - NEXT_AROUND_ORG next around the edge origin ( eOnext on the picture below if e is the input edge)
* - NEXT_AROUND_DST next around the edge vertex ( eDnext )
* - PREV_AROUND_ORG previous around the edge origin (reversed eRnext )
* - PREV_AROUND_DST previous around the edge destination (reversed eLnext )
* - NEXT_AROUND_LEFT next around the left facet ( eLnext )
* - NEXT_AROUND_RIGHT next around the right facet ( eRnext )
* - PREV_AROUND_LEFT previous around the left facet (reversed eOnext )
* - PREV_AROUND_RIGHT previous around the right facet (reversed eDnext )
*
* ![sample output](pics/quadedge.png)
*
* @returns edge ID related to the input edge.
*/
CV_WRAP int getEdge( int edge, int nextEdgeType ) const;
/** @brief Returns next edge around the edge origin.
*
* @param edge Subdivision edge ID.
*
* @returns an integer which is next edge ID around the edge origin: eOnext on the
* picture above if e is the input edge).
*/
CV_WRAP int nextEdge(int edge) const;
/** @brief Returns another edge of the same quad-edge.
*
* @param edge Subdivision edge ID.
* @param rotate Parameter specifying which of the edges of the same quad-edge as the input
* one to return. The following values are possible:
* - 0 - the input edge ( e on the picture below if e is the input edge)
* - 1 - the rotated edge ( eRot )
* - 2 - the reversed edge (reversed e (in green))
* - 3 - the reversed rotated edge (reversed eRot (in green))
*
* @returns one of the edges ID of the same quad-edge as the input edge.
*/
CV_WRAP int rotateEdge(int edge, int rotate) const;
CV_WRAP int symEdge(int edge) const;
/** @brief Returns the edge origin.
*
* @param edge Subdivision edge ID.
* @param orgpt Output vertex location.
*
* @returns vertex ID.
*/
CV_WRAP int edgeOrg(int edge, CV_OUT Point2f* orgpt = 0) const;
/** @brief Returns the edge destination.
*
* @param edge Subdivision edge ID.
* @param dstpt Output vertex location.
*
* @returns vertex ID.
*/
CV_WRAP int edgeDst(int edge, CV_OUT Point2f* dstpt = 0) const;
protected:
int newEdge();
void deleteEdge(int edge);
int newPoint(Point2f pt, bool isvirtual, int firstEdge = 0);
void deletePoint(int vtx);
void setEdgePoints( int edge, int orgPt, int dstPt );
void splice( int edgeA, int edgeB );
int connectEdges( int edgeA, int edgeB );
void swapEdges( int edge );
int isRightOf(Point2f pt, int edge) const;
void calcVoronoi();
void clearVoronoi();
void checkSubdiv() const;
struct CV_EXPORTS Vertex
{
Vertex();
Vertex(Point2f pt, bool isvirtual, int firstEdge=0);
bool isvirtual() const;
bool isfree() const;
int firstEdge;
int type;
Point2f pt;
};
struct CV_EXPORTS QuadEdge
{
QuadEdge();
QuadEdge(int edgeidx);
bool isfree() const;
int next[4];
int pt[4];
};
//! All of the vertices
std::vector<Vertex> vtx;
//! All of the edges
std::vector<QuadEdge> qedges;
int freeQEdge;
int freePoint;
bool validGeometry;
int recentEdge;
//! Top left corner of the bounding rect
Point2f topLeft;
//! Bottom right corner of the bounding rect
Point2f bottomRight;
};
//! @} imgproc_subdiv2d
//! @addtogroup imgproc_feature
//! @{
/** @example samples/cpp/snippets/lsd_lines.cpp
An example using the LineSegmentDetector
\image html building_lsd.png "Sample output image" width=434 height=300
*/
/** @brief Line segment detector class
following the algorithm described at @cite Rafael12 .
@note Implementation has been removed from OpenCV version 3.4.6 to 3.4.15 and version 4.1.0 to 4.5.3 due original code license conflict.
restored again after [Computation of a NFA](https://github.com/rafael-grompone-von-gioi/binomial_nfa) code published under the MIT license.
*/
class CV_EXPORTS_W LineSegmentDetector : public Algorithm
{
public:
/** @brief Finds lines in the input image.
This is the output of the default parameters of the algorithm on the above shown image.
![image](pics/building_lsd.png)
@param image A grayscale (CV_8UC1) input image. If only a roi needs to be selected, use:
`lsd_ptr-\>detect(image(roi), lines, ...); lines += Scalar(roi.x, roi.y, roi.x, roi.y);`
@param lines A vector of Vec4f elements specifying the beginning and ending point of a line. Where
Vec4f is (x1, y1, x2, y2), point 1 is the start, point 2 - end. Returned lines are strictly
oriented depending on the gradient.
@param width Vector of widths of the regions, where the lines are found. E.g. Width of line.
@param prec Vector of precisions with which the lines are found.
@param nfa Vector containing number of false alarms in the line region, with precision of 10%. The
bigger the value, logarithmically better the detection.
- -1 corresponds to 10 mean false alarms
- 0 corresponds to 1 mean false alarm
- 1 corresponds to 0.1 mean false alarms
This vector will be calculated only when the objects type is #LSD_REFINE_ADV.
*/
CV_WRAP virtual void detect(InputArray image, OutputArray lines,
OutputArray width = noArray(), OutputArray prec = noArray(),
OutputArray nfa = noArray()) = 0;
/** @brief Draws the line segments on a given image.
@param image The image, where the lines will be drawn. Should be bigger or equal to the image,
where the lines were found.
@param lines A vector of the lines that needed to be drawn.
*/
CV_WRAP virtual void drawSegments(InputOutputArray image, InputArray lines) = 0;
/** @brief Draws two groups of lines in blue and red, counting the non overlapping (mismatching) pixels.
@param size The size of the image, where lines1 and lines2 were found.
@param lines1 The first group of lines that needs to be drawn. It is visualized in blue color.
@param lines2 The second group of lines. They visualized in red color.
@param image Optional image, where the lines will be drawn. The image should be color(3-channel)
in order for lines1 and lines2 to be drawn in the above mentioned colors.
*/
CV_WRAP virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray image = noArray()) = 0;
virtual ~LineSegmentDetector() { }
};
/** @brief Creates a smart pointer to a LineSegmentDetector object and initializes it.
The LineSegmentDetector algorithm is defined using the standard values. Only advanced users may want
to edit those, as to tailor it for their own application.
@param refine The way found lines will be refined, see #LineSegmentDetectorModes
@param scale The scale of the image that will be used to find the lines. Range (0..1].
@param sigma_scale Sigma for Gaussian filter. It is computed as sigma = sigma_scale/scale.
@param quant Bound to the quantization error on the gradient norm.
@param ang_th Gradient angle tolerance in degrees.
@param log_eps Detection threshold: -log10(NFA) \> log_eps. Used only when advance refinement is chosen.
@param density_th Minimal density of aligned region points in the enclosing rectangle.
@param n_bins Number of bins in pseudo-ordering of gradient modulus.
*/
CV_EXPORTS_W Ptr<LineSegmentDetector> createLineSegmentDetector(
LineSegmentDetectorModes refine = LSD_REFINE_STD, double scale = 0.8,
double sigma_scale = 0.6, double quant = 2.0, double ang_th = 22.5,
double log_eps = 0, double density_th = 0.7, int n_bins = 1024);
//! @} imgproc_feature
/** @example samples/python/snippets/squares.py
A n example using approxPolyDP function in python. *
*/
/** @brief Approximates a polygonal curve(s) with the specified precision.
*
T he function cv::approxPolyDP approximates a curve or a p*olygon with another curve/polygon with less
vertices so that the distance between them is less or equal to the specified precision. It uses the
Douglas-Peucker algorithm <https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm>
@param curve Input vector of a 2D point stored in std::vector or Mat
@param approxCurve Result of the approximation. The type should match the type of the input curve.
@param epsilon Parameter specifying the approximation accuracy. This is the maximum distance
between the original curve and its approximation.
@param closed If true, the approximated curve is closed (its first and last vertices are
connected). Otherwise, it is not closed.
*/
CV_EXPORTS_W void approxPolyDP( InputArray curve,
OutputArray approxCurve,
double epsilon, bool closed );
/** @brief Approximates a polygon with a convex hull with a specified accuracy and number of sides.
*
T he cv::approxPolyN function approximates a polygon with *a convex hull
so that the difference between the contour area of the original contour and the new polygon is minimal.
It uses a greedy algorithm for contracting two vertices into one in such a way that the additional area is minimal.
Straight lines formed by each edge of the convex contour are drawn and the areas of the resulting triangles are considered.
Each vertex will lie either on the original contour or outside it.
The algorithm based on the paper @cite LowIlie2003 .
@param curve Input vector of a 2D points stored in std::vector or Mat, points must be float or integer.
@param approxCurve Result of the approximation. The type is vector of a 2D point (Point2f or Point) in std::vector or Mat.
@param nsides The parameter defines the number of sides of the result polygon.
@param epsilon_percentage defines the percentage of the maximum of additional area.
If it equals -1, it is not used. Otherwise algorithm stops if additional area is greater than contourArea(_curve) * percentage.
If additional area exceeds the limit, algorithm returns as many vertices as there were at the moment the limit was exceeded.
@param ensure_convex If it is true, algorithm creates a convex hull of input contour. Otherwise input vector should be convex.
*/
CV_EXPORTS_W void approxPolyN(InputArray curve, OutputArray approxCurve,
int nsides, float epsilon_percentage = -1.0,
bool ensure_convex = true);
/** @brief Finds a rotated rectangle of the minimum area enclosing the input 2D point set.
*
* The function calculates and returns the minimum-area bounding rectangle (possibly rotated) for a
* specified point set. The angle of rotation represents the angle between the line connecting the starting
* and ending points (based on the clockwise order with greatest index for the corner with greatest \f$y\f$)
* and the horizontal axis. This angle always falls between \f$[-90, 0)\f$ because, if the object
* rotates more than a rect angle, the next edge is used to measure the angle. The starting and ending points change
* as the object rotates.Developer should keep in mind that the returned RotatedRect can contain negative
* indices when data is close to the containing Mat element boundary.
*
* @param points Input vector of 2D points, stored in std::vector\<\> or Mat
*/
CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );
/** @brief Finds the four vertices of a rotated rect. Useful to draw the rotated rectangle.
*
* The function finds the four vertices of a rotated rectangle. The four vertices are returned
* in clockwise order starting from the point with greatest \f$y\f$. If two points have the
* same \f$y\f$ coordinate the rightmost is the starting point. This function is useful to draw the
* rectangle. In C++, instead of using this function, you can directly use RotatedRect::points method. Please
* visit the @ref tutorial_bounding_rotated_ellipses "tutorial on Creating Bounding rotated boxes and ellipses
* for contours" for more information.
*
* @param box The input rotated rectangle. It may be the output of @ref minAreaRect.
* @param points The output array of four vertices of rectangles.
*/
CV_EXPORTS_W void boxPoints(RotatedRect box, OutputArray points);
/** @brief Finds a circle of the minimum area enclosing a 2D point set.
*
* The function finds the minimal enclosing circle of a 2D point set using an iterative algorithm.
*
* @param points Input vector of 2D points, stored in std::vector\<\> or Mat
* @param center Output center of the circle.
* @param radius Output radius of the circle.
*/
CV_EXPORTS_W void minEnclosingCircle( InputArray points,
CV_OUT Point2f& center, CV_OUT float& radius );
/** @brief Finds a triangle of minimum area enclosing a 2D point set and returns its area.
*
* The function finds a triangle of minimum area enclosing the given set of 2D points and returns its
* area. The output for a given 2D point set is shown in the image below. 2D points are depicted in
*red* and the enclosing triangle in *yellow*.
*
* ![Sample output of the minimum enclosing triangle function](pics/minenclosingtriangle.png)
*
* The implementation of the algorithm is based on O'Rourke's @cite ORourke86 and Klee and Laskowski's
* @cite KleeLaskowski85 papers. O'Rourke provides a \f$\theta(n)\f$ algorithm for finding the minimal
* enclosing triangle of a 2D convex polygon with n vertices. Since the #minEnclosingTriangle function
* takes a 2D point set as input an additional preprocessing step of computing the convex hull of the
* 2D point set is required. The complexity of the #convexHull function is \f$O(n log(n))\f$ which is higher
* than \f$\theta(n)\f$. Thus the overall complexity of the function is \f$O(n log(n))\f$.
*
* @param points Input vector of 2D points with depth CV_32S or CV_32F, stored in std::vector\<\> or Mat
* @param triangle Output vector of three 2D points defining the vertices of the triangle. The depth
* of the OutputArray must be CV_32F.
*/
CV_EXPORTS_W double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle );
/**
* @brief Finds a convex polygon of minimum area enclosing a 2D point set and returns its area.
*
* This function takes a given set of 2D points and finds the enclosing polygon with k vertices and minimal
* area. It takes the set of points and the parameter k as input and returns the area of the minimal
* enclosing polygon.
*
* The Implementation is based on a paper by Aggarwal, Chang and Yap @cite Aggarwal1985. They
* provide a \f$\theta(n²log(n)log(k))\f$ algorithm for finding the minimal convex polygon with k
* vertices enclosing a 2D convex polygon with n vertices (k < n). Since the #minEnclosingConvexPolygon
* function takes a 2D point set as input, an additional preprocessing step of computing the convex hull
* of the 2D point set is required. The complexity of the #convexHull function is \f$O(n log(n))\f$ which
* is lower than \f$\theta(n²log(n)log(k))\f$. Thus the overall complexity of the function is
* \f$O(n²log(n)log(k))\f$.
*
* @param points Input vector of 2D points, stored in std::vector\<\> or Mat
* @param polygon Output vector of 2D points defining the vertices of the enclosing polygon
* @param k Number of vertices of the output polygon
*/
CV_EXPORTS_W double minEnclosingConvexPolygon ( InputArray points, OutputArray polygon, int k );
/** @brief Compares two shapes.
*
* The function compares two shapes. All three implemented methods use the Hu invariants (see #HuMoments)
*
* @param contour1 First contour or grayscale image.
* @param contour2 Second contour or grayscale image.
* @param method Comparison method, see #ShapeMatchModes
* @param parameter Method-specific parameter (not supported now).
*/
CV_EXPORTS_W double matchShapes( InputArray contour1, InputArray contour2,
int method, double parameter );
/** @example samples/cpp/geometry.cpp
* An example program illustrates the use of cv::convexHull, cv::fitEllipse, cv::minEnclosingTriangle, cv::minEnclosingCircle and cv::minAreaRect.
*/
/** @brief Finds the convex hull of a point set.
*
* The function cv::convexHull finds the convex hull of a 2D point set using the Sklansky's algorithm @cite Sklansky82
* that has *O(N logN)* complexity in the current implementation.
*
* @param points Input 2D point set, stored in std::vector or Mat.
* @param hull Output convex hull. It is either an integer vector of indices or vector of points. In
* the first case, the hull elements are 0-based indices of the convex hull points in the original
* array (since the set of convex hull points is a subset of the original point set). In the second
* case, hull elements are the convex hull points themselves.
* @param clockwise Orientation flag. If it is true, the output convex hull is oriented clockwise.
* Otherwise, it is oriented counter-clockwise. The assumed coordinate system has its X axis pointing
* to the right, and its Y axis pointing upwards.
* @param returnPoints Operation flag. In case of a matrix, when the flag is true, the function
* returns convex hull points. Otherwise, it returns indices of the convex hull points. When the
* output array is std::vector, the flag is ignored, and the output depends on the type of the
* vector: std::vector\<int\> implies returnPoints=false, std::vector\<Point\> implies
* returnPoints=true.
*
* @note `points` and `hull` should be different arrays, inplace processing isn't supported.
*
* Check @ref tutorial_hull "the corresponding tutorial" for more details.
*
* useful links:
*
* https://www.learnopencv.com/convex-hull-using-opencv-in-python-and-c/
*/
CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull,
bool clockwise = false, bool returnPoints = true );
/** @brief Finds the convexity defects of a contour.
*
* The figure below displays convexity defects of a hand contour:
*
* ![image](pics/defects.png)
*
* @param contour Input contour.
* @param convexhull Convex hull obtained using convexHull that should contain indices of the contour
* points that make the hull.
* @param convexityDefects The output vector of convexity defects. In C++ and the new Python/Java
* interface each convexity defect is represented as 4-element integer vector (a.k.a. #Vec4i):
* (start_index, end_index, farthest_pt_index, fixpt_depth), where indices are 0-based indices
* in the original contour of the convexity defect beginning, end and the farthest point, and
* fixpt_depth is fixed-point approximation (with 8 fractional bits) of the distance between the
* farthest contour point and the hull. That is, to get the floating-point value of the depth will be
* fixpt_depth/256.0.
*/
CV_EXPORTS_W void convexityDefects( InputArray contour, InputArray convexhull, OutputArray convexityDefects );
/** @brief Tests a contour convexity.
*
* The function tests whether the input contour is convex or not. The contour must be simple, that is,
* without self-intersections. Otherwise, the function output is undefined.
*
* @param contour Input vector of 2D points, stored in std::vector\<\> or Mat
*/
CV_EXPORTS_W bool isContourConvex( InputArray contour );
/** @example samples/cpp/snippets/intersectExample.cpp
* Examples of how intersectConvexConvex works
*/
/** @brief Finds intersection of two convex polygons
*
* @param p1 First polygon
* @param p2 Second polygon
* @param p12 Output polygon describing the intersecting area
* @param handleNested When true, an intersection is found if one of the polygons is fully enclosed in the other.
* When false, no intersection is found. If the polygons share a side or the vertex of one polygon lies on an edge
* of the other, they are not considered nested and an intersection will be found regardless of the value of handleNested.
*
* @returns Area of intersecting polygon. May be negative, if algorithm has not converged, e.g. non-convex input.
*
* @note intersectConvexConvex doesn't confirm that both polygons are convex and will return invalid results if they aren't.
*/
CV_EXPORTS_W float intersectConvexConvex( InputArray p1, InputArray p2,
OutputArray p12, bool handleNested = true );
/** @brief Fits an ellipse around a set of 2D points.
*
* The function calculates the ellipse that fits (in a least-squares sense) a set of 2D points best of
* all. It returns the rotated rectangle in which the ellipse is inscribed. The first algorithm described by @cite Fitzgibbon95
* is used. Developer should keep in mind that it is possible that the returned
* ellipse/rotatedRect data contains negative indices, due to the data points being close to the
* border of the containing Mat element.
*
* @param points Input 2D point set, stored in std::vector\<\> or Mat
*
* @note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required.
* @note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error.
*/
CV_EXPORTS_W RotatedRect fitEllipse( InputArray points );
/** @brief Fits an ellipse around a set of 2D points.
*
* The function calculates the ellipse that fits a set of 2D points.
* It returns the rotated rectangle in which the ellipse is inscribed.
* The Approximate Mean Square (AMS) proposed by @cite Taubin1991 is used.
*
* For an ellipse, this basis set is \f$ \chi= \left(x^2, x y, y^2, x, y, 1\right) \f$,
* which is a set of six free coefficients \f$ A^T=\left\{A_{\text{xx}},A_{\text{xy}},A_{\text{yy}},A_x,A_y,A_0\right\} \f$.
* However, to specify an ellipse, all that is needed is five numbers; the major and minor axes lengths \f$ (a,b) \f$,
* the position \f$ (x_0,y_0) \f$, and the orientation \f$ \theta \f$. This is because the basis set includes lines,
* quadratics, parabolic and hyperbolic functions as well as elliptical functions as possible fits.
* If the fit is found to be a parabolic or hyperbolic function then the standard #fitEllipse method is used.
* The AMS method restricts the fit to parabolic, hyperbolic and elliptical curves
* by imposing the condition that \f$ A^T ( D_x^T D_x + D_y^T D_y) A = 1 \f$ where
* the matrices \f$ Dx \f$ and \f$ Dy \f$ are the partial derivatives of the design matrix \f$ D \f$ with
* respect to x and y. The matrices are formed row by row applying the following to
* each of the points in the set:
* \f{align*}{
* D(i,:)&=\left\{x_i^2, x_i y_i, y_i^2, x_i, y_i, 1\right\} &
* D_x(i,:)&=\left\{2 x_i,y_i,0,1,0,0\right\} &
* D_y(i,:)&=\left\{0,x_i,2 y_i,0,1,0\right\}
* \f}
* The AMS method minimizes the cost function
* \f{equation*}{
* \epsilon ^2=\frac{ A^T D^T D A }{ A^T (D_x^T D_x + D_y^T D_y) A^T }
* \f}
*
* The minimum cost is found by solving the generalized eigenvalue problem.
*
* \f{equation*}{
* D^T D A = \lambda \left( D_x^T D_x + D_y^T D_y\right) A
* \f}
*
* @param points Input 2D point set, stored in std::vector\<\> or Mat
*
* @note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required.
* @note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error.
*/
CV_EXPORTS_W RotatedRect fitEllipseAMS( InputArray points );
/** @brief Fits an ellipse around a set of 2D points.
*
* The function calculates the ellipse that fits a set of 2D points.
* It returns the rotated rectangle in which the ellipse is inscribed.
* The Direct least square (Direct) method by @cite oy1998NumericallySD is used.
*
* For an ellipse, this basis set is \f$ \chi= \left(x^2, x y, y^2, x, y, 1\right) \f$,
* which is a set of six free coefficients \f$ A^T=\left\{A_{\text{xx}},A_{\text{xy}},A_{\text{yy}},A_x,A_y,A_0\right\} \f$.
* However, to specify an ellipse, all that is needed is five numbers; the major and minor axes lengths \f$ (a,b) \f$,
* the position \f$ (x_0,y_0) \f$, and the orientation \f$ \theta \f$. This is because the basis set includes lines,
* quadratics, parabolic and hyperbolic functions as well as elliptical functions as possible fits.
* The Direct method confines the fit to ellipses by ensuring that \f$ 4 A_{xx} A_{yy}- A_{xy}^2 > 0 \f$.
* The condition imposed is that \f$ 4 A_{xx} A_{yy}- A_{xy}^2=1 \f$ which satisfies the inequality
* and as the coefficients can be arbitrarily scaled is not overly restrictive.
*
* \f{equation*}{
* \epsilon ^2= A^T D^T D A \quad \text{with} \quad A^T C A =1 \quad \text{and} \quad C=\left(\begin{matrix}
* 0 & 0 & 2 & 0 & 0 & 0 \\
* 0 & -1 & 0 & 0 & 0 & 0 \\
* 2 & 0 & 0 & 0 & 0 & 0 \\
* 0 & 0 & 0 & 0 & 0 & 0 \\
* 0 & 0 & 0 & 0 & 0 & 0 \\
* 0 & 0 & 0 & 0 & 0 & 0
* \end{matrix} \right)
* \f}
*
* The minimum cost is found by solving the generalized eigenvalue problem.
*
* \f{equation*}{
* D^T D A = \lambda \left( C\right) A
* \f}
*
* The system produces only one positive eigenvalue \f$ \lambda\f$ which is chosen as the solution
* with its eigenvector \f$\mathbf{u}\f$. These are used to find the coefficients
*
* \f{equation*}{
* A = \sqrt{\frac{1}{\mathbf{u}^T C \mathbf{u}}} \mathbf{u}
* \f}
* The scaling factor guarantees that \f$A^T C A =1\f$.
*
* @param points Input 2D point set, stored in std::vector\<\> or Mat
*
* @note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required.
* @note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error.
*/
CV_EXPORTS_W RotatedRect fitEllipseDirect( InputArray points );
/** @example samples/python/snippets/fitline.py
* An example for fitting line in python
*/
/** @brief Compute for each 2d point the nearest 2d point located on a given ellipse.
*
* The function computes the nearest 2d location on a given ellipse for a vector of 2d points and is based on @cite Chatfield2017 code.
* This function can be used to compute for instance the ellipse fitting error.
*
* @param ellipse_params Ellipse parameters
* @param points Input 2d points
* @param closest_pts For each 2d point, their corresponding closest 2d point located on a given ellipse
*
* @note Input point types are @ref Point2i or @ref Point2f
* @see fitEllipse, fitEllipseAMS, fitEllipseDirect
*/
CV_EXPORTS_W void getClosestEllipsePoints( const RotatedRect& ellipse_params, InputArray points, OutputArray closest_pts );
/** @brief Fits a line to a 2D or 3D point set.
*
* The function fitLine fits a line to a 2D or 3D point set by minimizing \f$\sum_i \rho(r_i)\f$ where
* \f$r_i\f$ is a distance between the \f$i^{th}\f$ point, the line and \f$\rho(r)\f$ is a distance function, one
* of the following:
* - DIST_L2
* \f[\rho (r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)}\f]
* - DIST_L1
* \f[\rho (r) = r\f]
* - DIST_L12
* \f[\rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)\f]
* - DIST_FAIR
* \f[\rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998\f]
* - DIST_WELSCH
* \f[\rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846\f]
* - DIST_HUBER
* \f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f]
*
* The algorithm is based on the M-estimator ( <https://en.wikipedia.org/wiki/M-estimator> ) technique
* that iteratively fits the line using the weighted least-squares algorithm. After each iteration the
* weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ .
*
* @param points Input vector of 2D or 3D points, stored in std::vector\<\> or Mat.
* @param line Output line parameters. In case of 2D fitting, it should be a vector of 4 elements
* (like Vec4f) - (vx, vy, x0, y0), where (vx, vy) is a normalized vector collinear to the line and
* (x0, y0) is a point on the line. In case of 3D fitting, it should be a vector of 6 elements (like
* Vec6f) - (vx, vy, vz, x0, y0, z0), where (vx, vy, vz) is a normalized vector collinear to the line
* and (x0, y0, z0) is a point on the line.
* @param distType Distance used by the M-estimator, see #DistanceTypes
* @param param Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value
* is chosen.
* @param reps Sufficient accuracy for the radius (distance between the coordinate origin and the line).
* @param aeps Sufficient accuracy for the angle. 0.01 would be a good default value for reps and aeps.
*/
CV_EXPORTS_W void fitLine( InputArray points, OutputArray line, int distType,
double param, double reps, double aeps );
/** @brief Performs a point-in-contour test.
*
* The function determines whether the point is inside a contour, outside, or lies on an edge (or
* coincides with a vertex). It returns positive (inside), negative (outside), or zero (on an edge)
* value, correspondingly. When measureDist=false , the return value is +1, -1, and 0, respectively.
* Otherwise, the return value is a signed distance between the point and the nearest contour edge.
*
* See below a sample output of the function where each image pixel is tested against the contour:
*
* ![sample output](pics/pointpolygon.png)
*
* @param contour Input contour.
* @param pt Point tested against the contour.
* @param measureDist If true, the function estimates the signed distance from the point to the
* nearest contour edge. Otherwise, the function only checks if the point is inside a contour or not.
*/
CV_EXPORTS_W double pointPolygonTest( InputArray contour, Point2f pt, bool measureDist );
/** @brief Finds out if there is any intersection between two rotated rectangles.
*
* If there is then the vertices of the intersecting region are returned as well.
*
* Below are some examples of intersection configurations. The hatched pattern indicates the
* intersecting region and the red vertices are returned by the function.
*
* ![intersection examples](pics/intersection.png)
*
* @param rect1 First rectangle
* @param rect2 Second rectangle
* @param intersectingRegion The output array of the vertices of the intersecting region. It returns
* at most 8 vertices. Stored as std::vector\<cv::Point2f\> or cv::Mat as Mx1 of type CV_32FC2.
* @returns One of #RectanglesIntersectTypes
*/
CV_EXPORTS_W int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion );
} // namespace cv
#endif // OPENCV_2D_HPP
+158
View File
@@ -1,17 +1,23 @@
package org.opencv.test.cv3d;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.opencv.cv3d.Cv3d;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfDouble;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.MatOfPoint3f;
import org.opencv.core.MatOfInt;
import org.opencv.core.MatOfInt4;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.core.RotatedRect;
import org.opencv.test.OpenCVTestCase;
import org.opencv.imgproc.Imgproc;
@@ -583,4 +589,156 @@ public class Cv3dTest extends OpenCVTestCase {
assertMatEqual(K_new, K_new_truth, EPS);
}
public void testApproxPolyDP() {
MatOfPoint2f curve = new MatOfPoint2f(new Point(1, 3), new Point(2, 4), new Point(3, 5), new Point(4, 4), new Point(5, 3));
MatOfPoint2f approxCurve = new MatOfPoint2f();
Cv3d.approxPolyDP(curve, approxCurve, EPS, true);
List<Point> approxCurveGold = new ArrayList<Point>(3);
approxCurveGold.add(new Point(1, 3));
approxCurveGold.add(new Point(3, 5));
approxCurveGold.add(new Point(5, 3));
assertListPointEquals(approxCurve.toList(), approxCurveGold, EPS);
}
public void testConvexHullMatMat() {
MatOfPoint points = new MatOfPoint(
new Point(20, 0),
new Point(40, 0),
new Point(30, 20),
new Point(0, 20),
new Point(20, 10),
new Point(30, 10)
);
MatOfInt hull = new MatOfInt();
Cv3d.convexHull(points, hull);
MatOfInt expHull = new MatOfInt(
0, 1, 2, 3
);
assertMatEqual(expHull, hull.reshape(1, (int)hull.total()), EPS);
}
public void testConvexHullMatMatBooleanBoolean() {
MatOfPoint points = new MatOfPoint(
new Point(2, 0),
new Point(4, 0),
new Point(3, 2),
new Point(0, 2),
new Point(2, 1),
new Point(3, 1)
);
MatOfInt hull = new MatOfInt();
Cv3d.convexHull(points, hull, true);
MatOfInt expHull = new MatOfInt(
3, 2, 1, 0
);
assertMatEqual(expHull, hull.reshape(1, hull.cols()), EPS);
}
public void testConvexityDefects() {
MatOfPoint points = new MatOfPoint(
new Point(20, 0),
new Point(40, 0),
new Point(30, 20),
new Point(0, 20),
new Point(20, 10),
new Point(30, 10)
);
MatOfInt hull = new MatOfInt();
Cv3d.convexHull(points, hull);
MatOfInt4 convexityDefects = new MatOfInt4();
Cv3d.convexityDefects(points, hull, convexityDefects);
assertMatEqual(new MatOfInt4(3, 0, 5, 3620), convexityDefects.reshape(4, convexityDefects.cols()));
}
public void testFitEllipse() {
MatOfPoint2f points = new MatOfPoint2f(new Point(0, 0), new Point(-1, 1), new Point(1, 1), new Point(1, -1), new Point(-1, -1));
RotatedRect rrect = new RotatedRect();
rrect = Cv3d.fitEllipse(points);
double FIT_ELLIPSE_CENTER_EPS = 0.01;
double FIT_ELLIPSE_SIZE_EPS = 0.4;
assertEquals(0.0, rrect.center.x, FIT_ELLIPSE_CENTER_EPS);
assertEquals(0.0, rrect.center.y, FIT_ELLIPSE_CENTER_EPS);
assertEquals(2.828, rrect.size.width, FIT_ELLIPSE_SIZE_EPS);
assertEquals(2.828, rrect.size.height, FIT_ELLIPSE_SIZE_EPS);
}
public void testFitLine() {
Mat points = new Mat(1, 4, CvType.CV_32FC2);
points.put(0, 0, 0, 0, 2, 3, 3, 4, 5, 8);
Mat linePoints = new Mat(4, 1, CvType.CV_32FC1);
linePoints.put(0, 0, 0.53198653, 0.84675282, 2.5, 3.75);
Cv3d.fitLine(points, dst, Imgproc.DIST_L12, 0, 0.01, 0.01);
assertMatEqual(linePoints, dst, EPS);
}
public void testIsContourConvex() {
MatOfPoint contour1 = new MatOfPoint(new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(5, 4));
assertFalse(Cv3d.isContourConvex(contour1));
MatOfPoint contour2 = new MatOfPoint(new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(5, 6));
assertTrue(Cv3d.isContourConvex(contour2));
}
public void testMatchShapes() {
Mat contour1 = new Mat(1, 4, CvType.CV_32FC2);
Mat contour2 = new Mat(1, 4, CvType.CV_32FC2);
contour1.put(0, 0, 1, 1, 5, 1, 4, 3, 6, 2);
contour2.put(0, 0, 1, 1, 6, 1, 4, 1, 2, 5);
double distance = Cv3d.matchShapes(contour1, contour2, Imgproc.CONTOURS_MATCH_I1, 1);
assertEquals(2.81109697365334, distance, EPS);
}
public void testMinAreaRect() {
MatOfPoint2f points = new MatOfPoint2f(new Point(1, 1), new Point(5, 1), new Point(4, 3), new Point(6, 2));
RotatedRect rrect = Cv3d.minAreaRect(points);
assertEquals(new Size(2, 5), rrect.size);
assertEquals(-90., rrect.angle);
assertEquals(new Point(3.5, 2), rrect.center);
}
public void testMinEnclosingCircle() {
MatOfPoint2f points = new MatOfPoint2f(new Point(0, 0), new Point(-100, 0), new Point(0, -100), new Point(100, 0), new Point(0, 100));
Point actualCenter = new Point();
float[] radius = new float[1];
Cv3d.minEnclosingCircle(points, actualCenter, radius);
assertEquals(new Point(0, 0), actualCenter);
assertEquals(100.0f, radius[0], 1.0);
}
public void testPointPolygonTest() {
MatOfPoint2f contour = new MatOfPoint2f(new Point(0, 0), new Point(1, 3), new Point(3, 4), new Point(4, 3), new Point(2, 1));
double sign1 = Cv3d.pointPolygonTest(contour, new Point(2, 2), false);
assertEquals(1.0, sign1);
double sign2 = Cv3d.pointPolygonTest(contour, new Point(4, 4), true);
assertEquals(-Math.sqrt(0.5), sign2);
}
}
@@ -1,9 +1,9 @@
package org.opencv.test.imgproc;
package org.opencv.test.cv3d;
import org.opencv.core.MatOfFloat6;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.imgproc.Subdiv2D;
import org.opencv.cv3d.Subdiv2D;
import org.opencv.test.OpenCVTestCase;
public class Subdiv2DTest extends OpenCVTestCase {
+47
View File
@@ -0,0 +1,47 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "perf_precomp.hpp"
#include "opencv2/ts.hpp"
#include "opencv2/ts/ts_perf.hpp"
namespace opencv_test { namespace {
using namespace perf;
typedef TestBaseWithParam< tuple<MatDepth, int> > TestMinEnclosingCircle;
PERF_TEST_P(TestMinEnclosingCircle, minEnclosingCircle,
Combine(
testing::Values(CV_32S, CV_32F),
Values(400, 1000, 10000, 100000)
))
{
int ptType = get<0>(GetParam());
int n = get<1>(GetParam());
Mat pts(n, 2, ptType);
declare.in(pts, WARMUP_RNG);
Point2f center;
float radius;
TEST_CYCLE() minEnclosingCircle(pts, center, radius);
SANITY_CHECK_NOTHING();
}
typedef TestBaseWithParam<int> TestMinEnclosingCircleWorstCase;
PERF_TEST_P(TestMinEnclosingCircleWorstCase, minEnclosingCircle_sequential,
Values(400, 1000, 5000, 10000))
{
int n = GetParam();
vector<Point2f> contour;
for(int i = 0; i < n; ++i) {
float angle = (float)(i * 2 * CV_PI / n);
contour.push_back(Point2f(cos(angle) * 100, sin(angle) * 100));
}
Point2f center;
float radius;
TEST_CYCLE() minEnclosingCircle(contour, center, radius);
SANITY_CHECK_NOTHING();
}
}} // namespace
@@ -554,214 +554,3 @@ float cv::intersectConvexConvex( InputArray _p1, InputArray _p2, OutputArray _p1
}
return (float)fabs(area);
}
static Rect maskBoundingRect( const Mat& img )
{
CV_Assert( img.depth() <= CV_8S && img.channels() == 1 );
Size size = img.size();
int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k;
for( i = 0; i < size.height; i++ )
{
const uchar* _ptr = img.ptr(i);
const uchar* ptr = (const uchar*)alignPtr(_ptr, 4);
int have_nz = 0, k_min, offset = (int)(ptr - _ptr);
j = 0;
offset = MIN(offset, size.width);
for( ; j < offset; j++ )
if( _ptr[j] )
{
if( j < xmin )
xmin = j;
if( j > xmax )
xmax = j;
have_nz = 1;
}
if( offset < size.width )
{
xmin -= offset;
xmax -= offset;
size.width -= offset;
j = 0;
for( ; j <= xmin - 4; j += 4 )
if( *((int*)(ptr+j)) )
break;
for( ; j < xmin; j++ )
if( ptr[j] )
{
xmin = j;
if( j > xmax )
xmax = j;
have_nz = 1;
break;
}
k_min = MAX(j-1, xmax);
k = size.width - 1;
for( ; k > k_min && (k&3) != 3; k-- )
if( ptr[k] )
break;
if( k > k_min && (k&3) == 3 )
{
for( ; k > k_min+3; k -= 4 )
if( *((int*)(ptr+k-3)) )
break;
}
for( ; k > k_min; k-- )
if( ptr[k] )
{
xmax = k;
have_nz = 1;
break;
}
if( !have_nz )
{
j &= ~3;
for( ; j <= k - 3; j += 4 )
if( *((int*)(ptr+j)) )
break;
for( ; j <= k; j++ )
if( ptr[j] )
{
have_nz = 1;
break;
}
}
xmin += offset;
xmax += offset;
size.width += offset;
}
if( have_nz )
{
if( ymin < 0 )
ymin = i;
ymax = i;
}
}
if( xmin >= size.width )
xmin = ymin = 0;
return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
}
// Calculates bounding rectangle of a point set or retrieves already calculated
static Rect pointSetBoundingRect( const Mat& points )
{
int npoints = points.checkVector(2);
int depth = points.depth();
CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S));
int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i = 0;
bool is_float = depth == CV_32F;
if( npoints == 0 )
return Rect();
if( !is_float )
{
const int32_t* pts = points.ptr<int32_t>();
int64_t firstval = 0;
std::memcpy(&firstval, pts, sizeof(pts[0]) * 2);
xmin = xmax = pts[0];
ymin = ymax = pts[1];
#if CV_SIMD || CV_SIMD_SCALABLE
v_int32 minval, maxval;
minval = maxval = v_reinterpret_as_s32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y
const int nlanes = VTraits<v_int32>::vlanes()/2;
for (; i < npoints; i += nlanes)
{
if (i > npoints - nlanes)
{
if (i == 0)
break;
i = npoints - nlanes;
}
v_int32 ptXY2 = vx_load(pts + 2 * i);
minval = v_min(ptXY2, minval);
maxval = v_max(ptXY2, maxval);
}
constexpr int max_nlanes = VTraits<v_int32>::max_nlanes;
int arr_minval[max_nlanes], arr_maxval[max_nlanes];
vx_store(arr_minval, minval);
vx_store(arr_maxval, maxval);
for (int j = 0; j < nlanes; j++)
{
xmin = std::min(xmin, arr_minval[2*j]);
ymin = std::min(ymin, arr_minval[2*j+1]);
xmax = std::max(xmax, arr_maxval[2*j]);
ymax = std::max(ymax, arr_maxval[2*j+1]);
}
#endif
for( ; i < npoints; i++ )
{
int pt_x = pts[2*i];
int pt_y = pts[2*i+1];
xmin = std::min(xmin, pt_x);
xmax = std::max(xmax, pt_x);
ymin = std::min(ymin, pt_y);
ymax = std::max(ymax, pt_y);
}
}
else
{
const float* pts = points.ptr<float>();
int64_t firstval = 0;
std::memcpy(&firstval, pts, sizeof(pts[0]) * 2);
xmin = xmax = cvFloor(pts[0]);
ymin = ymax = cvFloor(pts[1]);
#if CV_SIMD || CV_SIMD_SCALABLE
v_float32 minval, maxval;
minval = maxval = v_reinterpret_as_f32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y
const int nlanes = VTraits<v_float32>::vlanes()/2;
for (; i < npoints; i += nlanes)
{
if (i > npoints - nlanes)
{
if (i == 0)
break;
i = npoints - nlanes;
}
v_float32 ptXY2 = vx_load(pts + 2 * i);
minval = v_min(ptXY2, minval);
maxval = v_max(ptXY2, maxval);
}
constexpr int max_nlanes = VTraits<v_int32>::max_nlanes;
float arr_minval[max_nlanes], arr_maxval[max_nlanes];
vx_store(arr_minval, minval);
vx_store(arr_maxval, maxval);
for (int j = 0; j < nlanes; j++)
{
int _xmin = cvFloor(arr_minval[2*j]), _ymin = cvFloor(arr_minval[2*j+1]);
int _xmax = cvFloor(arr_maxval[2*j]), _ymax = cvFloor(arr_maxval[2*j+1]);
xmin = std::min(xmin, _xmin);
ymin = std::min(ymin, _ymin);
xmax = std::max(xmax, _xmax);
ymax = std::max(ymax, _ymax);
}
#endif
for( ; i < npoints; i++ )
{
// because right and bottom sides of the bounding rectangle are not inclusive
// (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil
int pt_x = cvFloor(pts[2*i]);
int pt_y = cvFloor(pts[2*i+1]);
xmin = std::min(xmin, pt_x);
xmax = std::max(xmax, pt_x);
ymin = std::min(ymin, pt_y);
ymax = std::max(ymax, pt_y);
}
}
return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
}
cv::Rect cv::boundingRect(InputArray array)
{
CV_INSTRUMENT_REGION();
Mat m = array.getMat();
return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m);
}
@@ -90,8 +90,8 @@ static void fitLine2D_wods( const Point2f* points, int count, float *weights, fl
dxy = xy - x * y;
t = (float) atan2( 2 * dxy, dx2 - dy2 ) / 2;
line[0] = (float) cos( t );
line[1] = (float) sin( t );
line[0] = (float) std::cos( t );
line[1] = (float) std::sin( t );
line[2] = (float) x;
line[3] = (float) y;
@@ -394,7 +394,7 @@ static void fitLine2D( const Point2f * points, int count, int dist,
double t = _line[0] * _lineprev[0] + _line[1] * _lineprev[1];
t = MAX(t,-1.);
t = MIN(t,1.);
if( fabs(acos(t)) < adelta )
if( fabs(std::acos(t)) < adelta )
{
float x, y, d;
@@ -535,7 +535,7 @@ static void fitLine3D( Point3f * points, int count, int dist,
double t = _line[0] * _lineprev[0] + _line[1] * _lineprev[1] + _line[2] * _lineprev[2];
t = MAX(t,-1.);
t = MIN(t,1.);
if( fabs(acos(t)) < adelta )
if( fabs(std::acos(t)) < adelta )
{
float x, y, z, ax, ay, az, dx, dy, dz, d;
@@ -41,6 +41,7 @@
#include "precomp.hpp"
#include <vector>
#include <cmath>
/////////////////////////////////////////////////////////////////////////////////////////
// Default LSD parameters
@@ -450,7 +451,7 @@ void LineSegmentDetectorImpl::flsd(std::vector<Vec4f>& lines,
// Angle tolerance
const double prec = CV_PI * ANG_TH / 180;
const double p = ANG_TH / 180;
const double rho = QUANT / sin(prec); // gradient magnitude threshold
const double rho = QUANT / std::sin(prec); // gradient magnitude threshold
if(SCALE != 1)
{
@@ -642,8 +643,8 @@ void LineSegmentDetectorImpl::region_grow(const Point2i& s, std::vector<RegionPo
reg.push_back(region_point);
// Update region's angle
sumdx += cos(float(angle));
sumdy += sin(float(angle));
sumdx += std::cos(float(angle));
sumdy += std::sin(float(angle));
// reg_angle is used in the isAligned, so it needs to be updates?
reg_angle = fastAtan2(sumdy, sumdx) * DEG_TO_RADS;
}
@@ -674,8 +675,8 @@ void LineSegmentDetectorImpl::region2rect(const std::vector<RegionPoint>& reg,
double theta = get_theta(reg, x, y, reg_angle, prec);
// Find length and width
double dx = cos(theta);
double dy = sin(theta);
double dx = std::cos(theta);
double dy = std::sin(theta);
double l_min = 0, l_max = 0, w_min = 0, w_max = 0;
for(size_t i = 0; i < reg.size(); ++i)
+1
View File
@@ -82,6 +82,7 @@
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <cmath>
#define GET_OPTIMIZED(func) (func)
@@ -237,75 +237,6 @@ void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radiu
}
}
// calculates length of a curve (e.g. contour perimeter)
double cv::arcLength( InputArray _curve, bool is_closed )
{
CV_INSTRUMENT_REGION();
Mat curve = _curve.getMat();
int count = curve.checkVector(2);
int depth = curve.depth();
CV_Assert( count >= 0 && (depth == CV_32F || depth == CV_32S));
double perimeter = 0;
int i;
if( count <= 1 )
return 0.;
bool is_float = depth == CV_32F;
int last = is_closed ? count-1 : 0;
const Point* pti = curve.ptr<Point>();
const Point2f* ptf = curve.ptr<Point2f>();
Point2f prev = is_float ? ptf[last] : Point2f((float)pti[last].x,(float)pti[last].y);
for( i = 0; i < count; i++ )
{
Point2f p = is_float ? ptf[i] : Point2f((float)pti[i].x,(float)pti[i].y);
float dx = p.x - prev.x, dy = p.y - prev.y;
perimeter += std::sqrt(dx*dx + dy*dy);
prev = p;
}
return perimeter;
}
// area of a whole sequence
double cv::contourArea( InputArray _contour, bool oriented )
{
CV_INSTRUMENT_REGION();
Mat contour = _contour.getMat();
int npoints = contour.checkVector(2);
int depth = contour.depth();
CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S));
if( npoints == 0 )
return 0.;
double a00 = 0;
bool is_float = depth == CV_32F;
const Point* ptsi = contour.ptr<Point>();
const Point2f* ptsf = contour.ptr<Point2f>();
Point2f prev = is_float ? ptsf[npoints-1] : Point2f((float)ptsi[npoints-1].x, (float)ptsi[npoints-1].y);
for( int i = 0; i < npoints; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
a00 += (double)prev.x * p.y - (double)prev.y * p.x;
prev = p;
}
a00 *= 0.5;
if( !oriented )
a00 = fabs(a00);
return a00;
}
namespace cv
{
@@ -442,7 +373,7 @@ static RotatedRect fitEllipseNoDirect( InputArray _points )
// store angle and radii
rp[4] = -0.5 * atan2(gfp[2], gfp[1] - gfp[0]); // convert from APP angle usage
if( fabs(gfp[2]) > min_eps )
t = gfp[2]/sin(-2.0 * rp[4]);
t = gfp[2]/std::sin(-2.0 * rp[4]);
else // ellipse is rotated by an integer multiple of pi/2
t = gfp[1] - gfp[0];
rp[2] = fabs(gfp[0] + gfp[1] - t);
@@ -598,6 +598,20 @@ TEST(Imgproc_minAreaRect, roundtrip_accuracy)
EXPECT_LT(std::abs(rect.angle - rect_out.angle), 1e-5);
}
TEST(Imgproc_PointPolygonTest, regression_10222)
{
vector<Point> contour;
contour.push_back(Point(0, 0));
contour.push_back(Point(0, 100000));
contour.push_back(Point(100000, 100000));
contour.push_back(Point(100000, 50000));
contour.push_back(Point(100000, 0));
const Point2f point(40000, 40000);
const double result = cv::pointPolygonTest(contour, point, false);
EXPECT_GT(result, 0) << "Desired result: point is inside polygon - actual result: point is not inside polygon";
}
TEST(Imgproc_minEnclosingTriangle, regression_17585)
{
const int N = 3;
@@ -416,4 +416,83 @@ TEST_F(Imgproc_LSD_Common, drawSegmentsEmpty)
);
}
///////////////////////////////////////////////////////////////////////////
TEST(Imgproc_fitLine_vector_3d, regression)
{
std::vector<Point3f> points_vector;
Point3f p21(4,4,4);
Point3f p22(8,8,8);
points_vector.push_back(p21);
points_vector.push_back(p22);
std::vector<float> line;
cv::fitLine(points_vector, line, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line.size(), (size_t)6);
}
TEST(Imgproc_fitLine_vector_2d, regression)
{
std::vector<Point2f> points_vector;
Point2f p21(4,4);
Point2f p22(8,8);
Point2f p23(16,16);
points_vector.push_back(p21);
points_vector.push_back(p22);
points_vector.push_back(p23);
std::vector<float> line;
cv::fitLine(points_vector, line, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line.size(), (size_t)4);
}
TEST(Imgproc_fitLine_Mat_2dC2, regression)
{
cv::Mat mat1 = Mat::zeros(3, 1, CV_32SC2);
std::vector<float> line1;
cv::fitLine(mat1, line1, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line1.size(), (size_t)4);
}
TEST(Imgproc_fitLine_Mat_2dC1, regression)
{
cv::Matx<int, 3, 2> mat2;
std::vector<float> line2;
cv::fitLine(mat2, line2, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line2.size(), (size_t)4);
}
TEST(Imgproc_fitLine_Mat_3dC3, regression)
{
cv::Mat mat1 = Mat::zeros(2, 1, CV_32SC3);
std::vector<float> line1;
cv::fitLine(mat1, line1, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line1.size(), (size_t)6);
}
TEST(Imgproc_fitLine_Mat_3dC1, regression)
{
cv::Mat mat2 = Mat::zeros(2, 3, CV_32SC1);
std::vector<float> line2;
cv::fitLine(mat2, line2, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line2.size(), (size_t)6);
}
}} // namespace
+1 -1
View File
@@ -19,7 +19,7 @@ ocv_add_dispatched_file_force_all("layers/cpu_kernels/transpose_kernels" AVX AVX
ocv_add_dispatched_file_force_all("layers/cpu_kernels/gridsample_kernels" AVX AVX2 NEON RVV LASX)
ocv_add_dispatched_file_force_all("layers/cpu_kernels/nary_eltwise_kernels" AVX AVX2 NEON RVV LASX)
ocv_add_module(dnn opencv_core opencv_imgproc WRAP python java objc js)
ocv_add_module(dnn opencv_core opencv_imgproc opencv_3d WRAP python java objc js)
include(${CMAKE_CURRENT_LIST_DIR}/cmake/plugin.cmake)
+1
View File
@@ -10,6 +10,7 @@
#include <iterator>
#include <opencv2/imgproc.hpp>
#include <opencv2/3d.hpp>
namespace cv {
namespace dnn {
+1
View File
@@ -9,6 +9,7 @@
#include "nms.inl.hpp"
#include <opencv2/imgproc.hpp>
#include <opencv2/3d.hpp>
namespace cv { namespace dnn {
CV__DNN_INLINE_NS_BEGIN
+1
View File
@@ -14,6 +14,7 @@
#include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/3d.hpp>
#ifdef _WIN32
#ifndef NOMINMAX
+1
View File
@@ -4,6 +4,7 @@
#include "test_precomp.hpp"
#include <opencv2/dnn/shape_utils.hpp>
#include <opencv2/3d.hpp>
#include "npy_blob.hpp"
#include <map>
#include <set>
+1 -1
View File
@@ -6,7 +6,7 @@ set(debug_modules "")
if(DEBUG_opencv_features)
list(APPEND debug_modules opencv_highgui)
endif()
ocv_define_module(features opencv_imgproc ${debug_modules} OPTIONAL opencv_flann WRAP java objc python js)
ocv_define_module(features opencv_imgproc opencv_3d ${debug_modules} OPTIONAL opencv_flann WRAP java objc python js)
ocv_install_3rdparty_licenses(mscr "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/mscr/chi_table_LICENSE.txt")
ocv_install_3rdparty_licenses(annoylib "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/annoy/LICENSE")
+1
View File
@@ -47,6 +47,7 @@
#include "precomp.hpp"
#include <iostream>
namespace cv {
class AffineFeature_Impl CV_FINAL : public AffineFeature
+1
View File
@@ -45,6 +45,7 @@
#include "opencv2/features.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/3d.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
+43 -837
View File
@@ -490,14 +490,6 @@ enum HoughModes {
HOUGH_GRADIENT_ALT = 4, //!< variation of HOUGH_GRADIENT to get better accuracy
};
//! Variants of Line Segment %Detector
enum LineSegmentDetectorModes {
LSD_REFINE_NONE = 0, //!< No refinement applied
LSD_REFINE_STD = 1, //!< Standard refinement is applied. E.g. breaking arches into smaller straighter line approximations.
LSD_REFINE_ADV = 2 //!< Advanced refinement. Number of false alarms is calculated, lines are
//!< refined through increase of precision, decrement in size, etc.
};
//! @} imgproc_feature
/** Histogram comparison methods
@@ -882,13 +874,6 @@ enum ColorConversionCodes {
//! @addtogroup imgproc_shape
//! @{
//! types of intersection between rectangles
enum RectanglesIntersectTypes {
INTERSECT_NONE = 0, //!< No intersection
INTERSECT_PARTIAL = 1, //!< There is a partial intersection
INTERSECT_FULL = 2 //!< One of the rectangle is fully enclosed in the other
};
/** types of line
@ingroup imgproc_draw
*/
@@ -1087,370 +1072,6 @@ public:
//! @} imgproc_hist
//! @addtogroup imgproc_subdiv2d
//! @{
class CV_EXPORTS_W Subdiv2D
{
public:
/** Subdiv2D point location cases */
enum { PTLOC_ERROR = -2, //!< Point location error
PTLOC_OUTSIDE_RECT = -1, //!< Point outside the subdivision bounding rect
PTLOC_INSIDE = 0, //!< Point inside some facet
PTLOC_VERTEX = 1, //!< Point coincides with one of the subdivision vertices
PTLOC_ON_EDGE = 2 //!< Point on some edge
};
/** Subdiv2D edge type navigation (see: getEdge()) */
enum { NEXT_AROUND_ORG = 0x00,
NEXT_AROUND_DST = 0x22,
PREV_AROUND_ORG = 0x11,
PREV_AROUND_DST = 0x33,
NEXT_AROUND_LEFT = 0x13,
NEXT_AROUND_RIGHT = 0x31,
PREV_AROUND_LEFT = 0x20,
PREV_AROUND_RIGHT = 0x02
};
/** creates an empty Subdiv2D object.
To create a new empty Delaunay subdivision you need to use the #initDelaunay function.
*/
CV_WRAP Subdiv2D();
/** @overload
@param rect Rectangle that includes all of the 2D points that are to be added to the subdivision.
The function creates an empty Delaunay subdivision where 2D points can be added using the function
insert() . All of the points to be added must be within the specified rectangle, otherwise a runtime
error is raised.
*/
CV_WRAP Subdiv2D(Rect rect);
/** @overload */
CV_WRAP Subdiv2D(Rect2f rect2f);
/** @overload
@brief Creates a new empty Delaunay subdivision
@param rect Rectangle that includes all of the 2D points that are to be added to the subdivision.
*/
CV_WRAP void initDelaunay(Rect rect);
/** @overload
@brief Creates a new empty Delaunay subdivision
@param rect Rectangle that includes all of the 2d points that are to be added to the subdivision.
*/
CV_WRAP_AS(initDelaunay2f) CV_WRAP void initDelaunay(Rect2f rect);
/** @brief Insert a single point into a Delaunay triangulation.
@param pt Point to insert.
The function inserts a single point into a subdivision and modifies the subdivision topology
appropriately. If a point with the same coordinates exists already, no new point is added.
@returns the ID of the point.
@note If the point is outside of the triangulation specified rect a runtime error is raised.
*/
CV_WRAP int insert(Point2f pt);
/** @brief Insert multiple points into a Delaunay triangulation.
@param ptvec Points to insert.
The function inserts a vector of points into a subdivision and modifies the subdivision topology
appropriately.
*/
CV_WRAP void insert(const std::vector<Point2f>& ptvec);
/** @brief Returns the location of a point within a Delaunay triangulation.
@param pt Point to locate.
@param edge Output edge that the point belongs to or is located to the right of it.
@param vertex Optional output vertex the input point coincides with.
The function locates the input point within the subdivision and gives one of the triangle edges
or vertices.
@returns an integer which specify one of the following five cases for point location:
- The point falls into some facet. The function returns #PTLOC_INSIDE and edge will contain one of
edges of the facet.
- The point falls onto the edge. The function returns #PTLOC_ON_EDGE and edge will contain this edge.
- The point coincides with one of the subdivision vertices. The function returns #PTLOC_VERTEX and
vertex will contain a pointer to the vertex.
- The point is outside the subdivision reference rectangle. The function returns #PTLOC_OUTSIDE_RECT
and no pointers are filled.
- One of input arguments is invalid. A runtime error is raised or, if silent or "parent" error
processing mode is selected, #PTLOC_ERROR is returned.
*/
CV_WRAP int locate(Point2f pt, CV_OUT int& edge, CV_OUT int& vertex);
/** @brief Finds the subdivision vertex closest to the given point.
@param pt Input point.
@param nearestPt Output subdivision vertex point.
The function is another function that locates the input point within the subdivision. It finds the
subdivision vertex that is the closest to the input point. It is not necessarily one of vertices
of the facet containing the input point, though the facet (located using locate() ) is used as a
starting point.
@returns vertex ID.
*/
CV_WRAP int findNearest(Point2f pt, CV_OUT Point2f* nearestPt = 0);
/** @brief Returns a list of all edges.
@param edgeList Output vector.
The function gives each edge as a 4 numbers vector, where each two are one of the edge
vertices. i.e. org_x = v[0], org_y = v[1], dst_x = v[2], dst_y = v[3].
*/
CV_WRAP void getEdgeList(CV_OUT std::vector<Vec4f>& edgeList) const;
/** @brief Returns a list of the leading edge ID connected to each triangle.
@param leadingEdgeList Output vector.
The function gives one edge ID for each triangle.
*/
CV_WRAP void getLeadingEdgeList(CV_OUT std::vector<int>& leadingEdgeList) const;
/** @brief Returns a list of all triangles.
@param triangleList Output vector.
The function gives each triangle as a 6 numbers vector, where each two are one of the triangle
vertices. i.e. p1_x = v[0], p1_y = v[1], p2_x = v[2], p2_y = v[3], p3_x = v[4], p3_y = v[5].
*/
CV_WRAP void getTriangleList(CV_OUT std::vector<Vec6f>& triangleList) const;
/** @brief Returns a list of all Voronoi facets.
@param idx Vector of vertices IDs to consider. For all vertices you can pass empty vector.
@param facetList Output vector of the Voronoi facets.
@param facetCenters Output vector of the Voronoi facets center points.
*/
CV_WRAP void getVoronoiFacetList(const std::vector<int>& idx, CV_OUT std::vector<std::vector<Point2f> >& facetList,
CV_OUT std::vector<Point2f>& facetCenters);
/** @brief Returns vertex location from vertex ID.
@param vertex vertex ID.
@param firstEdge Optional. The first edge ID which is connected to the vertex.
@returns vertex (x,y)
*/
CV_WRAP Point2f getVertex(int vertex, CV_OUT int* firstEdge = 0) const;
/** @brief Returns one of the edges related to the given edge.
@param edge Subdivision edge ID.
@param nextEdgeType Parameter specifying which of the related edges to return.
The following values are possible:
- NEXT_AROUND_ORG next around the edge origin ( eOnext on the picture below if e is the input edge)
- NEXT_AROUND_DST next around the edge vertex ( eDnext )
- PREV_AROUND_ORG previous around the edge origin (reversed eRnext )
- PREV_AROUND_DST previous around the edge destination (reversed eLnext )
- NEXT_AROUND_LEFT next around the left facet ( eLnext )
- NEXT_AROUND_RIGHT next around the right facet ( eRnext )
- PREV_AROUND_LEFT previous around the left facet (reversed eOnext )
- PREV_AROUND_RIGHT previous around the right facet (reversed eDnext )
![sample output](pics/quadedge.png)
@returns edge ID related to the input edge.
*/
CV_WRAP int getEdge( int edge, int nextEdgeType ) const;
/** @brief Returns next edge around the edge origin.
@param edge Subdivision edge ID.
@returns an integer which is next edge ID around the edge origin: eOnext on the
picture above if e is the input edge).
*/
CV_WRAP int nextEdge(int edge) const;
/** @brief Returns another edge of the same quad-edge.
@param edge Subdivision edge ID.
@param rotate Parameter specifying which of the edges of the same quad-edge as the input
one to return. The following values are possible:
- 0 - the input edge ( e on the picture below if e is the input edge)
- 1 - the rotated edge ( eRot )
- 2 - the reversed edge (reversed e (in green))
- 3 - the reversed rotated edge (reversed eRot (in green))
@returns one of the edges ID of the same quad-edge as the input edge.
*/
CV_WRAP int rotateEdge(int edge, int rotate) const;
CV_WRAP int symEdge(int edge) const;
/** @brief Returns the edge origin.
@param edge Subdivision edge ID.
@param orgpt Output vertex location.
@returns vertex ID.
*/
CV_WRAP int edgeOrg(int edge, CV_OUT Point2f* orgpt = 0) const;
/** @brief Returns the edge destination.
@param edge Subdivision edge ID.
@param dstpt Output vertex location.
@returns vertex ID.
*/
CV_WRAP int edgeDst(int edge, CV_OUT Point2f* dstpt = 0) const;
protected:
int newEdge();
void deleteEdge(int edge);
int newPoint(Point2f pt, bool isvirtual, int firstEdge = 0);
void deletePoint(int vtx);
void setEdgePoints( int edge, int orgPt, int dstPt );
void splice( int edgeA, int edgeB );
int connectEdges( int edgeA, int edgeB );
void swapEdges( int edge );
int isRightOf(Point2f pt, int edge) const;
void calcVoronoi();
void clearVoronoi();
void checkSubdiv() const;
struct CV_EXPORTS Vertex
{
Vertex();
Vertex(Point2f pt, bool isvirtual, int firstEdge=0);
bool isvirtual() const;
bool isfree() const;
int firstEdge;
int type;
Point2f pt;
};
struct CV_EXPORTS QuadEdge
{
QuadEdge();
QuadEdge(int edgeidx);
bool isfree() const;
int next[4];
int pt[4];
};
//! All of the vertices
std::vector<Vertex> vtx;
//! All of the edges
std::vector<QuadEdge> qedges;
int freeQEdge;
int freePoint;
bool validGeometry;
int recentEdge;
//! Top left corner of the bounding rect
Point2f topLeft;
//! Bottom right corner of the bounding rect
Point2f bottomRight;
};
//! @} imgproc_subdiv2d
//! @addtogroup imgproc_feature
//! @{
/** @example samples/cpp/snippets/lsd_lines.cpp
An example using the LineSegmentDetector
\image html building_lsd.png "Sample output image" width=434 height=300
*/
/** @brief Line segment detector class
following the algorithm described at @cite Rafael12 .
@note Implementation has been removed from OpenCV version 3.4.6 to 3.4.15 and version 4.1.0 to 4.5.3 due original code license conflict.
restored again after [Computation of a NFA](https://github.com/rafael-grompone-von-gioi/binomial_nfa) code published under the MIT license.
*/
class CV_EXPORTS_W LineSegmentDetector : public Algorithm
{
public:
/** @brief Finds lines in the input image.
This is the output of the default parameters of the algorithm on the above shown image.
![image](pics/building_lsd.png)
@param image A grayscale (CV_8UC1) input image. If only a roi needs to be selected, use:
`lsd_ptr-\>detect(image(roi), lines, ...); lines += Scalar(roi.x, roi.y, roi.x, roi.y);`
@param lines A vector of Vec4f elements specifying the beginning and ending point of a line. Where
Vec4f is (x1, y1, x2, y2), point 1 is the start, point 2 - end. Returned lines are strictly
oriented depending on the gradient.
@param width Vector of widths of the regions, where the lines are found. E.g. Width of line.
@param prec Vector of precisions with which the lines are found.
@param nfa Vector containing number of false alarms in the line region, with precision of 10%. The
bigger the value, logarithmically better the detection.
- -1 corresponds to 10 mean false alarms
- 0 corresponds to 1 mean false alarm
- 1 corresponds to 0.1 mean false alarms
This vector will be calculated only when the objects type is #LSD_REFINE_ADV.
*/
CV_WRAP virtual void detect(InputArray image, OutputArray lines,
OutputArray width = noArray(), OutputArray prec = noArray(),
OutputArray nfa = noArray()) = 0;
/** @brief Draws the line segments on a given image.
@param image The image, where the lines will be drawn. Should be bigger or equal to the image,
where the lines were found.
@param lines A vector of the lines that needed to be drawn.
*/
CV_WRAP virtual void drawSegments(InputOutputArray image, InputArray lines) = 0;
/** @brief Draws two groups of lines in blue and red, counting the non overlapping (mismatching) pixels.
@param size The size of the image, where lines1 and lines2 were found.
@param lines1 The first group of lines that needs to be drawn. It is visualized in blue color.
@param lines2 The second group of lines. They visualized in red color.
@param image Optional image, where the lines will be drawn. The image should be color(3-channel)
in order for lines1 and lines2 to be drawn in the above mentioned colors.
*/
CV_WRAP virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray image = noArray()) = 0;
virtual ~LineSegmentDetector() { }
};
/** @brief Creates a smart pointer to a LineSegmentDetector object and initializes it.
The LineSegmentDetector algorithm is defined using the standard values. Only advanced users may want
to edit those, as to tailor it for their own application.
@param refine The way found lines will be refined, see #LineSegmentDetectorModes
@param scale The scale of the image that will be used to find the lines. Range (0..1].
@param sigma_scale Sigma for Gaussian filter. It is computed as sigma = sigma_scale/scale.
@param quant Bound to the quantization error on the gradient norm.
@param ang_th Gradient angle tolerance in degrees.
@param log_eps Detection threshold: -log10(NFA) \> log_eps. Used only when advance refinement is chosen.
@param density_th Minimal density of aligned region points in the enclosing rectangle.
@param n_bins Number of bins in pseudo-ordering of gradient modulus.
*/
CV_EXPORTS_W Ptr<LineSegmentDetector> createLineSegmentDetector(
LineSegmentDetectorModes refine = LSD_REFINE_STD, double scale = 0.8,
double sigma_scale = 0.6, double quant = 2.0, double ang_th = 22.5,
double log_eps = 0, double density_th = 0.7, int n_bins = 1024);
//! @} imgproc_feature
//! @addtogroup imgproc_filter
//! @{
@@ -2576,50 +2197,50 @@ Mat getRotationMatrix2D(Point2f center, double angle, double scale)
}
/** @brief Calculates an affine transform from three pairs of the corresponding points.
The function calculates the \f$2 \times 3\f$ matrix of an affine transform so that:
\f[\begin{bmatrix} x'_i \\ y'_i \end{bmatrix} = \texttt{map_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f]
where
\f[dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2\f]
@param src Coordinates of triangle vertices in the source image.
@param dst Coordinates of the corresponding triangle vertices in the destination image.
@sa warpAffine, transform
*
* The function calculates the \f$2 \times 3\f$ matrix of an affine transform so that:
*
* \f[\begin{bmatrix} x'_i \\ y'_i \end{bmatrix} = \texttt{map_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f]
*
* where
*
* \f[dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2\f]
*
* @param src Coordinates of triangle vertices in the source image.
* @param dst Coordinates of the corresponding triangle vertices in the destination image.
*
* @sa warpAffine, transform
*/
CV_EXPORTS Mat getAffineTransform( const Point2f src[], const Point2f dst[] );
/** @brief Inverts an affine transformation.
The function computes an inverse affine transformation represented by \f$2 \times 3\f$ matrix M:
\f[\begin{bmatrix} a_{11} & a_{12} & b_1 \\ a_{21} & a_{22} & b_2 \end{bmatrix}\f]
The result is also a \f$2 \times 3\f$ matrix of the same type as M.
@param M Original affine transformation.
@param iM Output reverse affine transformation.
*
* The function computes an inverse affine transformation represented by \f$2 \times 3\f$ matrix M:
*
* \f[\begin{bmatrix} a_{11} & a_{12} & b_1 \\ a_{21} & a_{22} & b_2 \end{bmatrix}\f]
*
* The result is also a \f$2 \times 3\f$ matrix of the same type as M.
*
* @param M Original affine transformation.
* @param iM Output reverse affine transformation.
*/
CV_EXPORTS_W void invertAffineTransform( InputArray M, OutputArray iM );
/** @brief Calculates a perspective transform from four pairs of the corresponding points.
The function calculates the \f$3 \times 3\f$ matrix of a perspective transform so that:
\f[\begin{bmatrix} t_i x'_i \\ t_i y'_i \\ t_i \end{bmatrix} = \texttt{map_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f]
where
\f[dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2,3\f]
@param src Coordinates of quadrangle vertices in the source image.
@param dst Coordinates of the corresponding quadrangle vertices in the destination image.
@param solveMethod method passed to cv::solve (#DecompTypes)
@sa findHomography, warpPerspective, perspectiveTransform
*
* The function calculates the \f$3 \times 3\f$ matrix of a perspective transform so that:
*
* \f[\begin{bmatrix} t_i x'_i \\ t_i y'_i \\ t_i \end{bmatrix} = \texttt{map_matrix} \cdot \begin{bmatrix} x_i \\ y_i \\ 1 \end{bmatrix}\f]
*
* where
*
* \f[dst(i)=(x'_i,y'_i), src(i)=(x_i, y_i), i=0,1,2,3\f]
*
* @param src Coordinates of quadrangle vertices in the source image.
* @param dst Coordinates of the corresponding quadrangle vertices in the destination image.
* @param solveMethod method passed to cv::solve (#DecompTypes)
*
* @sa findHomography, warpPerspective, perspectiveTransform
*/
CV_EXPORTS_W Mat getPerspectiveTransform(InputArray src, InputArray dst, int solveMethod = DECOMP_LU);
@@ -3995,48 +3616,14 @@ CV_EXPORTS_W void findContoursLinkRuns(InputArray image, OutputArrayOfArrays con
//! @overload
CV_EXPORTS_W void findContoursLinkRuns(InputArray image, OutputArrayOfArrays contours);
/** @example samples/python/snippets/squares.py
An example using approxPolyDP function in python.
*/
/** @brief Approximates a polygonal curve(s) with the specified precision.
The function cv::approxPolyDP approximates a curve or a polygon with another curve/polygon with less
vertices so that the distance between them is less or equal to the specified precision. It uses the
Douglas-Peucker algorithm <https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm>
@param curve Input vector of a 2D point stored in std::vector or Mat
@param approxCurve Result of the approximation. The type should match the type of the input curve.
@param epsilon Parameter specifying the approximation accuracy. This is the maximum distance
between the original curve and its approximation.
@param closed If true, the approximated curve is closed (its first and last vertices are
connected). Otherwise, it is not closed.
/** @brief Calculates the up-right bounding rectangle of a point set or non-zero pixels of gray-scale image.
*
* The function calculates and returns the minimal up-right bounding rectangle for the specified point set or
* non-zero pixels of gray-scale image.
*
* @param array Input gray-scale image or 2D point set, stored in std::vector or Mat.
*/
CV_EXPORTS_W void approxPolyDP( InputArray curve,
OutputArray approxCurve,
double epsilon, bool closed );
/** @brief Approximates a polygon with a convex hull with a specified accuracy and number of sides.
The cv::approxPolyN function approximates a polygon with a convex hull
so that the difference between the contour area of the original contour and the new polygon is minimal.
It uses a greedy algorithm for contracting two vertices into one in such a way that the additional area is minimal.
Straight lines formed by each edge of the convex contour are drawn and the areas of the resulting triangles are considered.
Each vertex will lie either on the original contour or outside it.
The algorithm based on the paper @cite LowIlie2003 .
@param curve Input vector of a 2D points stored in std::vector or Mat, points must be float or integer.
@param approxCurve Result of the approximation. The type is vector of a 2D point (Point2f or Point) in std::vector or Mat.
@param nsides The parameter defines the number of sides of the result polygon.
@param epsilon_percentage defines the percentage of the maximum of additional area.
If it equals -1, it is not used. Otherwise algorithm stops if additional area is greater than contourArea(_curve) * percentage.
If additional area exceeds the limit, algorithm returns as many vertices as there were at the moment the limit was exceeded.
@param ensure_convex If it is true, algorithm creates a convex hull of input contour. Otherwise input vector should be convex.
*/
CV_EXPORTS_W void approxPolyN(InputArray curve, OutputArray approxCurve,
int nsides, float epsilon_percentage = -1.0,
bool ensure_convex = true);
CV_EXPORTS_W Rect boundingRect( InputArray array );
/** @brief Calculates a contour perimeter or a curve length.
@@ -4047,15 +3634,6 @@ The function computes a curve length or a closed contour perimeter.
*/
CV_EXPORTS_W double arcLength( InputArray curve, bool closed );
/** @brief Calculates the up-right bounding rectangle of a point set or non-zero pixels of gray-scale image.
The function calculates and returns the minimal up-right bounding rectangle for the specified point set or
non-zero pixels of gray-scale image.
@param array Input gray-scale image or 2D point set, stored in std::vector or Mat.
*/
CV_EXPORTS_W Rect boundingRect( InputArray array );
/** @brief Calculates a contour area.
The function computes a contour area. Similarly to moments , the area is computed using the Green
@@ -4088,378 +3666,6 @@ false, which means that the absolute value is returned.
*/
CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false );
/** @brief Finds a rotated rectangle of the minimum area enclosing the input 2D point set.
The function calculates and returns the minimum-area bounding rectangle (possibly rotated) for a
specified point set. The angle of rotation represents the angle between the line connecting the starting
and ending points (based on the clockwise order with greatest index for the corner with greatest \f$y\f$)
and the horizontal axis. This angle always falls between \f$[-90, 0)\f$ because, if the object
rotates more than a rect angle, the next edge is used to measure the angle. The starting and ending points change
as the object rotates.Developer should keep in mind that the returned RotatedRect can contain negative
indices when data is close to the containing Mat element boundary.
@param points Input vector of 2D points, stored in std::vector\<\> or Mat
*/
CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );
/** @brief Finds the four vertices of a rotated rect. Useful to draw the rotated rectangle.
The function finds the four vertices of a rotated rectangle. The four vertices are returned
in clockwise order starting from the point with greatest \f$y\f$. If two points have the
same \f$y\f$ coordinate the rightmost is the starting point. This function is useful to draw the
rectangle. In C++, instead of using this function, you can directly use RotatedRect::points method. Please
visit the @ref tutorial_bounding_rotated_ellipses "tutorial on Creating Bounding rotated boxes and ellipses
for contours" for more information.
@param box The input rotated rectangle. It may be the output of @ref minAreaRect.
@param points The output array of four vertices of rectangles.
*/
CV_EXPORTS_W void boxPoints(RotatedRect box, OutputArray points);
/** @brief Finds a circle of the minimum area enclosing a 2D point set.
The function finds the minimal enclosing circle of a 2D point set using an iterative algorithm.
@param points Input vector of 2D points, stored in std::vector\<\> or Mat
@param center Output center of the circle.
@param radius Output radius of the circle.
*/
CV_EXPORTS_W void minEnclosingCircle( InputArray points,
CV_OUT Point2f& center, CV_OUT float& radius );
/** @brief Finds a triangle of minimum area enclosing a 2D point set and returns its area.
The function finds a triangle of minimum area enclosing the given set of 2D points and returns its
area. The output for a given 2D point set is shown in the image below. 2D points are depicted in
*red* and the enclosing triangle in *yellow*.
![Sample output of the minimum enclosing triangle function](pics/minenclosingtriangle.png)
The implementation of the algorithm is based on O'Rourke's @cite ORourke86 and Klee and Laskowski's
@cite KleeLaskowski85 papers. O'Rourke provides a \f$\theta(n)\f$ algorithm for finding the minimal
enclosing triangle of a 2D convex polygon with n vertices. Since the #minEnclosingTriangle function
takes a 2D point set as input an additional preprocessing step of computing the convex hull of the
2D point set is required. The complexity of the #convexHull function is \f$O(n log(n))\f$ which is higher
than \f$\theta(n)\f$. Thus the overall complexity of the function is \f$O(n log(n))\f$.
@param points Input vector of 2D points with depth CV_32S or CV_32F, stored in std::vector\<\> or Mat
@param triangle Output vector of three 2D points defining the vertices of the triangle. The depth
of the OutputArray must be CV_32F.
*/
CV_EXPORTS_W double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle );
/**
@brief Finds a convex polygon of minimum area enclosing a 2D point set and returns its area.
This function takes a given set of 2D points and finds the enclosing polygon with k vertices and minimal
area. It takes the set of points and the parameter k as input and returns the area of the minimal
enclosing polygon.
The Implementation is based on a paper by Aggarwal, Chang and Yap @cite Aggarwal1985. They
provide a \f$\theta(n²log(n)log(k))\f$ algorithm for finding the minimal convex polygon with k
vertices enclosing a 2D convex polygon with n vertices (k < n). Since the #minEnclosingConvexPolygon
function takes a 2D point set as input, an additional preprocessing step of computing the convex hull
of the 2D point set is required. The complexity of the #convexHull function is \f$O(n log(n))\f$ which
is lower than \f$\theta(n²log(n)log(k))\f$. Thus the overall complexity of the function is
\f$O(n²log(n)log(k))\f$.
@param points Input vector of 2D points, stored in std::vector\<\> or Mat
@param polygon Output vector of 2D points defining the vertices of the enclosing polygon
@param k Number of vertices of the output polygon
*/
CV_EXPORTS_W double minEnclosingConvexPolygon ( InputArray points, OutputArray polygon, int k );
/** @brief Compares two shapes.
The function compares two shapes. All three implemented methods use the Hu invariants (see #HuMoments)
@param contour1 First contour or grayscale image.
@param contour2 Second contour or grayscale image.
@param method Comparison method, see #ShapeMatchModes
@param parameter Method-specific parameter (not supported now).
*/
CV_EXPORTS_W double matchShapes( InputArray contour1, InputArray contour2,
int method, double parameter );
/** @example samples/cpp/geometry.cpp
An example program illustrates the use of cv::convexHull, cv::fitEllipse, cv::minEnclosingTriangle, cv::minEnclosingCircle and cv::minAreaRect.
*/
/** @brief Finds the convex hull of a point set.
The function cv::convexHull finds the convex hull of a 2D point set using the Sklansky's algorithm @cite Sklansky82
that has *O(N logN)* complexity in the current implementation.
@param points Input 2D point set, stored in std::vector or Mat.
@param hull Output convex hull. It is either an integer vector of indices or vector of points. In
the first case, the hull elements are 0-based indices of the convex hull points in the original
array (since the set of convex hull points is a subset of the original point set). In the second
case, hull elements are the convex hull points themselves.
@param clockwise Orientation flag. If it is true, the output convex hull is oriented clockwise.
Otherwise, it is oriented counter-clockwise. The assumed coordinate system has its X axis pointing
to the right, and its Y axis pointing upwards.
@param returnPoints Operation flag. In case of a matrix, when the flag is true, the function
returns convex hull points. Otherwise, it returns indices of the convex hull points. When the
output array is std::vector, the flag is ignored, and the output depends on the type of the
vector: std::vector\<int\> implies returnPoints=false, std::vector\<Point\> implies
returnPoints=true.
@note `points` and `hull` should be different arrays, inplace processing isn't supported.
Check @ref tutorial_hull "the corresponding tutorial" for more details.
useful links:
https://www.learnopencv.com/convex-hull-using-opencv-in-python-and-c/
*/
CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull,
bool clockwise = false, bool returnPoints = true );
/** @brief Finds the convexity defects of a contour.
The figure below displays convexity defects of a hand contour:
![image](pics/defects.png)
@param contour Input contour.
@param convexhull Convex hull obtained using convexHull that should contain indices of the contour
points that make the hull.
@param convexityDefects The output vector of convexity defects. In C++ and the new Python/Java
interface each convexity defect is represented as 4-element integer vector (a.k.a. #Vec4i):
(start_index, end_index, farthest_pt_index, fixpt_depth), where indices are 0-based indices
in the original contour of the convexity defect beginning, end and the farthest point, and
fixpt_depth is fixed-point approximation (with 8 fractional bits) of the distance between the
farthest contour point and the hull. That is, to get the floating-point value of the depth will be
fixpt_depth/256.0.
*/
CV_EXPORTS_W void convexityDefects( InputArray contour, InputArray convexhull, OutputArray convexityDefects );
/** @brief Tests a contour convexity.
The function tests whether the input contour is convex or not. The contour must be simple, that is,
without self-intersections. Otherwise, the function output is undefined.
@param contour Input vector of 2D points, stored in std::vector\<\> or Mat
*/
CV_EXPORTS_W bool isContourConvex( InputArray contour );
/** @example samples/cpp/snippets/intersectExample.cpp
Examples of how intersectConvexConvex works
*/
/** @brief Finds intersection of two convex polygons
@param p1 First polygon
@param p2 Second polygon
@param p12 Output polygon describing the intersecting area
@param handleNested When true, an intersection is found if one of the polygons is fully enclosed in the other.
When false, no intersection is found. If the polygons share a side or the vertex of one polygon lies on an edge
of the other, they are not considered nested and an intersection will be found regardless of the value of handleNested.
@returns Area of intersecting polygon. May be negative, if algorithm has not converged, e.g. non-convex input.
@note intersectConvexConvex doesn't confirm that both polygons are convex and will return invalid results if they aren't.
*/
CV_EXPORTS_W float intersectConvexConvex( InputArray p1, InputArray p2,
OutputArray p12, bool handleNested = true );
/** @brief Fits an ellipse around a set of 2D points.
The function calculates the ellipse that fits (in a least-squares sense) a set of 2D points best of
all. It returns the rotated rectangle in which the ellipse is inscribed. The first algorithm described by @cite Fitzgibbon95
is used. Developer should keep in mind that it is possible that the returned
ellipse/rotatedRect data contains negative indices, due to the data points being close to the
border of the containing Mat element.
@param points Input 2D point set, stored in std::vector\<\> or Mat
@note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required.
@note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error.
*/
CV_EXPORTS_W RotatedRect fitEllipse( InputArray points );
/** @brief Fits an ellipse around a set of 2D points.
The function calculates the ellipse that fits a set of 2D points.
It returns the rotated rectangle in which the ellipse is inscribed.
The Approximate Mean Square (AMS) proposed by @cite Taubin1991 is used.
For an ellipse, this basis set is \f$ \chi= \left(x^2, x y, y^2, x, y, 1\right) \f$,
which is a set of six free coefficients \f$ A^T=\left\{A_{\text{xx}},A_{\text{xy}},A_{\text{yy}},A_x,A_y,A_0\right\} \f$.
However, to specify an ellipse, all that is needed is five numbers; the major and minor axes lengths \f$ (a,b) \f$,
the position \f$ (x_0,y_0) \f$, and the orientation \f$ \theta \f$. This is because the basis set includes lines,
quadratics, parabolic and hyperbolic functions as well as elliptical functions as possible fits.
If the fit is found to be a parabolic or hyperbolic function then the standard #fitEllipse method is used.
The AMS method restricts the fit to parabolic, hyperbolic and elliptical curves
by imposing the condition that \f$ A^T ( D_x^T D_x + D_y^T D_y) A = 1 \f$ where
the matrices \f$ Dx \f$ and \f$ Dy \f$ are the partial derivatives of the design matrix \f$ D \f$ with
respect to x and y. The matrices are formed row by row applying the following to
each of the points in the set:
\f{align*}{
D(i,:)&=\left\{x_i^2, x_i y_i, y_i^2, x_i, y_i, 1\right\} &
D_x(i,:)&=\left\{2 x_i,y_i,0,1,0,0\right\} &
D_y(i,:)&=\left\{0,x_i,2 y_i,0,1,0\right\}
\f}
The AMS method minimizes the cost function
\f{equation*}{
\epsilon ^2=\frac{ A^T D^T D A }{ A^T (D_x^T D_x + D_y^T D_y) A^T }
\f}
The minimum cost is found by solving the generalized eigenvalue problem.
\f{equation*}{
D^T D A = \lambda \left( D_x^T D_x + D_y^T D_y\right) A
\f}
@param points Input 2D point set, stored in std::vector\<\> or Mat
@note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required.
@note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error.
*/
CV_EXPORTS_W RotatedRect fitEllipseAMS( InputArray points );
/** @brief Fits an ellipse around a set of 2D points.
The function calculates the ellipse that fits a set of 2D points.
It returns the rotated rectangle in which the ellipse is inscribed.
The Direct least square (Direct) method by @cite oy1998NumericallySD is used.
For an ellipse, this basis set is \f$ \chi= \left(x^2, x y, y^2, x, y, 1\right) \f$,
which is a set of six free coefficients \f$ A^T=\left\{A_{\text{xx}},A_{\text{xy}},A_{\text{yy}},A_x,A_y,A_0\right\} \f$.
However, to specify an ellipse, all that is needed is five numbers; the major and minor axes lengths \f$ (a,b) \f$,
the position \f$ (x_0,y_0) \f$, and the orientation \f$ \theta \f$. This is because the basis set includes lines,
quadratics, parabolic and hyperbolic functions as well as elliptical functions as possible fits.
The Direct method confines the fit to ellipses by ensuring that \f$ 4 A_{xx} A_{yy}- A_{xy}^2 > 0 \f$.
The condition imposed is that \f$ 4 A_{xx} A_{yy}- A_{xy}^2=1 \f$ which satisfies the inequality
and as the coefficients can be arbitrarily scaled is not overly restrictive.
\f{equation*}{
\epsilon ^2= A^T D^T D A \quad \text{with} \quad A^T C A =1 \quad \text{and} \quad C=\left(\begin{matrix}
0 & 0 & 2 & 0 & 0 & 0 \\
0 & -1 & 0 & 0 & 0 & 0 \\
2 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0
\end{matrix} \right)
\f}
The minimum cost is found by solving the generalized eigenvalue problem.
\f{equation*}{
D^T D A = \lambda \left( C\right) A
\f}
The system produces only one positive eigenvalue \f$ \lambda\f$ which is chosen as the solution
with its eigenvector \f$\mathbf{u}\f$. These are used to find the coefficients
\f{equation*}{
A = \sqrt{\frac{1}{\mathbf{u}^T C \mathbf{u}}} \mathbf{u}
\f}
The scaling factor guarantees that \f$A^T C A =1\f$.
@param points Input 2D point set, stored in std::vector\<\> or Mat
@note Input point types are @ref Point2i or @ref Point2f and at least 5 points are required.
@note @ref getClosestEllipsePoints function can be used to compute the ellipse fitting error.
*/
CV_EXPORTS_W RotatedRect fitEllipseDirect( InputArray points );
/** @example samples/python/snippets/fitline.py
An example for fitting line in python
*/
/** @brief Compute for each 2d point the nearest 2d point located on a given ellipse.
The function computes the nearest 2d location on a given ellipse for a vector of 2d points and is based on @cite Chatfield2017 code.
This function can be used to compute for instance the ellipse fitting error.
@param ellipse_params Ellipse parameters
@param points Input 2d points
@param closest_pts For each 2d point, their corresponding closest 2d point located on a given ellipse
@note Input point types are @ref Point2i or @ref Point2f
@see fitEllipse, fitEllipseAMS, fitEllipseDirect
*/
CV_EXPORTS_W void getClosestEllipsePoints( const RotatedRect& ellipse_params, InputArray points, OutputArray closest_pts );
/** @brief Fits a line to a 2D or 3D point set.
The function fitLine fits a line to a 2D or 3D point set by minimizing \f$\sum_i \rho(r_i)\f$ where
\f$r_i\f$ is a distance between the \f$i^{th}\f$ point, the line and \f$\rho(r)\f$ is a distance function, one
of the following:
- DIST_L2
\f[\rho (r) = r^2/2 \quad \text{(the simplest and the fastest least-squares method)}\f]
- DIST_L1
\f[\rho (r) = r\f]
- DIST_L12
\f[\rho (r) = 2 \cdot ( \sqrt{1 + \frac{r^2}{2}} - 1)\f]
- DIST_FAIR
\f[\rho \left (r \right ) = C^2 \cdot \left ( \frac{r}{C} - \log{\left(1 + \frac{r}{C}\right)} \right ) \quad \text{where} \quad C=1.3998\f]
- DIST_WELSCH
\f[\rho \left (r \right ) = \frac{C^2}{2} \cdot \left ( 1 - \exp{\left(-\left(\frac{r}{C}\right)^2\right)} \right ) \quad \text{where} \quad C=2.9846\f]
- DIST_HUBER
\f[\rho (r) = \fork{r^2/2}{if \(r < C\)}{C \cdot (r-C/2)}{otherwise} \quad \text{where} \quad C=1.345\f]
The algorithm is based on the M-estimator ( <https://en.wikipedia.org/wiki/M-estimator> ) technique
that iteratively fits the line using the weighted least-squares algorithm. After each iteration the
weights \f$w_i\f$ are adjusted to be inversely proportional to \f$\rho(r_i)\f$ .
@param points Input vector of 2D or 3D points, stored in std::vector\<\> or Mat.
@param line Output line parameters. In case of 2D fitting, it should be a vector of 4 elements
(like Vec4f) - (vx, vy, x0, y0), where (vx, vy) is a normalized vector collinear to the line and
(x0, y0) is a point on the line. In case of 3D fitting, it should be a vector of 6 elements (like
Vec6f) - (vx, vy, vz, x0, y0, z0), where (vx, vy, vz) is a normalized vector collinear to the line
and (x0, y0, z0) is a point on the line.
@param distType Distance used by the M-estimator, see #DistanceTypes
@param param Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value
is chosen.
@param reps Sufficient accuracy for the radius (distance between the coordinate origin and the line).
@param aeps Sufficient accuracy for the angle. 0.01 would be a good default value for reps and aeps.
*/
CV_EXPORTS_W void fitLine( InputArray points, OutputArray line, int distType,
double param, double reps, double aeps );
/** @brief Performs a point-in-contour test.
The function determines whether the point is inside a contour, outside, or lies on an edge (or
coincides with a vertex). It returns positive (inside), negative (outside), or zero (on an edge)
value, correspondingly. When measureDist=false , the return value is +1, -1, and 0, respectively.
Otherwise, the return value is a signed distance between the point and the nearest contour edge.
See below a sample output of the function where each image pixel is tested against the contour:
![sample output](pics/pointpolygon.png)
@param contour Input contour.
@param pt Point tested against the contour.
@param measureDist If true, the function estimates the signed distance from the point to the
nearest contour edge. Otherwise, the function only checks if the point is inside a contour or not.
*/
CV_EXPORTS_W double pointPolygonTest( InputArray contour, Point2f pt, bool measureDist );
/** @brief Finds out if there is any intersection between two rotated rectangles.
If there is then the vertices of the intersecting region are returned as well.
Below are some examples of intersection configurations. The hatched pattern indicates the
intersecting region and the red vertices are returned by the function.
![intersection examples](pics/intersection.png)
@param rect1 First rectangle
@param rect2 Second rectangle
@param intersectingRegion The output array of the vertices of the intersecting region. It returns
at most 8 vertices. Stored as std::vector\<cv::Point2f\> or cv::Mat as Mx1 of type CV_32FC2.
@returns One of #RectanglesIntersectTypes
*/
CV_EXPORTS_W int rotatedRectangleIntersection( const RotatedRect& rect1, const RotatedRect& rect2, OutputArray intersectingRegion );
/** @brief Creates a smart pointer to a cv::GeneralizedHoughBallard class and initializes it.
*/
@@ -145,21 +145,6 @@ public class ImgprocTest extends OpenCVTestCase {
assertEquals(src.rows(), Core.countNonZero(dst));
}
public void testApproxPolyDP() {
MatOfPoint2f curve = new MatOfPoint2f(new Point(1, 3), new Point(2, 4), new Point(3, 5), new Point(4, 4), new Point(5, 3));
MatOfPoint2f approxCurve = new MatOfPoint2f();
Imgproc.approxPolyDP(curve, approxCurve, EPS, true);
List<Point> approxCurveGold = new ArrayList<Point>(3);
approxCurveGold.add(new Point(1, 3));
approxCurveGold.add(new Point(3, 5));
approxCurveGold.add(new Point(5, 3));
assertListPointEquals(approxCurve.toList(), approxCurveGold, EPS);
}
public void testArcLength() {
MatOfPoint2f curve = new MatOfPoint2f(new Point(1, 3), new Point(2, 4), new Point(3, 5), new Point(4, 4), new Point(5, 3));
@@ -412,65 +397,6 @@ public class ImgprocTest extends OpenCVTestCase {
assertMatEqual(truthMap2, dstmap2);
}
public void testConvexHullMatMat() {
MatOfPoint points = new MatOfPoint(
new Point(20, 0),
new Point(40, 0),
new Point(30, 20),
new Point(0, 20),
new Point(20, 10),
new Point(30, 10)
);
MatOfInt hull = new MatOfInt();
Imgproc.convexHull(points, hull);
MatOfInt expHull = new MatOfInt(
0, 1, 2, 3
);
assertMatEqual(expHull, hull.reshape(1, (int)hull.total()), EPS);
}
public void testConvexHullMatMatBooleanBoolean() {
MatOfPoint points = new MatOfPoint(
new Point(2, 0),
new Point(4, 0),
new Point(3, 2),
new Point(0, 2),
new Point(2, 1),
new Point(3, 1)
);
MatOfInt hull = new MatOfInt();
Imgproc.convexHull(points, hull, true);
MatOfInt expHull = new MatOfInt(
3, 2, 1, 0
);
assertMatEqual(expHull, hull.reshape(1, hull.cols()), EPS);
}
public void testConvexityDefects() {
MatOfPoint points = new MatOfPoint(
new Point(20, 0),
new Point(40, 0),
new Point(30, 20),
new Point(0, 20),
new Point(20, 10),
new Point(30, 10)
);
MatOfInt hull = new MatOfInt();
Imgproc.convexHull(points, hull);
MatOfInt4 convexityDefects = new MatOfInt4();
Imgproc.convexityDefects(points, hull, convexityDefects);
assertMatEqual(new MatOfInt4(3, 0, 5, 3620), convexityDefects.reshape(4, convexityDefects.cols()));
}
public void testCornerEigenValsAndVecsMatMatIntInt() {
fail("Not yet implemented");
// TODO: write better test
@@ -791,33 +717,6 @@ public class ImgprocTest extends OpenCVTestCase {
*/
}
public void testFitEllipse() {
MatOfPoint2f points = new MatOfPoint2f(new Point(0, 0), new Point(-1, 1), new Point(1, 1), new Point(1, -1), new Point(-1, -1));
RotatedRect rrect = new RotatedRect();
rrect = Imgproc.fitEllipse(points);
double FIT_ELLIPSE_CENTER_EPS = 0.01;
double FIT_ELLIPSE_SIZE_EPS = 0.4;
assertEquals(0.0, rrect.center.x, FIT_ELLIPSE_CENTER_EPS);
assertEquals(0.0, rrect.center.y, FIT_ELLIPSE_CENTER_EPS);
assertEquals(2.828, rrect.size.width, FIT_ELLIPSE_SIZE_EPS);
assertEquals(2.828, rrect.size.height, FIT_ELLIPSE_SIZE_EPS);
}
public void testFitLine() {
Mat points = new Mat(1, 4, CvType.CV_32FC2);
points.put(0, 0, 0, 0, 2, 3, 3, 4, 5, 8);
Mat linePoints = new Mat(4, 1, CvType.CV_32FC1);
linePoints.put(0, 0, 0.53198653, 0.84675282, 2.5, 3.75);
Imgproc.fitLine(points, dst, Imgproc.DIST_L12, 0, 0.01, 0.01);
assertMatEqual(linePoints, dst, EPS);
}
public void testFloodFillMatMatPointScalar() {
Mat mask = new Mat(matSize + 2, matSize + 2, CvType.CV_8U, new Scalar(0));
Mat img = gray0;
@@ -1243,16 +1142,6 @@ public class ImgprocTest extends OpenCVTestCase {
assertMatEqual(truth, dst, EPS);
}
public void testIsContourConvex() {
MatOfPoint contour1 = new MatOfPoint(new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(5, 4));
assertFalse(Imgproc.isContourConvex(contour1));
MatOfPoint contour2 = new MatOfPoint(new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(5, 6));
assertTrue(Imgproc.isContourConvex(contour2));
}
public void testLaplacianMatMatInt() {
Imgproc.Laplacian(gray0, dst, CvType.CV_8U);
@@ -1282,17 +1171,6 @@ public class ImgprocTest extends OpenCVTestCase {
assertMatEqual(truth, dst, EPS);
}
public void testMatchShapes() {
Mat contour1 = new Mat(1, 4, CvType.CV_32FC2);
Mat contour2 = new Mat(1, 4, CvType.CV_32FC2);
contour1.put(0, 0, 1, 1, 5, 1, 4, 3, 6, 2);
contour2.put(0, 0, 1, 1, 6, 1, 4, 1, 2, 5);
double distance = Imgproc.matchShapes(contour1, contour2, Imgproc.CONTOURS_MATCH_I1, 1);
assertEquals(2.81109697365334, distance, EPS);
}
public void testMatchTemplate() {
Mat image = new Mat(imgprocSz, imgprocSz, CvType.CV_8U);
Mat templ = new Mat(imgprocSz, imgprocSz, CvType.CV_8U);
@@ -1319,27 +1197,6 @@ public class ImgprocTest extends OpenCVTestCase {
// TODO_: write better test
}
public void testMinAreaRect() {
MatOfPoint2f points = new MatOfPoint2f(new Point(1, 1), new Point(5, 1), new Point(4, 3), new Point(6, 2));
RotatedRect rrect = Imgproc.minAreaRect(points);
assertEquals(new Size(2, 5), rrect.size);
assertEquals(-90., rrect.angle);
assertEquals(new Point(3.5, 2), rrect.center);
}
public void testMinEnclosingCircle() {
MatOfPoint2f points = new MatOfPoint2f(new Point(0, 0), new Point(-100, 0), new Point(0, -100), new Point(100, 0), new Point(0, 100));
Point actualCenter = new Point();
float[] radius = new float[1];
Imgproc.minEnclosingCircle(points, actualCenter, radius);
assertEquals(new Point(0, 0), actualCenter);
assertEquals(100.0f, radius[0], 1.0);
}
public void testMomentsMat() {
fail("Not yet implemented");
}
@@ -1389,15 +1246,6 @@ public class ImgprocTest extends OpenCVTestCase {
// TODO_: write better test
}
public void testPointPolygonTest() {
MatOfPoint2f contour = new MatOfPoint2f(new Point(0, 0), new Point(1, 3), new Point(3, 4), new Point(4, 3), new Point(2, 1));
double sign1 = Imgproc.pointPolygonTest(contour, new Point(2, 2), false);
assertEquals(1.0, sign1);
double sign2 = Imgproc.pointPolygonTest(contour, new Point(4, 4), true);
assertEquals(-Math.sqrt(0.5), sign2);
}
public void testPreCornerDetectMatMatInt() {
Mat src = new Mat(4, 4, CvType.CV_32F, new Scalar(1));
int ksize = 3;
-35
View File
@@ -106,41 +106,6 @@ PERF_TEST_P(TestBoundingRect, BoundingRect,
SANITY_CHECK_NOTHING();
}
typedef TestBaseWithParam< tuple<MatDepth, int> > TestMinEnclosingCircle;
PERF_TEST_P(TestMinEnclosingCircle, minEnclosingCircle,
Combine(
testing::Values(CV_32S, CV_32F),
Values(400, 1000, 10000, 100000)
))
{
int ptType = get<0>(GetParam());
int n = get<1>(GetParam());
Mat pts(n, 2, ptType);
declare.in(pts, WARMUP_RNG);
Point2f center;
float radius;
TEST_CYCLE() minEnclosingCircle(pts, center, radius);
SANITY_CHECK_NOTHING();
}
typedef TestBaseWithParam<int> TestMinEnclosingCircleWorstCase;
PERF_TEST_P(TestMinEnclosingCircleWorstCase, minEnclosingCircle_sequential,
Values(400, 1000, 5000, 10000))
{
int n = GetParam();
vector<Point2f> contour;
for(int i = 0; i < n; ++i) {
float angle = (float)(i * 2 * CV_PI / n);
contour.push_back(Point2f(cos(angle) * 100, sin(angle) * 100));
}
Point2f center;
float radius;
TEST_CYCLE() minEnclosingCircle(contour, center, radius);
SANITY_CHECK_NOTHING();
}
// ============================================================
// findTRUContours performance tests
// ============================================================
+280
View File
@@ -6,10 +6,290 @@
#include "contours_common.hpp"
#include <map>
#include <limits>
#include "opencv2/core/hal/intrin.hpp"
#include "opencv2/core/check.hpp"
using namespace std;
using namespace cv;
// calculates length of a curve (e.g. contour perimeter)
double cv::arcLength( InputArray _curve, bool is_closed )
{
CV_INSTRUMENT_REGION();
Mat curve = _curve.getMat();
int count = curve.checkVector(2);
int depth = curve.depth();
CV_Assert( count >= 0 && (depth == CV_32F || depth == CV_32S));
double perimeter = 0;
int i;
if( count <= 1 )
return 0.;
bool is_float = depth == CV_32F;
int last = is_closed ? count-1 : 0;
const Point* pti = curve.ptr<Point>();
const Point2f* ptf = curve.ptr<Point2f>();
Point2f prev = is_float ? ptf[last] : Point2f((float)pti[last].x,(float)pti[last].y);
for( i = 0; i < count; i++ )
{
Point2f p = is_float ? ptf[i] : Point2f((float)pti[i].x,(float)pti[i].y);
float dx = p.x - prev.x, dy = p.y - prev.y;
perimeter += std::sqrt(dx*dx + dy*dy);
prev = p;
}
return perimeter;
}
static Rect maskBoundingRect( const Mat& img )
{
CV_Assert( img.depth() <= CV_8S && img.channels() == 1 );
Size size = img.size();
int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k;
for( i = 0; i < size.height; i++ )
{
const uchar* _ptr = img.ptr(i);
const uchar* ptr = (const uchar*)alignPtr(_ptr, 4);
int have_nz = 0, k_min, offset = (int)(ptr - _ptr);
j = 0;
offset = MIN(offset, size.width);
for( ; j < offset; j++ )
if( _ptr[j] )
{
if( j < xmin )
xmin = j;
if( j > xmax )
xmax = j;
have_nz = 1;
}
if( offset < size.width )
{
xmin -= offset;
xmax -= offset;
size.width -= offset;
j = 0;
for( ; j <= xmin - 4; j += 4 )
if( *((int*)(ptr+j)) )
break;
for( ; j < xmin; j++ )
if( ptr[j] )
{
xmin = j;
if( j > xmax )
xmax = j;
have_nz = 1;
break;
}
k_min = MAX(j-1, xmax);
k = size.width - 1;
for( ; k > k_min && (k&3) != 3; k-- )
if( ptr[k] )
break;
if( k > k_min && (k&3) == 3 )
{
for( ; k > k_min+3; k -= 4 )
if( *((int*)(ptr+k-3)) )
break;
}
for( ; k > k_min; k-- )
if( ptr[k] )
{
xmax = k;
have_nz = 1;
break;
}
if( !have_nz )
{
j &= ~3;
for( ; j <= k - 3; j += 4 )
if( *((int*)(ptr+j)) )
break;
for( ; j <= k; j++ )
if( ptr[j] )
{
have_nz = 1;
break;
}
}
xmin += offset;
xmax += offset;
size.width += offset;
}
if( have_nz )
{
if( ymin < 0 )
ymin = i;
ymax = i;
}
}
if( xmin >= size.width )
xmin = ymin = 0;
return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
}
// Calculates bounding rectangle of a point set or retrieves already calculated
static Rect pointSetBoundingRect( const Mat& points )
{
int npoints = points.checkVector(2);
int depth = points.depth();
CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S));
int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i = 0;
bool is_float = depth == CV_32F;
if( npoints == 0 )
return Rect();
if( !is_float )
{
const int32_t* pts = points.ptr<int32_t>();
int64_t firstval = 0;
std::memcpy(&firstval, pts, sizeof(pts[0]) * 2);
xmin = xmax = pts[0];
ymin = ymax = pts[1];
#if CV_SIMD || CV_SIMD_SCALABLE
v_int32 minval, maxval;
minval = maxval = v_reinterpret_as_s32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y
const int nlanes = VTraits<v_int32>::vlanes()/2;
for (; i < npoints; i += nlanes)
{
if (i > npoints - nlanes)
{
if (i == 0)
break;
i = npoints - nlanes;
}
v_int32 ptXY2 = vx_load(pts + 2 * i);
minval = v_min(ptXY2, minval);
maxval = v_max(ptXY2, maxval);
}
constexpr int max_nlanes = VTraits<v_int32>::max_nlanes;
int arr_minval[max_nlanes], arr_maxval[max_nlanes];
vx_store(arr_minval, minval);
vx_store(arr_maxval, maxval);
for (int j = 0; j < nlanes; j++)
{
xmin = std::min(xmin, arr_minval[2*j]);
ymin = std::min(ymin, arr_minval[2*j+1]);
xmax = std::max(xmax, arr_maxval[2*j]);
ymax = std::max(ymax, arr_maxval[2*j+1]);
}
#endif
for( ; i < npoints; i++ )
{
int pt_x = pts[2*i];
int pt_y = pts[2*i+1];
xmin = std::min(xmin, pt_x);
xmax = std::max(xmax, pt_x);
ymin = std::min(ymin, pt_y);
ymax = std::max(ymax, pt_y);
}
}
else
{
const float* pts = points.ptr<float>();
int64_t firstval = 0;
std::memcpy(&firstval, pts, sizeof(pts[0]) * 2);
xmin = xmax = cvFloor(pts[0]);
ymin = ymax = cvFloor(pts[1]);
#if CV_SIMD || CV_SIMD_SCALABLE
v_float32 minval, maxval;
minval = maxval = v_reinterpret_as_f32(vx_setall_s64(firstval)); //min[0]=pt.x, min[1]=pt.y, min[2]=pt.x, min[3]=pt.y
const int nlanes = VTraits<v_float32>::vlanes()/2;
for (; i < npoints; i += nlanes)
{
if (i > npoints - nlanes)
{
if (i == 0)
break;
i = npoints - nlanes;
}
v_float32 ptXY2 = vx_load(pts + 2 * i);
minval = v_min(ptXY2, minval);
maxval = v_max(ptXY2, maxval);
}
constexpr int max_nlanes = VTraits<v_int32>::max_nlanes;
float arr_minval[max_nlanes], arr_maxval[max_nlanes];
vx_store(arr_minval, minval);
vx_store(arr_maxval, maxval);
for (int j = 0; j < nlanes; j++)
{
int _xmin = cvFloor(arr_minval[2*j]), _ymin = cvFloor(arr_minval[2*j+1]);
int _xmax = cvFloor(arr_maxval[2*j]), _ymax = cvFloor(arr_maxval[2*j+1]);
xmin = std::min(xmin, _xmin);
ymin = std::min(ymin, _ymin);
xmax = std::max(xmax, _xmax);
ymax = std::max(ymax, _ymax);
}
#endif
for( ; i < npoints; i++ )
{
// because right and bottom sides of the bounding rectangle are not inclusive
// (note +1 in width and height calculation below), cvFloor is used here instead of cvCeil
int pt_x = cvFloor(pts[2*i]);
int pt_y = cvFloor(pts[2*i+1]);
xmin = std::min(xmin, pt_x);
xmax = std::max(xmax, pt_x);
ymin = std::min(ymin, pt_y);
ymax = std::max(ymax, pt_y);
}
}
return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
}
cv::Rect cv::boundingRect(InputArray array)
{
CV_INSTRUMENT_REGION();
Mat m = array.getMat();
return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m);
}
// area of a whole sequence
double cv::contourArea( InputArray _contour, bool oriented )
{
CV_INSTRUMENT_REGION();
Mat contour = _contour.getMat();
int npoints = contour.checkVector(2);
int depth = contour.depth();
CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_32S));
if( npoints == 0 )
return 0.;
double a00 = 0;
bool is_float = depth == CV_32F;
const Point* ptsi = contour.ptr<Point>();
const Point2f* ptsf = contour.ptr<Point2f>();
Point2f prev = is_float ? ptsf[npoints-1] : Point2f((float)ptsi[npoints-1].x, (float)ptsi[npoints-1].y);
for( int i = 0; i < npoints; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
a00 += (double)prev.x * p.y - (double)prev.y * p.x;
prev = p;
}
a00 *= 0.5;
if( !oriented )
a00 = fabs(a00);
return a00;
}
void cv::contourTreeToResults(CTree& tree,
int res_type,
OutputArrayOfArrays& _contours,
View File
-14
View File
@@ -208,20 +208,6 @@ TEST(Imgproc_DrawContours, regression_26264)
ASSERT_EQ(0, cvtest::norm(img2, img3, NORM_INF));
}
TEST(Imgproc_PointPolygonTest, regression_10222)
{
vector<Point> contour;
contour.push_back(Point(0, 0));
contour.push_back(Point(0, 100000));
contour.push_back(Point(100000, 100000));
contour.push_back(Point(100000, 50000));
contour.push_back(Point(100000, 0));
const Point2f point(40000, 40000);
const double result = cv::pointPolygonTest(contour, point, false);
EXPECT_GT(result, 0) << "Desired result: point is inside polygon - actual result: point is not inside polygon";
}
TEST(Imgproc_DrawContours, MatListOfMatIntScalarInt)
{
Mat gray0 = Mat::zeros(10, 10, CV_8U);
-79
View File
@@ -599,85 +599,6 @@ static void check_resize_area(const Mat& expected, const Mat& actual, double tol
ASSERT_EQ(0, cvtest::norm(one_channel_diff, cv::NORM_INF));
}
///////////////////////////////////////////////////////////////////////////
TEST(Imgproc_fitLine_vector_3d, regression)
{
std::vector<Point3f> points_vector;
Point3f p21(4,4,4);
Point3f p22(8,8,8);
points_vector.push_back(p21);
points_vector.push_back(p22);
std::vector<float> line;
cv::fitLine(points_vector, line, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line.size(), (size_t)6);
}
TEST(Imgproc_fitLine_vector_2d, regression)
{
std::vector<Point2f> points_vector;
Point2f p21(4,4);
Point2f p22(8,8);
Point2f p23(16,16);
points_vector.push_back(p21);
points_vector.push_back(p22);
points_vector.push_back(p23);
std::vector<float> line;
cv::fitLine(points_vector, line, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line.size(), (size_t)4);
}
TEST(Imgproc_fitLine_Mat_2dC2, regression)
{
cv::Mat mat1 = Mat::zeros(3, 1, CV_32SC2);
std::vector<float> line1;
cv::fitLine(mat1, line1, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line1.size(), (size_t)4);
}
TEST(Imgproc_fitLine_Mat_2dC1, regression)
{
cv::Matx<int, 3, 2> mat2;
std::vector<float> line2;
cv::fitLine(mat2, line2, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line2.size(), (size_t)4);
}
TEST(Imgproc_fitLine_Mat_3dC3, regression)
{
cv::Mat mat1 = Mat::zeros(2, 1, CV_32SC3);
std::vector<float> line1;
cv::fitLine(mat1, line1, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line1.size(), (size_t)6);
}
TEST(Imgproc_fitLine_Mat_3dC1, regression)
{
cv::Mat mat2 = Mat::zeros(2, 3, CV_32SC1);
std::vector<float> line2;
cv::fitLine(mat2, line2, DIST_L2, 0 ,0 ,0);
ASSERT_EQ(line2.size(), (size_t)6);
}
TEST(Imgproc_resize_area, regression)
{
static ushort input_data[16 * 16] = {
@@ -5,7 +5,7 @@
#include "../precomp.hpp"
#include "bardetect.hpp"
#include "opencv2/3d.hpp"
namespace cv {
namespace barcode {
+1 -1
View File
@@ -47,6 +47,7 @@
#include "opencv2/objdetect.hpp"
#include "opencv2/objdetect/barcode.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/3d.hpp"
#include <opencv2/core/utils/logger.hpp>
#include "opencv2/core/utility.hpp"
@@ -61,7 +62,6 @@ namespace cv {
int checkChessboardBinary(const Mat & img, const Size & size);
}
#endif
@@ -43,6 +43,7 @@
#include "test_chessboardgenerator.hpp"
#include <functional>
#include <numeric>
namespace opencv_test { namespace {
+1 -1
View File
@@ -4,7 +4,7 @@ if(HAVE_CUDA)
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations -Wshadow)
endif()
ocv_define_module(photo opencv_imgproc OPTIONAL opencv_cudaarithm opencv_cudaimgproc WRAP java objc python js)
ocv_define_module(photo opencv_imgproc opencv_3d OPTIONAL opencv_cudaarithm opencv_cudaimgproc WRAP java objc python js)
if(HAVE_CUDA AND ENABLE_CUDA_FIRST_CLASS_LANGUAGE AND HAVE_opencv_cudaarithm AND HAVE_opencv_cudaimgproc)
ocv_target_link_libraries(${the_module} PRIVATE CUDA::cudart${CUDA_LIB_EXT})
+1
View File
@@ -41,6 +41,7 @@
#include "precomp.hpp"
#include "opencv2/photo.hpp"
#include "opencv2/3d.hpp"
#include "seamless_cloning.hpp"
+1
View File
@@ -1,3 +1,4 @@
#include <opencv2/3d.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
+1
View File
@@ -16,6 +16,7 @@
*
*********************************************************************************/
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
@@ -4,6 +4,7 @@
* A program that illustrates intersectConvexConvex in various scenarios
*/
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
+1
View File
@@ -1,3 +1,4 @@
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
+1
View File
@@ -4,6 +4,7 @@
// each image
#include "opencv2/core.hpp"
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
@@ -6,6 +6,7 @@
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
@@ -6,6 +6,7 @@
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
@@ -6,6 +6,7 @@
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
@@ -5,6 +5,7 @@
*/
#include "opencv2/highgui.hpp"
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
+1
View File
@@ -2,6 +2,7 @@
#include "opencv2/core.hpp"
#include "opencv2/core/ocl.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"