mirror of
https://github.com/opencv/opencv.git
synced 2024-11-28 13:10:12 +08:00
326 lines
12 KiB
TeX
326 lines
12 KiB
TeX
|
\section{Planar Subdivisions}
|
||
|
|
||
|
\ifCPy
|
||
|
|
||
|
\cvclass{CvSubdiv2D}\label{CvSubdiv2D}
|
||
|
|
||
|
Planar subdivision.
|
||
|
|
||
|
\ifC
|
||
|
\begin{lstlisting}
|
||
|
#define CV_SUBDIV2D_FIELDS() \
|
||
|
CV_GRAPH_FIELDS() \
|
||
|
int quad_edges; \
|
||
|
int is_geometry_valid; \
|
||
|
CvSubdiv2DEdge recent_edge; \
|
||
|
CvPoint2D32f topleft; \
|
||
|
CvPoint2D32f bottomright;
|
||
|
|
||
|
typedef struct CvSubdiv2D
|
||
|
{
|
||
|
CV_SUBDIV2D_FIELDS()
|
||
|
}
|
||
|
CvSubdiv2D;
|
||
|
\end{lstlisting}
|
||
|
\else
|
||
|
\begin{description}
|
||
|
\cvarg{edges}{A \cross{CvSet} of \cross{CvSubdiv2DEdge}}
|
||
|
\end{description}
|
||
|
\fi
|
||
|
|
||
|
Planar subdivision is the subdivision of a plane into a set of
|
||
|
non-overlapped regions (facets) that cover the whole plane. The above
|
||
|
structure describes a subdivision built on a 2d point set, where the points
|
||
|
are linked together and form a planar graph, which, together with a few
|
||
|
edges connecting the exterior subdivision points (namely, convex hull points)
|
||
|
with infinity, subdivides a plane into facets by its edges.
|
||
|
|
||
|
For every subdivision there exists a dual subdivision in which facets and
|
||
|
points (subdivision vertices) swap their roles, that is, a facet is
|
||
|
treated as a vertex (called a virtual point below) of the dual subdivision and
|
||
|
the original subdivision vertices become facets. On the picture below
|
||
|
original subdivision is marked with solid lines and dual subdivision
|
||
|
with dotted lines.
|
||
|
|
||
|
\includegraphics[width=0.5\textwidth]{pics/subdiv.png}
|
||
|
|
||
|
OpenCV subdivides a plane into triangles using Delaunay's
|
||
|
algorithm. Subdivision is built iteratively starting from a dummy
|
||
|
triangle that includes all the subdivision points for sure. In this
|
||
|
case the dual subdivision is a Voronoi diagram of the input 2d point set. The
|
||
|
subdivisions can be used for the 3d piece-wise transformation of a plane,
|
||
|
morphing, fast location of points on the plane, building special graphs
|
||
|
(such as NNG,RNG) and so forth.
|
||
|
|
||
|
\ifC
|
||
|
\cvclass{CvQuadEdge2D}\label{CvQuadEdge2D}
|
||
|
|
||
|
Quad-edge of planar subdivision.
|
||
|
|
||
|
\begin{lstlisting}
|
||
|
/* one of edges within quad-edge, lower 2 bits is index (0..3)
|
||
|
and upper bits are quad-edge pointer */
|
||
|
typedef long CvSubdiv2DEdge;
|
||
|
|
||
|
/* quad-edge structure fields */
|
||
|
#define CV_QUADEDGE2D_FIELDS() \
|
||
|
int flags; \
|
||
|
struct CvSubdiv2DPoint* pt[4]; \
|
||
|
CvSubdiv2DEdge next[4];
|
||
|
|
||
|
typedef struct CvQuadEdge2D
|
||
|
{
|
||
|
CV_QUADEDGE2D_FIELDS()
|
||
|
}
|
||
|
CvQuadEdge2D;
|
||
|
|
||
|
\end{lstlisting}
|
||
|
|
||
|
Quad-edge is a basic element of subdivision containing four edges (e, eRot, reversed e and reversed eRot):
|
||
|
|
||
|
\includegraphics[width=0.5\textwidth]{pics/quadedge.png}
|
||
|
\fi
|
||
|
|
||
|
\cvclass{CvSubdiv2DPoint}\label{CvSubdiv2DPoint}
|
||
|
|
||
|
\ifC
|
||
|
Point of original or dual subdivision.
|
||
|
|
||
|
\begin{lstlisting}
|
||
|
#define CV_SUBDIV2D_POINT_FIELDS()\
|
||
|
int flags; \
|
||
|
CvSubdiv2DEdge first; \
|
||
|
CvPoint2D32f pt; \
|
||
|
int id;
|
||
|
|
||
|
#define CV_SUBDIV2D_VIRTUAL_POINT_FLAG (1 << 30)
|
||
|
|
||
|
typedef struct CvSubdiv2DPoint
|
||
|
{
|
||
|
CV_SUBDIV2D_POINT_FIELDS()
|
||
|
}
|
||
|
CvSubdiv2DPoint;
|
||
|
\end{lstlisting}
|
||
|
|
||
|
\begin{itemize}
|
||
|
\item[id] This integer can be used to index auxillary data associated with each vertex of the planar subdivision
|
||
|
\end{itemize}
|
||
|
\else
|
||
|
Point of original or dual subdivision.
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{first}{A connected \cross{CvSubdiv2DEdge}}
|
||
|
\cvarg{pt}{Position, as a \cross{CvPoint2D32f}}
|
||
|
\end{description}
|
||
|
|
||
|
\fi
|
||
|
|
||
|
\cvCPyFunc{CalcSubdivVoronoi2D}
|
||
|
Calculates the coordinates of Voronoi diagram cells.
|
||
|
|
||
|
\cvdefC{
|
||
|
void cvCalcSubdivVoronoi2D( \par CvSubdiv2D* subdiv );
|
||
|
}
|
||
|
\cvdefPy{CalcSubdivVoronoi2D(subdiv)-> None}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{subdiv}{Delaunay subdivision, in which all the points are already added}
|
||
|
\end{description}
|
||
|
|
||
|
The function calculates the coordinates
|
||
|
of virtual points. All virtual points corresponding to some vertex of the
|
||
|
original subdivision form (when connected together) a boundary of the Voronoi
|
||
|
cell at that point.
|
||
|
|
||
|
\cvCPyFunc{ClearSubdivVoronoi2D}
|
||
|
Removes all virtual points.
|
||
|
|
||
|
\cvdefC{
|
||
|
void cvClearSubdivVoronoi2D( CvSubdiv2D* subdiv );
|
||
|
}\cvdefPy{ClearSubdivVoronoi2D(subdiv)-> None}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{subdiv}{Delaunay subdivision}
|
||
|
\end{description}
|
||
|
|
||
|
The function removes all of the virtual points. It
|
||
|
is called internally in \cvCPyCross{CalcSubdivVoronoi2D} if the subdivision
|
||
|
was modified after previous call to the function.
|
||
|
|
||
|
|
||
|
\cvCPyFunc{CreateSubdivDelaunay2D}
|
||
|
Creates an empty Delaunay triangulation.
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2D* cvCreateSubdivDelaunay2D( \par CvRect rect,\par CvMemStorage* storage );
|
||
|
}\cvdefPy{CreateSubdivDelaunay2D(rect,storage)-> delaunay\_triangulation}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{rect}{Rectangle that includes all of the 2d points that are to be added to the subdivision}
|
||
|
\cvarg{storage}{Container for subdivision}
|
||
|
\end{description}
|
||
|
|
||
|
The function creates an empty Delaunay
|
||
|
subdivision, where 2d points can be added using the function
|
||
|
\cvCPyCross{SubdivDelaunay2DInsert}. All of the points to be added must be within
|
||
|
the specified rectangle, otherwise a runtime error will be raised.
|
||
|
|
||
|
Note that the triangulation is a single large triangle that covers the given rectangle. Hence the three vertices of this triangle are outside the rectangle \texttt{rect}.
|
||
|
|
||
|
\cvCPyFunc{FindNearestPoint2D}
|
||
|
Finds the closest subdivision vertex to the given point.
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2DPoint* cvFindNearestPoint2D( \par CvSubdiv2D* subdiv,\par CvPoint2D32f pt );
|
||
|
}\cvdefPy{FindNearestPoint2D(subdiv,pt)-> point}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{subdiv}{Delaunay or another subdivision}
|
||
|
\cvarg{pt}{Input point}
|
||
|
\end{description}
|
||
|
|
||
|
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
|
||
|
\cvCPyCross{Subdiv2DLocate}) is used as a starting
|
||
|
point. The function returns a pointer to the found subdivision vertex.
|
||
|
|
||
|
\cvCPyFunc{Subdiv2DEdgeDst}
|
||
|
Returns the edge destination.
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2DPoint* cvSubdiv2DEdgeDst( \par CvSubdiv2DEdge edge );
|
||
|
}
|
||
|
\cvdefPy{Subdiv2DEdgeDst(edge)-> point}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{edge}{Subdivision edge (not a quad-edge)}
|
||
|
\end{description}
|
||
|
|
||
|
The function returns the edge destination. The
|
||
|
returned pointer may be NULL if the edge is from dual subdivision and
|
||
|
the virtual point coordinates are not calculated yet. The virtual points
|
||
|
can be calculated using the function \cvCPyCross{CalcSubdivVoronoi2D}.
|
||
|
|
||
|
\cvCPyFunc{Subdiv2DGetEdge}
|
||
|
Returns one of the edges related to the given edge.
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2DEdge cvSubdiv2DGetEdge( CvSubdiv2DEdge edge, CvNextEdgeType type );
|
||
|
|
||
|
|
||
|
}\cvdefPy{Subdiv2DGetEdge(edge,type)-> CvSubdiv2DEdge}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{edge}{Subdivision edge (not a quad-edge)}
|
||
|
\cvarg{type}{Specifies which of the related edges to return, one of the following:}
|
||
|
\begin{description}
|
||
|
\cvarg{CV\_NEXT\_AROUND\_ORG}{next around the edge origin (\texttt{eOnext} on the picture below if \texttt{e} is the input edge)}
|
||
|
\cvarg{CV\_NEXT\_AROUND\_DST}{next around the edge vertex (\texttt{eDnext})}
|
||
|
\cvarg{CV\_PREV\_AROUND\_ORG}{previous around the edge origin (reversed \texttt{eRnext})}
|
||
|
\cvarg{CV\_PREV\_AROUND\_DST}{previous around the edge destination (reversed \texttt{eLnext})}
|
||
|
\cvarg{CV\_NEXT\_AROUND\_LEFT}{next around the left facet (\texttt{eLnext})}
|
||
|
\cvarg{CV\_NEXT\_AROUND\_RIGHT}{next around the right facet (\texttt{eRnext})}
|
||
|
\cvarg{CV\_PREV\_AROUND\_LEFT}{previous around the left facet (reversed \texttt{eOnext})}
|
||
|
\cvarg{CV\_PREV\_AROUND\_RIGHT}{previous around the right facet (reversed \texttt{eDnext})}
|
||
|
\end{description}
|
||
|
\end{description}
|
||
|
|
||
|
\includegraphics[width=0.5\textwidth]{pics/quadedge.png}
|
||
|
|
||
|
The function returns one of the edges related to the input edge.
|
||
|
|
||
|
\cvCPyFunc{Subdiv2DNextEdge}
|
||
|
Returns next edge around the edge origin
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2DEdge cvSubdiv2DNextEdge( CvSubdiv2DEdge edge );
|
||
|
}
|
||
|
\cvdefPy{Subdiv2DNextEdge(edge)-> CvSubdiv2DEdge}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{edge}{Subdivision edge (not a quad-edge)}
|
||
|
\end{description}
|
||
|
|
||
|
\includegraphics[width=0.5\textwidth]{pics/quadedge.png}
|
||
|
|
||
|
The function returns the next edge around the edge origin: \texttt{eOnext} on the picture above if \texttt{e} is the input edge)
|
||
|
|
||
|
\cvCPyFunc{Subdiv2DLocate}
|
||
|
Returns the location of a point within a Delaunay triangulation.
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2DPointLocation cvSubdiv2DLocate( \par CvSubdiv2D* subdiv,\par CvPoint2D32f pt,\par CvSubdiv2DEdge* edge,\par CvSubdiv2DPoint** vertex=NULL );
|
||
|
}
|
||
|
\cvdefPy{Subdiv2DLocate(subdiv, pt) -> (loc, where)}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{subdiv}{Delaunay or another subdivision}
|
||
|
\cvarg{pt}{The point to locate}
|
||
|
\cvC{\cvarg{edge}{The output edge the point falls onto or right to}}
|
||
|
\cvC{\cvarg{vertex}{Optional output vertex double pointer the input point coinsides with}}
|
||
|
\cvPy{\cvarg{loc}{The location of the point within the triangulation}}
|
||
|
\cvPy{\cvarg{where}{The edge or vertex. See below.}}
|
||
|
\end{description}
|
||
|
|
||
|
The function locates the input point within the subdivision. There are 5 cases:
|
||
|
|
||
|
\ifC
|
||
|
\begin{itemize}
|
||
|
\item The point falls into some facet. The function returns \texttt{CV\_PTLOC\_INSIDE} and \texttt{*edge} will contain one of edges of the facet.
|
||
|
\item The point falls onto the edge. The function returns \texttt{CV\_PTLOC\_ON\_EDGE} and \texttt{*edge} will contain this edge.
|
||
|
\item The point coincides with one of the subdivision vertices. The function returns \texttt{CV\_PTLOC\_VERTEX} and \texttt{*vertex} will contain a pointer to the vertex.
|
||
|
\item The point is outside the subdivsion reference rectangle. The function returns \texttt{CV\_PTLOC\_OUTSIDE\_RECT} and no pointers are filled.
|
||
|
\item One of input arguments is invalid. A runtime error is raised or, if silent or "parent" error processing mode is selected, \texttt{CV\_PTLOC\_ERROR} is returnd.
|
||
|
\end{itemize}
|
||
|
\fi
|
||
|
|
||
|
\ifPy
|
||
|
\begin{itemize}
|
||
|
\item The point falls into some facet. \texttt{loc} is \texttt{CV\_PTLOC\_INSIDE} and \texttt{where} is one of edges of the facet.
|
||
|
\item The point falls onto the edge. \texttt{loc} is \texttt{CV\_PTLOC\_ON\_EDGE} and \texttt{where} is the edge.
|
||
|
\item The point coincides with one of the subdivision vertices. \texttt{loc} is \texttt{CV\_PTLOC\_VERTEX} and \texttt{where} is the vertex.
|
||
|
\item The point is outside the subdivsion reference rectangle. \texttt{loc} is \texttt{CV\_PTLOC\_OUTSIDE\_RECT} and \texttt{where} is None.
|
||
|
\item One of input arguments is invalid. The function raises an exception.
|
||
|
\end{itemize}
|
||
|
\fi
|
||
|
|
||
|
\cvCPyFunc{Subdiv2DRotateEdge}
|
||
|
Returns another edge of the same quad-edge.
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2DEdge cvSubdiv2DRotateEdge( \par CvSubdiv2DEdge edge,\par int rotate );
|
||
|
}\cvdefPy{Subdiv2DRotateEdge(edge,rotate)-> CvSubdiv2DEdge}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{edge}{Subdivision edge (not a quad-edge)}
|
||
|
\cvarg{rotate}{Specifies which of the edges of the same quad-edge as the input one to return, one of the following:
|
||
|
\begin{description}
|
||
|
\cvarg{0}{the input edge (\texttt{e} on the picture below if \texttt{e} is the input edge)}
|
||
|
\cvarg{1}{the rotated edge (\texttt{eRot})}
|
||
|
\cvarg{2}{the reversed edge (reversed \texttt{e} (in green))}
|
||
|
\cvarg{3}{the reversed rotated edge (reversed \texttt{eRot} (in green))}
|
||
|
\end{description}}
|
||
|
\end{description}
|
||
|
|
||
|
\includegraphics[width=0.5\textwidth]{pics/quadedge.png}
|
||
|
|
||
|
The function returns one of the edges of the same quad-edge as the input edge.
|
||
|
|
||
|
\cvCPyFunc{SubdivDelaunay2DInsert}
|
||
|
Inserts a single point into a Delaunay triangulation.
|
||
|
|
||
|
\cvdefC{
|
||
|
CvSubdiv2DPoint* cvSubdivDelaunay2DInsert( \par CvSubdiv2D* subdiv,\par CvPoint2D32f pt);
|
||
|
}\cvdefPy{SubdivDelaunay2DInsert(subdiv,pt)-> point}
|
||
|
|
||
|
\begin{description}
|
||
|
\cvarg{subdiv}{Delaunay subdivision created by the function \cvCPyCross{CreateSubdivDelaunay2D}}
|
||
|
\cvarg{pt}{Inserted point}
|
||
|
\end{description}
|
||
|
|
||
|
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. The function returns a pointer to the allocated point. No virtual point coordinates are calculated at this stage.
|
||
|
|
||
|
\fi
|