From aac582119c54c50cc241d372ca5a2ff82d2ecf5b Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov <2536374+asmorkalov@users.noreply.github.com> Date: Thu, 28 May 2026 21:09:52 +0300 Subject: [PATCH] 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 --- doc/Doxyfile.in | 2 +- modules/3d/include/opencv2/3d.hpp | 1 + modules/3d/include/opencv2/3d/2d.hpp | 811 ++++++++++++++++ modules/3d/misc/java/test/Cv3dTest.java | 158 ++++ .../misc/java/test/Subdiv2DTest.java | 4 +- .../misc/objc/test/Subdiv2DTest.swift | 0 modules/3d/perf/perf_2d.cpp | 47 + modules/{imgproc => 3d}/src/approx.cpp | 0 modules/{imgproc => 3d}/src/convhull.cpp | 0 modules/{imgproc => 3d}/src/geometry.cpp | 211 ----- modules/{imgproc => 3d}/src/intersection.cpp | 0 modules/{imgproc => 3d}/src/linefit.cpp | 8 +- modules/{imgproc => 3d}/src/lsd.cpp | 11 +- modules/{imgproc => 3d}/src/matchcontours.cpp | 0 .../src/min_enclosing_convex_polygon.cpp | 0 .../src/min_enclosing_triangle.cpp | 0 modules/3d/src/precomp.hpp | 1 + modules/{imgproc => 3d}/src/rotcalipers.cpp | 0 modules/{imgproc => 3d}/src/shapedescr.cpp | 71 +- modules/{imgproc => 3d}/src/subdivision2d.cpp | 0 .../{imgproc => 3d}/test/test_approxpoly.cpp | 0 .../{imgproc => 3d}/test/test_convhull.cpp | 14 + .../{imgproc => 3d}/test/test_fitellipse.cpp | 0 .../test/test_fitellipse_ams.cpp | 0 .../test/test_fitellipse_direct.cpp | 0 .../test/test_intersectconvexconvex.cpp | 0 .../test/test_intersection.cpp | 0 modules/{imgproc => 3d}/test/test_lsd.cpp | 79 ++ .../test/test_subdivision2d.cpp | 0 modules/dnn/CMakeLists.txt | 2 +- modules/dnn/src/model.cpp | 1 + modules/dnn/src/nms.cpp | 1 + modules/dnn/test/test_common.impl.hpp | 1 + modules/dnn/test/test_model.cpp | 1 + modules/features/CMakeLists.txt | 2 +- modules/features/src/affine_feature.cpp | 1 + modules/features/src/precomp.hpp | 1 + modules/imgproc/include/opencv2/imgproc.hpp | 880 +----------------- .../imgproc/misc/java/test/ImgprocTest.java | 152 --- modules/imgproc/perf/perf_contours.cpp | 35 - modules/imgproc/src/contours_common.cpp | 280 ++++++ modules/imgproc/src/distransform.cpp | 0 modules/imgproc/test/test_contours.cpp | 14 - modules/imgproc/test/test_imgwarp.cpp | 79 -- .../src/barcode_detector/bardetect.cpp | 2 +- modules/objdetect/src/precomp.hpp | 2 +- modules/objdetect/test/test_chesscorners.cpp | 1 + modules/photo/CMakeLists.txt | 2 +- modules/photo/src/seamless_cloning.cpp | 1 + samples/cpp/delaunay2.cpp | 1 + samples/cpp/geometry.cpp | 1 + samples/cpp/snippets/intersectExample.cpp | 1 + samples/cpp/snippets/lsd_lines.cpp | 1 + samples/cpp/snippets/squares.cpp | 1 + .../generalContours_demo1.cpp | 1 + .../generalContours_demo2.cpp | 1 + .../ShapeDescriptors/hull_demo.cpp | 1 + .../pointPolygonTest_demo.cpp | 1 + samples/tapi/squares.cpp | 1 + 59 files changed, 1471 insertions(+), 1415 deletions(-) create mode 100644 modules/3d/include/opencv2/3d/2d.hpp rename modules/{imgproc => 3d}/misc/java/test/Subdiv2DTest.java (97%) rename modules/{imgproc => 3d}/misc/objc/test/Subdiv2DTest.swift (100%) create mode 100644 modules/3d/perf/perf_2d.cpp rename modules/{imgproc => 3d}/src/approx.cpp (100%) rename modules/{imgproc => 3d}/src/convhull.cpp (100%) rename modules/{imgproc => 3d}/src/geometry.cpp (72%) rename modules/{imgproc => 3d}/src/intersection.cpp (100%) rename modules/{imgproc => 3d}/src/linefit.cpp (98%) rename modules/{imgproc => 3d}/src/lsd.cpp (99%) rename modules/{imgproc => 3d}/src/matchcontours.cpp (100%) rename modules/{imgproc => 3d}/src/min_enclosing_convex_polygon.cpp (100%) rename modules/{imgproc => 3d}/src/min_enclosing_triangle.cpp (100%) rename modules/{imgproc => 3d}/src/rotcalipers.cpp (100%) rename modules/{imgproc => 3d}/src/shapedescr.cpp (94%) rename modules/{imgproc => 3d}/src/subdivision2d.cpp (100%) rename modules/{imgproc => 3d}/test/test_approxpoly.cpp (100%) rename modules/{imgproc => 3d}/test/test_convhull.cpp (98%) rename modules/{imgproc => 3d}/test/test_fitellipse.cpp (100%) rename modules/{imgproc => 3d}/test/test_fitellipse_ams.cpp (100%) rename modules/{imgproc => 3d}/test/test_fitellipse_direct.cpp (100%) rename modules/{imgproc => 3d}/test/test_intersectconvexconvex.cpp (100%) rename modules/{imgproc => 3d}/test/test_intersection.cpp (100%) rename modules/{imgproc => 3d}/test/test_lsd.cpp (87%) rename modules/{imgproc => 3d}/test/test_subdivision2d.cpp (100%) mode change 100755 => 100644 modules/imgproc/src/distransform.cpp diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 3556360cba..f34c040810 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -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 diff --git a/modules/3d/include/opencv2/3d.hpp b/modules/3d/include/opencv2/3d.hpp index dfdecd2b59..fabfdea4d2 100644 --- a/modules/3d/include/opencv2/3d.hpp +++ b/modules/3d/include/opencv2/3d.hpp @@ -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" diff --git a/modules/3d/include/opencv2/3d/2d.hpp b/modules/3d/include/opencv2/3d/2d.hpp new file mode 100644 index 0000000000..95378f7d7a --- /dev/null +++ b/modules/3d/include/opencv2/3d/2d.hpp @@ -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& 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& 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& 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& 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& idx, CV_OUT std::vector >& facetList, + CV_OUT std::vector& 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 vtx; + //! All of the edges + std::vector 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 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 + + @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\ implies returnPoints=false, std::vector\ 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 ( ) 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\ 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 diff --git a/modules/3d/misc/java/test/Cv3dTest.java b/modules/3d/misc/java/test/Cv3dTest.java index cb58814940..a360522b91 100644 --- a/modules/3d/misc/java/test/Cv3dTest.java +++ b/modules/3d/misc/java/test/Cv3dTest.java @@ -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 approxCurveGold = new ArrayList(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); + } } diff --git a/modules/imgproc/misc/java/test/Subdiv2DTest.java b/modules/3d/misc/java/test/Subdiv2DTest.java similarity index 97% rename from modules/imgproc/misc/java/test/Subdiv2DTest.java rename to modules/3d/misc/java/test/Subdiv2DTest.java index ea82032ef3..dd0f4e4749 100644 --- a/modules/imgproc/misc/java/test/Subdiv2DTest.java +++ b/modules/3d/misc/java/test/Subdiv2DTest.java @@ -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 { diff --git a/modules/imgproc/misc/objc/test/Subdiv2DTest.swift b/modules/3d/misc/objc/test/Subdiv2DTest.swift similarity index 100% rename from modules/imgproc/misc/objc/test/Subdiv2DTest.swift rename to modules/3d/misc/objc/test/Subdiv2DTest.swift diff --git a/modules/3d/perf/perf_2d.cpp b/modules/3d/perf/perf_2d.cpp new file mode 100644 index 0000000000..75615a0192 --- /dev/null +++ b/modules/3d/perf/perf_2d.cpp @@ -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 > 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 TestMinEnclosingCircleWorstCase; +PERF_TEST_P(TestMinEnclosingCircleWorstCase, minEnclosingCircle_sequential, + Values(400, 1000, 5000, 10000)) +{ + int n = GetParam(); + vector 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 diff --git a/modules/imgproc/src/approx.cpp b/modules/3d/src/approx.cpp similarity index 100% rename from modules/imgproc/src/approx.cpp rename to modules/3d/src/approx.cpp diff --git a/modules/imgproc/src/convhull.cpp b/modules/3d/src/convhull.cpp similarity index 100% rename from modules/imgproc/src/convhull.cpp rename to modules/3d/src/convhull.cpp diff --git a/modules/imgproc/src/geometry.cpp b/modules/3d/src/geometry.cpp similarity index 72% rename from modules/imgproc/src/geometry.cpp rename to modules/3d/src/geometry.cpp index 8bef6668cd..c83022e1dd 100644 --- a/modules/imgproc/src/geometry.cpp +++ b/modules/3d/src/geometry.cpp @@ -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(); - 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::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::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(); - 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::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::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); -} diff --git a/modules/imgproc/src/intersection.cpp b/modules/3d/src/intersection.cpp similarity index 100% rename from modules/imgproc/src/intersection.cpp rename to modules/3d/src/intersection.cpp diff --git a/modules/imgproc/src/linefit.cpp b/modules/3d/src/linefit.cpp similarity index 98% rename from modules/imgproc/src/linefit.cpp rename to modules/3d/src/linefit.cpp index c39411d000..254dc40a4f 100644 --- a/modules/imgproc/src/linefit.cpp +++ b/modules/3d/src/linefit.cpp @@ -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; diff --git a/modules/imgproc/src/lsd.cpp b/modules/3d/src/lsd.cpp similarity index 99% rename from modules/imgproc/src/lsd.cpp rename to modules/3d/src/lsd.cpp index 483dcf6d7b..bbe9d11373 100644 --- a/modules/imgproc/src/lsd.cpp +++ b/modules/3d/src/lsd.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include +#include ///////////////////////////////////////////////////////////////////////////////////////// // Default LSD parameters @@ -450,7 +451,7 @@ void LineSegmentDetectorImpl::flsd(std::vector& 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& 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) diff --git a/modules/imgproc/src/matchcontours.cpp b/modules/3d/src/matchcontours.cpp similarity index 100% rename from modules/imgproc/src/matchcontours.cpp rename to modules/3d/src/matchcontours.cpp diff --git a/modules/imgproc/src/min_enclosing_convex_polygon.cpp b/modules/3d/src/min_enclosing_convex_polygon.cpp similarity index 100% rename from modules/imgproc/src/min_enclosing_convex_polygon.cpp rename to modules/3d/src/min_enclosing_convex_polygon.cpp diff --git a/modules/imgproc/src/min_enclosing_triangle.cpp b/modules/3d/src/min_enclosing_triangle.cpp similarity index 100% rename from modules/imgproc/src/min_enclosing_triangle.cpp rename to modules/3d/src/min_enclosing_triangle.cpp diff --git a/modules/3d/src/precomp.hpp b/modules/3d/src/precomp.hpp index 4e0f2b83a6..56701d0191 100755 --- a/modules/3d/src/precomp.hpp +++ b/modules/3d/src/precomp.hpp @@ -82,6 +82,7 @@ #include #include #include +#include #define GET_OPTIMIZED(func) (func) diff --git a/modules/imgproc/src/rotcalipers.cpp b/modules/3d/src/rotcalipers.cpp similarity index 100% rename from modules/imgproc/src/rotcalipers.cpp rename to modules/3d/src/rotcalipers.cpp diff --git a/modules/imgproc/src/shapedescr.cpp b/modules/3d/src/shapedescr.cpp similarity index 94% rename from modules/imgproc/src/shapedescr.cpp rename to modules/3d/src/shapedescr.cpp index 764b0a6d7a..dbb27d953e 100644 --- a/modules/imgproc/src/shapedescr.cpp +++ b/modules/3d/src/shapedescr.cpp @@ -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(); - const Point2f* ptf = curve.ptr(); - - 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(); - const Point2f* ptsf = contour.ptr(); - 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); diff --git a/modules/imgproc/src/subdivision2d.cpp b/modules/3d/src/subdivision2d.cpp similarity index 100% rename from modules/imgproc/src/subdivision2d.cpp rename to modules/3d/src/subdivision2d.cpp diff --git a/modules/imgproc/test/test_approxpoly.cpp b/modules/3d/test/test_approxpoly.cpp similarity index 100% rename from modules/imgproc/test/test_approxpoly.cpp rename to modules/3d/test/test_approxpoly.cpp diff --git a/modules/imgproc/test/test_convhull.cpp b/modules/3d/test/test_convhull.cpp similarity index 98% rename from modules/imgproc/test/test_convhull.cpp rename to modules/3d/test/test_convhull.cpp index 70b8beacdb..fcf48b23d2 100644 --- a/modules/imgproc/test/test_convhull.cpp +++ b/modules/3d/test/test_convhull.cpp @@ -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 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; diff --git a/modules/imgproc/test/test_fitellipse.cpp b/modules/3d/test/test_fitellipse.cpp similarity index 100% rename from modules/imgproc/test/test_fitellipse.cpp rename to modules/3d/test/test_fitellipse.cpp diff --git a/modules/imgproc/test/test_fitellipse_ams.cpp b/modules/3d/test/test_fitellipse_ams.cpp similarity index 100% rename from modules/imgproc/test/test_fitellipse_ams.cpp rename to modules/3d/test/test_fitellipse_ams.cpp diff --git a/modules/imgproc/test/test_fitellipse_direct.cpp b/modules/3d/test/test_fitellipse_direct.cpp similarity index 100% rename from modules/imgproc/test/test_fitellipse_direct.cpp rename to modules/3d/test/test_fitellipse_direct.cpp diff --git a/modules/imgproc/test/test_intersectconvexconvex.cpp b/modules/3d/test/test_intersectconvexconvex.cpp similarity index 100% rename from modules/imgproc/test/test_intersectconvexconvex.cpp rename to modules/3d/test/test_intersectconvexconvex.cpp diff --git a/modules/imgproc/test/test_intersection.cpp b/modules/3d/test/test_intersection.cpp similarity index 100% rename from modules/imgproc/test/test_intersection.cpp rename to modules/3d/test/test_intersection.cpp diff --git a/modules/imgproc/test/test_lsd.cpp b/modules/3d/test/test_lsd.cpp similarity index 87% rename from modules/imgproc/test/test_lsd.cpp rename to modules/3d/test/test_lsd.cpp index 5f31a15c21..951019997e 100644 --- a/modules/imgproc/test/test_lsd.cpp +++ b/modules/3d/test/test_lsd.cpp @@ -416,4 +416,83 @@ TEST_F(Imgproc_LSD_Common, drawSegmentsEmpty) ); } +/////////////////////////////////////////////////////////////////////////// + +TEST(Imgproc_fitLine_vector_3d, regression) +{ + std::vector points_vector; + + Point3f p21(4,4,4); + Point3f p22(8,8,8); + + points_vector.push_back(p21); + points_vector.push_back(p22); + + std::vector 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 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 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 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 mat2; + std::vector 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 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 line2; + + cv::fitLine(mat2, line2, DIST_L2, 0 ,0 ,0); + + ASSERT_EQ(line2.size(), (size_t)6); +} + }} // namespace diff --git a/modules/imgproc/test/test_subdivision2d.cpp b/modules/3d/test/test_subdivision2d.cpp similarity index 100% rename from modules/imgproc/test/test_subdivision2d.cpp rename to modules/3d/test/test_subdivision2d.cpp diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index 6b12bfddd7..df54e16e2e 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -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) diff --git a/modules/dnn/src/model.cpp b/modules/dnn/src/model.cpp index 404dafd250..5b1707b793 100644 --- a/modules/dnn/src/model.cpp +++ b/modules/dnn/src/model.cpp @@ -10,6 +10,7 @@ #include #include +#include namespace cv { namespace dnn { diff --git a/modules/dnn/src/nms.cpp b/modules/dnn/src/nms.cpp index c51a630558..0f9de33ba5 100644 --- a/modules/dnn/src/nms.cpp +++ b/modules/dnn/src/nms.cpp @@ -9,6 +9,7 @@ #include "nms.inl.hpp" #include +#include namespace cv { namespace dnn { CV__DNN_INLINE_NS_BEGIN diff --git a/modules/dnn/test/test_common.impl.hpp b/modules/dnn/test/test_common.impl.hpp index 74e1ce14aa..0889e93668 100644 --- a/modules/dnn/test/test_common.impl.hpp +++ b/modules/dnn/test/test_common.impl.hpp @@ -14,6 +14,7 @@ #include #include +#include #ifdef _WIN32 #ifndef NOMINMAX diff --git a/modules/dnn/test/test_model.cpp b/modules/dnn/test/test_model.cpp index bfb8aa6594..d9c994c793 100644 --- a/modules/dnn/test/test_model.cpp +++ b/modules/dnn/test/test_model.cpp @@ -4,6 +4,7 @@ #include "test_precomp.hpp" #include +#include #include "npy_blob.hpp" #include #include diff --git a/modules/features/CMakeLists.txt b/modules/features/CMakeLists.txt index b4fd86d881..a337e38104 100644 --- a/modules/features/CMakeLists.txt +++ b/modules/features/CMakeLists.txt @@ -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") diff --git a/modules/features/src/affine_feature.cpp b/modules/features/src/affine_feature.cpp index 0b5fea7a7f..798d20b382 100644 --- a/modules/features/src/affine_feature.cpp +++ b/modules/features/src/affine_feature.cpp @@ -47,6 +47,7 @@ #include "precomp.hpp" #include + namespace cv { class AffineFeature_Impl CV_FINAL : public AffineFeature diff --git a/modules/features/src/precomp.hpp b/modules/features/src/precomp.hpp index c7a13b4d82..4baa886fe1 100644 --- a/modules/features/src/precomp.hpp +++ b/modules/features/src/precomp.hpp @@ -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" diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 682da3c500..02ef55dc0c 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -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& 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& 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& 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& 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& idx, CV_OUT std::vector >& facetList, - CV_OUT std::vector& 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 vtx; - //! All of the edges - std::vector 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 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 - -@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\ implies returnPoints=false, std::vector\ 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 ( ) 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\ 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. */ diff --git a/modules/imgproc/misc/java/test/ImgprocTest.java b/modules/imgproc/misc/java/test/ImgprocTest.java index 836ddf575b..a91ad40dd0 100644 --- a/modules/imgproc/misc/java/test/ImgprocTest.java +++ b/modules/imgproc/misc/java/test/ImgprocTest.java @@ -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 approxCurveGold = new ArrayList(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; diff --git a/modules/imgproc/perf/perf_contours.cpp b/modules/imgproc/perf/perf_contours.cpp index 65e985e34a..5493a8b70d 100644 --- a/modules/imgproc/perf/perf_contours.cpp +++ b/modules/imgproc/perf/perf_contours.cpp @@ -106,41 +106,6 @@ PERF_TEST_P(TestBoundingRect, BoundingRect, SANITY_CHECK_NOTHING(); } -typedef TestBaseWithParam< tuple > 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 TestMinEnclosingCircleWorstCase; -PERF_TEST_P(TestMinEnclosingCircleWorstCase, minEnclosingCircle_sequential, - Values(400, 1000, 5000, 10000)) -{ - int n = GetParam(); - vector 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 // ============================================================ diff --git a/modules/imgproc/src/contours_common.cpp b/modules/imgproc/src/contours_common.cpp index 8fb1459fc9..1e85f1f571 100644 --- a/modules/imgproc/src/contours_common.cpp +++ b/modules/imgproc/src/contours_common.cpp @@ -6,10 +6,290 @@ #include "contours_common.hpp" #include #include +#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(); + const Point2f* ptf = curve.ptr(); + + 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(); + 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::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::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(); + 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::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::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(); + const Point2f* ptsf = contour.ptr(); + 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, diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp old mode 100755 new mode 100644 diff --git a/modules/imgproc/test/test_contours.cpp b/modules/imgproc/test/test_contours.cpp index 3fd3df8468..8b104e2815 100644 --- a/modules/imgproc/test/test_contours.cpp +++ b/modules/imgproc/test/test_contours.cpp @@ -208,20 +208,6 @@ TEST(Imgproc_DrawContours, regression_26264) ASSERT_EQ(0, cvtest::norm(img2, img3, NORM_INF)); } -TEST(Imgproc_PointPolygonTest, regression_10222) -{ - vector 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); diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index df2ea5e92a..cd70bf3581 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -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 points_vector; - - Point3f p21(4,4,4); - Point3f p22(8,8,8); - - points_vector.push_back(p21); - points_vector.push_back(p22); - - std::vector 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 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 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 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 mat2; - std::vector 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 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 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] = { diff --git a/modules/objdetect/src/barcode_detector/bardetect.cpp b/modules/objdetect/src/barcode_detector/bardetect.cpp index abb30bf547..4543c99242 100644 --- a/modules/objdetect/src/barcode_detector/bardetect.cpp +++ b/modules/objdetect/src/barcode_detector/bardetect.cpp @@ -5,7 +5,7 @@ #include "../precomp.hpp" #include "bardetect.hpp" - +#include "opencv2/3d.hpp" namespace cv { namespace barcode { diff --git a/modules/objdetect/src/precomp.hpp b/modules/objdetect/src/precomp.hpp index 9546892bda..588c19010f 100644 --- a/modules/objdetect/src/precomp.hpp +++ b/modules/objdetect/src/precomp.hpp @@ -47,6 +47,7 @@ #include "opencv2/objdetect.hpp" #include "opencv2/objdetect/barcode.hpp" #include "opencv2/imgproc.hpp" +#include "opencv2/3d.hpp" #include #include "opencv2/core/utility.hpp" @@ -61,7 +62,6 @@ namespace cv { int checkChessboardBinary(const Mat & img, const Size & size); - } #endif diff --git a/modules/objdetect/test/test_chesscorners.cpp b/modules/objdetect/test/test_chesscorners.cpp index 9570c22a6c..f8d4f7f20e 100644 --- a/modules/objdetect/test/test_chesscorners.cpp +++ b/modules/objdetect/test/test_chesscorners.cpp @@ -43,6 +43,7 @@ #include "test_chessboardgenerator.hpp" #include +#include namespace opencv_test { namespace { diff --git a/modules/photo/CMakeLists.txt b/modules/photo/CMakeLists.txt index 1d970f28f4..43795fab72 100644 --- a/modules/photo/CMakeLists.txt +++ b/modules/photo/CMakeLists.txt @@ -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}) diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index f9bced841c..529506bd96 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" +#include "opencv2/3d.hpp" #include "seamless_cloning.hpp" diff --git a/samples/cpp/delaunay2.cpp b/samples/cpp/delaunay2.cpp index 428804e31c..8b58343344 100644 --- a/samples/cpp/delaunay2.cpp +++ b/samples/cpp/delaunay2.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/samples/cpp/geometry.cpp b/samples/cpp/geometry.cpp index f88893c9e4..54825e28e8 100644 --- a/samples/cpp/geometry.cpp +++ b/samples/cpp/geometry.cpp @@ -16,6 +16,7 @@ * *********************************************************************************/ +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include diff --git a/samples/cpp/snippets/intersectExample.cpp b/samples/cpp/snippets/intersectExample.cpp index 187aebbea9..52135a1fad 100644 --- a/samples/cpp/snippets/intersectExample.cpp +++ b/samples/cpp/snippets/intersectExample.cpp @@ -4,6 +4,7 @@ * A program that illustrates intersectConvexConvex in various scenarios */ +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" diff --git a/samples/cpp/snippets/lsd_lines.cpp b/samples/cpp/snippets/lsd_lines.cpp index 3feed9cbc2..2840b485ba 100644 --- a/samples/cpp/snippets/lsd_lines.cpp +++ b/samples/cpp/snippets/lsd_lines.cpp @@ -1,3 +1,4 @@ +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" diff --git a/samples/cpp/snippets/squares.cpp b/samples/cpp/snippets/squares.cpp index 2ea824decd..a873429e12 100644 --- a/samples/cpp/snippets/squares.cpp +++ b/samples/cpp/snippets/squares.cpp @@ -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" diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp index 68fa2b97c5..8f3b5cb0be 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo1.cpp @@ -6,6 +6,7 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp index 81e5fd7588..72400209f3 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/generalContours_demo2.cpp @@ -6,6 +6,7 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp index 3b46f9e9b0..83a560c524 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/hull_demo.cpp @@ -6,6 +6,7 @@ #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include diff --git a/samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp b/samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp index e62dc8471b..236feaf9d9 100644 --- a/samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp +++ b/samples/cpp/tutorial_code/ShapeDescriptors/pointPolygonTest_demo.cpp @@ -5,6 +5,7 @@ */ #include "opencv2/highgui.hpp" +#include "opencv2/3d.hpp" #include "opencv2/imgproc.hpp" #include diff --git a/samples/tapi/squares.cpp b/samples/tapi/squares.cpp index 4cdce2251b..46ad775035 100644 --- a/samples/tapi/squares.cpp +++ b/samples/tapi/squares.cpp @@ -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"