Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
f8e9f65e
Commit
f8e9f65e
authored
Feb 07, 2011
by
Ilya Lysenkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added detection of asymmetric circles' pattern
parent
885cef76
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
672 additions
and
245 deletions
+672
-245
calib3d.hpp
modules/calib3d/include/opencv2/calib3d/calib3d.hpp
+3
-1
calibinit.cpp
modules/calib3d/src/calibinit.cpp
+22
-6
circlesgrid.cpp
modules/calib3d/src/circlesgrid.cpp
+471
-112
circlesgrid.hpp
modules/calib3d/src/circlesgrid.hpp
+104
-71
blobdetector.cpp
modules/features2d/src/blobdetector.cpp
+72
-55
No files found.
modules/calib3d/include/opencv2/calib3d/calib3d.hpp
View file @
f8e9f65e
...
@@ -543,10 +543,12 @@ CV_EXPORTS void drawChessboardCorners( Mat& image, Size patternSize,
...
@@ -543,10 +543,12 @@ CV_EXPORTS void drawChessboardCorners( Mat& image, Size patternSize,
const
vector
<
Point2f
>&
corners
,
const
vector
<
Point2f
>&
corners
,
bool
patternWasFound
);
bool
patternWasFound
);
enum
{
CALIB_CB_SYMMETRIC_GRID
=
1
,
CALIB_CB_ASYMMETRIC_GRID
=
2
};
//! finds circles' grid pattern of the specified size in the image
//! finds circles' grid pattern of the specified size in the image
CV_EXPORTS_W
bool
findCirclesGrid
(
const
Mat
&
image
,
Size
patternSize
,
CV_EXPORTS_W
bool
findCirclesGrid
(
const
Mat
&
image
,
Size
patternSize
,
CV_OUT
vector
<
Point2f
>&
centers
,
CV_OUT
vector
<
Point2f
>&
centers
,
int
flags
=
0
);
int
flags
=
CALIB_CB_SYMMETRIC_GRID
);
enum
enum
{
{
...
...
modules/calib3d/src/calibinit.cpp
View file @
f8e9f65e
...
@@ -1935,7 +1935,7 @@ void drawChessboardCorners( Mat& image, Size patternSize,
...
@@ -1935,7 +1935,7 @@ void drawChessboardCorners( Mat& image, Size patternSize,
}
}
bool
findCirclesGrid
(
const
Mat
&
image
,
Size
patternSize
,
bool
findCirclesGrid
(
const
Mat
&
image
,
Size
patternSize
,
vector
<
Point2f
>&
centers
,
int
)
vector
<
Point2f
>&
centers
,
int
flags
)
{
{
Ptr
<
SimpleBlobDetector
>
detector
=
new
SimpleBlobDetector
();
Ptr
<
SimpleBlobDetector
>
detector
=
new
SimpleBlobDetector
();
//Ptr<FeatureDetector> detector = new MserFeatureDetector();
//Ptr<FeatureDetector> detector = new MserFeatureDetector();
...
@@ -1944,7 +1944,7 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
...
@@ -1944,7 +1944,7 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
vector
<
Point2f
>
points
;
vector
<
Point2f
>
points
;
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
i
++
)
{
{
points
.
push_back
(
keypoints
[
i
].
pt
);
points
.
push_back
(
keypoints
[
i
].
pt
);
}
}
CirclesGridFinderParameters
parameters
;
CirclesGridFinderParameters
parameters
;
...
@@ -1954,8 +1954,13 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
...
@@ -1954,8 +1954,13 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
parameters
.
edgeGain
=
1
;
parameters
.
edgeGain
=
1
;
parameters
.
edgePenalty
=
-
0.6
f
;
parameters
.
edgePenalty
=
-
0.6
f
;
if
(
flags
&
CALIB_CB_ASYMMETRIC_GRID
)
parameters
.
gridType
=
CirclesGridFinderParameters
::
ASYMMETRIC_GRID
;
if
(
flags
&
CALIB_CB_SYMMETRIC_GRID
)
parameters
.
gridType
=
CirclesGridFinderParameters
::
SYMMETRIC_GRID
;
const
int
attempts
=
2
;
const
int
attempts
=
2
;
const
in
t
minHomographyPoints
=
4
;
const
size_
t
minHomographyPoints
=
4
;
Mat
H
;
Mat
H
;
for
(
int
i
=
0
;
i
<
attempts
;
i
++
)
for
(
int
i
=
0
;
i
<
attempts
;
i
++
)
{
{
...
@@ -1970,10 +1975,20 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
...
@@ -1970,10 +1975,20 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
{
{
}
}
boxFinder
.
getHoles
(
centers
);
if
(
isFound
)
if
(
isFound
)
{
{
switch
(
parameters
.
gridType
)
{
case
CirclesGridFinderParameters
:
:
SYMMETRIC_GRID
:
boxFinder
.
getHoles
(
centers
);
break
;
case
CirclesGridFinderParameters
:
:
ASYMMETRIC_GRID
:
boxFinder
.
getAsymmetricHoles
(
centers
);
break
;
default
:
CV_Error
(
CV_StsBadArg
,
"Unkown pattern type"
);
}
if
(
i
!=
0
)
if
(
i
!=
0
)
{
{
Mat
orgPointsMat
;
Mat
orgPointsMat
;
...
@@ -1983,7 +1998,8 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
...
@@ -1983,7 +1998,8 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
return
true
;
return
true
;
}
}
boxFinder
.
getHoles
(
centers
);
if
(
i
!=
attempts
-
1
)
if
(
i
!=
attempts
-
1
)
{
{
if
(
centers
.
size
()
<
minHomographyPoints
)
if
(
centers
.
size
()
<
minHomographyPoints
)
...
...
modules/calib3d/src/circlesgrid.cpp
View file @
f8e9f65e
/*M///////////////////////////////////////////////////////////////////////////////////////
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//
// By downloading, copying, installing or using the software you agree to this license.
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// If you do not agree to this license, do not download, install,
// copy or use the software.
// copy or use the software.
//
//
//
//
// License Agreement
// License Agreement
// For Open Source Computer Vision Library
// For Open Source Computer Vision Library
//
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
// Third party copyrights are property of their respective owners.
//
//
// Redistribution and use in source and binary forms, with or without modification,
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// are permitted provided that the following conditions are met:
//
//
// * Redistribution's of source code must retain the above copyright notice,
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// this list of conditions and the following disclaimer.
//
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// and/or other materials provided with the distribution.
//
//
// * The name of the copyright holders may not be used to endorse or promote products
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
// derived from this software without specific prior written permission.
//
//
// This software is provided by the copyright holders and contributors "as is" and
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
// the use of this software, even if advised of the possibility of such damage.
//
//
//M*/
//M*/
#include "circlesgrid.hpp"
#include "circlesgrid.hpp"
//#define DEBUG_CIRCLES
using
namespace
cv
;
using
namespace
cv
;
using
namespace
std
;
using
namespace
std
;
Graph
::
Graph
(
in
t
n
)
Graph
::
Graph
(
size_
t
n
)
{
{
for
(
in
t
i
=
0
;
i
<
n
;
i
++
)
for
(
size_
t
i
=
0
;
i
<
n
;
i
++
)
{
{
addVertex
(
i
);
addVertex
(
i
);
}
}
}
}
bool
Graph
::
doesVertexExist
(
in
t
id
)
const
bool
Graph
::
doesVertexExist
(
size_
t
id
)
const
{
{
return
(
vertices
.
find
(
id
)
!=
vertices
.
end
());
return
(
vertices
.
find
(
id
)
!=
vertices
.
end
());
}
}
void
Graph
::
addVertex
(
in
t
id
)
void
Graph
::
addVertex
(
size_
t
id
)
{
{
assert
(
!
doesVertexExist
(
id
)
);
assert
(
!
doesVertexExist
(
id
)
);
vertices
.
insert
(
pair
<
in
t
,
Vertex
>
(
id
,
Vertex
()));
vertices
.
insert
(
pair
<
size_
t
,
Vertex
>
(
id
,
Vertex
()));
}
}
void
Graph
::
addEdge
(
int
id1
,
in
t
id2
)
void
Graph
::
addEdge
(
size_t
id1
,
size_
t
id2
)
{
{
assert
(
doesVertexExist
(
id1
)
);
assert
(
doesVertexExist
(
id1
)
);
assert
(
doesVertexExist
(
id2
)
);
assert
(
doesVertexExist
(
id2
)
);
...
@@ -74,7 +75,16 @@ void Graph::addEdge(int id1, int id2)
...
@@ -74,7 +75,16 @@ void Graph::addEdge(int id1, int id2)
vertices
[
id2
].
neighbors
.
insert
(
id1
);
vertices
[
id2
].
neighbors
.
insert
(
id1
);
}
}
bool
Graph
::
areVerticesAdjacent
(
int
id1
,
int
id2
)
const
void
Graph
::
removeEdge
(
size_t
id1
,
size_t
id2
)
{
assert
(
doesVertexExist
(
id1
)
);
assert
(
doesVertexExist
(
id2
)
);
vertices
[
id1
].
neighbors
.
erase
(
id2
);
vertices
[
id2
].
neighbors
.
erase
(
id1
);
}
bool
Graph
::
areVerticesAdjacent
(
size_t
id1
,
size_t
id2
)
const
{
{
assert
(
doesVertexExist
(
id1
)
);
assert
(
doesVertexExist
(
id1
)
);
assert
(
doesVertexExist
(
id2
)
);
assert
(
doesVertexExist
(
id2
)
);
...
@@ -88,7 +98,7 @@ size_t Graph::getVerticesCount() const
...
@@ -88,7 +98,7 @@ size_t Graph::getVerticesCount() const
return
vertices
.
size
();
return
vertices
.
size
();
}
}
size_t
Graph
::
getDegree
(
in
t
id
)
const
size_t
Graph
::
getDegree
(
size_
t
id
)
const
{
{
assert
(
doesVertexExist
(
id
)
);
assert
(
doesVertexExist
(
id
)
);
...
@@ -126,13 +136,28 @@ void Graph::floydWarshall(cv::Mat &distanceMatrix, int infinity) const
...
@@ -126,13 +136,28 @@ void Graph::floydWarshall(cv::Mat &distanceMatrix, int infinity) const
==
infinity
)
==
infinity
)
val2
=
val1
;
val2
=
val1
;
else
else
{
val2
=
distanceMatrix
.
at
<
int
>
(
it2
->
first
,
it1
->
first
)
+
distanceMatrix
.
at
<
int
>
(
it1
->
first
,
it3
->
first
);
val2
=
distanceMatrix
.
at
<
int
>
(
it2
->
first
,
it1
->
first
)
+
distanceMatrix
.
at
<
int
>
(
it1
->
first
,
it3
->
first
);
distanceMatrix
.
at
<
int
>
(
it2
->
first
,
it3
->
first
)
=
std
::
min
(
val1
,
val2
);
}
distanceMatrix
.
at
<
int
>
(
it2
->
first
,
it3
->
first
)
=
(
val1
==
infinity
)
?
val2
:
std
::
min
(
val1
,
val2
);
}
}
}
}
}
}
}
}
const
Graph
::
Neighbors
&
Graph
::
getNeighbors
(
size_t
id
)
const
{
assert
(
doesVertexExist
(
id
)
);
Vertices
::
const_iterator
it
=
vertices
.
find
(
id
);
return
it
->
second
.
neighbors
;
}
CirclesGridFinder
::
Segment
::
Segment
(
cv
::
Point2f
_s
,
cv
::
Point2f
_e
)
:
s
(
_s
),
e
(
_e
)
{
}
void
computeShortestPath
(
Mat
&
predecessorMatrix
,
int
v1
,
int
v2
,
vector
<
int
>
&
path
);
void
computeShortestPath
(
Mat
&
predecessorMatrix
,
int
v1
,
int
v2
,
vector
<
int
>
&
path
);
void
computePredecessorMatrix
(
const
Mat
&
dm
,
int
verticesCount
,
Mat
&
predecessorMatrix
);
void
computePredecessorMatrix
(
const
Mat
&
dm
,
int
verticesCount
,
Mat
&
predecessorMatrix
);
...
@@ -151,54 +176,210 @@ CirclesGridFinderParameters::CirclesGridFinderParameters()
...
@@ -151,54 +176,210 @@ CirclesGridFinderParameters::CirclesGridFinderParameters()
edgeGain
=
1
;
edgeGain
=
1
;
edgePenalty
=
-
5
;
edgePenalty
=
-
5
;
existingVertexGain
=
0
;
existingVertexGain
=
0
;
minRNGEdgeSwitchDist
=
5.
f
;
gridType
=
SYMMETRIC_GRID
;
}
}
CirclesGridFinder
::
CirclesGridFinder
(
Size
_patternSize
,
const
vector
<
Point2f
>
&
testKeypoints
,
CirclesGridFinder
::
CirclesGridFinder
(
Size
_patternSize
,
const
vector
<
Point2f
>
&
testKeypoints
,
const
CirclesGridFinderParameters
&
_parameters
)
:
const
CirclesGridFinderParameters
&
_parameters
)
:
patternSize
(
_patternSize
)
patternSize
(
static_cast
<
size_t
>
(
_patternSize
.
width
),
static_cast
<
size_t
>
(
_patternSize
.
height
)
)
{
{
CV_Assert
(
_patternSize
.
height
>=
0
&&
_patternSize
.
width
>=
0
);
keypoints
=
testKeypoints
;
keypoints
=
testKeypoints
;
parameters
=
_parameters
;
parameters
=
_parameters
;
largeHoles
=
0
;
smallHoles
=
0
;
}
}
bool
CirclesGridFinder
::
findHoles
()
bool
CirclesGridFinder
::
findHoles
()
{
{
vector
<
Point2f
>
vectors
,
filteredVectors
,
basis
;
switch
(
parameters
.
gridType
)
computeEdgeVectorsOfRNG
(
vectors
);
{
filterOutliersByDensity
(
vectors
,
filteredVectors
);
case
CirclesGridFinderParameters
:
:
SYMMETRIC_GRID
:
vector
<
Graph
>
basisGraphs
;
{
findBasis
(
filteredVectors
,
basis
,
basisGraphs
);
vector
<
Point2f
>
vectors
,
filteredVectors
,
basis
;
findMCS
(
basis
,
basisGraphs
);
Graph
rng
(
0
);
computeRNG
(
rng
,
vectors
);
filterOutliersByDensity
(
vectors
,
filteredVectors
);
vector
<
Graph
>
basisGraphs
;
findBasis
(
filteredVectors
,
basis
,
basisGraphs
);
findMCS
(
basis
,
basisGraphs
);
break
;
}
case
CirclesGridFinderParameters
:
:
ASYMMETRIC_GRID
:
{
vector
<
Point2f
>
vectors
,
tmpVectors
,
filteredVectors
,
basis
;
Graph
rng
(
0
);
computeRNG
(
rng
,
tmpVectors
);
rng2gridGraph
(
rng
,
vectors
);
filterOutliersByDensity
(
vectors
,
filteredVectors
);
vector
<
Graph
>
basisGraphs
;
findBasis
(
filteredVectors
,
basis
,
basisGraphs
);
findMCS
(
basis
,
basisGraphs
);
eraseUsedGraph
(
basisGraphs
);
holes2
=
holes
;
holes
.
clear
();
findMCS
(
basis
,
basisGraphs
);
break
;
}
default
:
CV_Error
(
CV_StsBadArg
,
"Unkown pattern type"
);
}
return
(
isDetectionCorrect
());
return
(
isDetectionCorrect
());
//CV_Error( 0, "Detection is not correct" );
//CV_Error( 0, "Detection is not correct" );
}
}
bool
CirclesGridFinder
::
isDetectionCorrect
()
void
CirclesGridFinder
::
rng2gridGraph
(
Graph
&
rng
,
std
::
vector
<
cv
::
Point2f
>
&
vectors
)
const
{
{
if
(
holes
.
size
()
!=
patternSize
.
height
)
for
(
size_t
i
=
0
;
i
<
rng
.
getVerticesCount
();
i
++
)
return
false
;
{
Graph
::
Neighbors
neighbors1
=
rng
.
getNeighbors
(
i
);
for
(
Graph
::
Neighbors
::
iterator
it1
=
neighbors1
.
begin
();
it1
!=
neighbors1
.
end
();
it1
++
)
{
Graph
::
Neighbors
neighbors2
=
rng
.
getNeighbors
(
*
it1
);
for
(
Graph
::
Neighbors
::
iterator
it2
=
neighbors2
.
begin
();
it2
!=
neighbors2
.
end
();
it2
++
)
{
if
(
i
<
*
it2
)
{
Point2f
vec1
=
keypoints
[
i
]
-
keypoints
[
*
it1
];
Point2f
vec2
=
keypoints
[
*
it1
]
-
keypoints
[
*
it2
];
if
(
norm
(
vec1
-
vec2
)
<
parameters
.
minRNGEdgeSwitchDist
||
norm
(
vec1
+
vec2
)
<
parameters
.
minRNGEdgeSwitchDist
)
continue
;
vectors
.
push_back
(
keypoints
[
i
]
-
keypoints
[
*
it2
]);
vectors
.
push_back
(
keypoints
[
*
it2
]
-
keypoints
[
i
]);
}
}
}
}
}
set
<
int
>
vertices
;
void
CirclesGridFinder
::
eraseUsedGraph
(
vector
<
Graph
>
&
basisGraphs
)
const
{
for
(
size_t
i
=
0
;
i
<
holes
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
holes
.
size
();
i
++
)
{
{
if
(
holes
[
i
].
size
()
!=
patternSize
.
width
)
return
false
;
for
(
size_t
j
=
0
;
j
<
holes
[
i
].
size
();
j
++
)
for
(
size_t
j
=
0
;
j
<
holes
[
i
].
size
();
j
++
)
{
{
vertices
.
insert
(
holes
[
i
][
j
]);
for
(
size_t
k
=
0
;
k
<
basisGraphs
.
size
();
k
++
)
{
if
(
i
!=
holes
.
size
()
-
1
&&
basisGraphs
[
k
].
areVerticesAdjacent
(
holes
[
i
][
j
],
holes
[
i
+
1
][
j
]))
{
basisGraphs
[
k
].
removeEdge
(
holes
[
i
][
j
],
holes
[
i
+
1
][
j
]);
}
if
(
j
!=
holes
[
i
].
size
()
-
1
&&
basisGraphs
[
k
].
areVerticesAdjacent
(
holes
[
i
][
j
],
holes
[
i
][
j
+
1
]))
{
basisGraphs
[
k
].
removeEdge
(
holes
[
i
][
j
],
holes
[
i
][
j
+
1
]);
}
}
}
}
}
}
}
bool
CirclesGridFinder
::
isDetectionCorrect
()
{
switch
(
parameters
.
gridType
)
{
case
CirclesGridFinderParameters
:
:
SYMMETRIC_GRID
:
{
if
(
holes
.
size
()
!=
patternSize
.
height
)
return
false
;
set
<
size_t
>
vertices
;
for
(
size_t
i
=
0
;
i
<
holes
.
size
();
i
++
)
{
if
(
holes
[
i
].
size
()
!=
patternSize
.
width
)
return
false
;
for
(
size_t
j
=
0
;
j
<
holes
[
i
].
size
();
j
++
)
{
vertices
.
insert
(
holes
[
i
][
j
]);
}
}
return
vertices
.
size
()
==
patternSize
.
area
();
}
case
CirclesGridFinderParameters
:
:
ASYMMETRIC_GRID
:
{
if
(
holes
.
size
()
<
holes2
.
size
()
||
holes
[
0
].
size
()
<
holes2
[
0
].
size
())
{
largeHoles
=
&
holes2
;
smallHoles
=
&
holes
;
}
else
{
largeHoles
=
&
holes
;
smallHoles
=
&
holes2
;
}
size_t
largeWidth
=
patternSize
.
width
;
size_t
largeHeight
=
ceil
(
patternSize
.
height
/
2.
);
size_t
smallWidth
=
patternSize
.
width
;
size_t
smallHeight
=
floor
(
patternSize
.
height
/
2.
);
size_t
sw
=
smallWidth
,
sh
=
smallHeight
,
lw
=
largeWidth
,
lh
=
largeHeight
;
if
(
largeHoles
->
size
()
!=
largeHeight
)
{
std
::
swap
(
lh
,
lw
);
}
if
(
smallHoles
->
size
()
!=
smallHeight
)
{
std
::
swap
(
sh
,
sw
);
}
if
(
largeHoles
->
size
()
!=
lh
||
smallHoles
->
size
()
!=
sh
)
{
return
false
;
}
set
<
size_t
>
vertices
;
for
(
size_t
i
=
0
;
i
<
largeHoles
->
size
();
i
++
)
{
if
(
largeHoles
->
at
(
i
).
size
()
!=
lw
)
{
return
false
;
}
return
vertices
.
size
()
==
patternSize
.
area
();
for
(
size_t
j
=
0
;
j
<
largeHoles
->
at
(
i
).
size
();
j
++
)
{
vertices
.
insert
(
largeHoles
->
at
(
i
)[
j
]);
}
if
(
i
<
smallHoles
->
size
())
{
if
(
smallHoles
->
at
(
i
).
size
()
!=
sw
)
{
return
false
;
}
for
(
size_t
j
=
0
;
j
<
smallHoles
->
at
(
i
).
size
();
j
++
)
{
vertices
.
insert
(
smallHoles
->
at
(
i
)[
j
]);
}
}
}
return
(
vertices
.
size
()
==
largeHeight
*
largeWidth
+
smallHeight
*
smallWidth
);
}
default
:
CV_Error
(
0
,
"Unknown pattern type"
);
}
return
false
;
}
}
void
CirclesGridFinder
::
findMCS
(
const
vector
<
Point2f
>
&
basis
,
vector
<
Graph
>
&
basisGraphs
)
void
CirclesGridFinder
::
findMCS
(
const
vector
<
Point2f
>
&
basis
,
vector
<
Graph
>
&
basisGraphs
)
{
{
holes
.
clear
();
Path
longestPath
;
Path
longestPath
;
size_t
bestGraphIdx
=
findLongestPath
(
basisGraphs
,
longestPath
);
size_t
bestGraphIdx
=
findLongestPath
(
basisGraphs
,
longestPath
);
vector
<
in
t
>
holesRow
=
longestPath
.
vertices
;
vector
<
size_
t
>
holesRow
=
longestPath
.
vertices
;
while
(
holesRow
.
size
()
>
std
::
max
(
patternSize
.
width
,
patternSize
.
height
))
while
(
holesRow
.
size
()
>
std
::
max
(
patternSize
.
width
,
patternSize
.
height
))
{
{
...
@@ -209,14 +390,14 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
...
@@ -209,14 +390,14 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
if
(
bestGraphIdx
==
0
)
if
(
bestGraphIdx
==
0
)
{
{
holes
.
push_back
(
holesRow
);
holes
.
push_back
(
holesRow
);
in
t
w
=
holes
[
0
].
size
();
size_
t
w
=
holes
[
0
].
size
();
in
t
h
=
holes
.
size
();
size_
t
h
=
holes
.
size
();
//parameters.minGraphConfidence = holes[0].size() * parameters.vertexGain + (holes[0].size() - 1) * parameters.edgeGain;
//parameters.minGraphConfidence = holes[0].size() * parameters.vertexGain + (holes[0].size() - 1) * parameters.edgeGain;
//parameters.minGraphConfidence = holes[0].size() * parameters.vertexGain + (holes[0].size() / 2) * parameters.edgeGain;
//parameters.minGraphConfidence = holes[0].size() * parameters.vertexGain + (holes[0].size() / 2) * parameters.edgeGain;
//parameters.minGraphConfidence = holes[0].size() * parameters.existingVertexGain + (holes[0].size() / 2) * parameters.edgeGain;
//parameters.minGraphConfidence = holes[0].size() * parameters.existingVertexGain + (holes[0].size() / 2) * parameters.edgeGain;
parameters
.
minGraphConfidence
=
holes
[
0
].
size
()
*
parameters
.
existingVertexGain
;
parameters
.
minGraphConfidence
=
holes
[
0
].
size
()
*
parameters
.
existingVertexGain
;
for
(
in
t
i
=
h
;
i
<
patternSize
.
height
;
i
++
)
for
(
size_
t
i
=
h
;
i
<
patternSize
.
height
;
i
++
)
{
{
addHolesByGraph
(
basisGraphs
,
true
,
basis
[
1
]);
addHolesByGraph
(
basisGraphs
,
true
,
basis
[
1
]);
}
}
...
@@ -224,7 +405,7 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
...
@@ -224,7 +405,7 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
//parameters.minGraphConfidence = holes.size() * parameters.existingVertexGain + (holes.size() / 2) * parameters.edgeGain;
//parameters.minGraphConfidence = holes.size() * parameters.existingVertexGain + (holes.size() / 2) * parameters.edgeGain;
parameters
.
minGraphConfidence
=
holes
.
size
()
*
parameters
.
existingVertexGain
;
parameters
.
minGraphConfidence
=
holes
.
size
()
*
parameters
.
existingVertexGain
;
for
(
in
t
i
=
w
;
i
<
patternSize
.
width
;
i
++
)
for
(
size_
t
i
=
w
;
i
<
patternSize
.
width
;
i
++
)
{
{
addHolesByGraph
(
basisGraphs
,
false
,
basis
[
0
]);
addHolesByGraph
(
basisGraphs
,
false
,
basis
[
0
]);
}
}
...
@@ -235,17 +416,17 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
...
@@ -235,17 +416,17 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
for
(
size_t
i
=
0
;
i
<
holesRow
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
holesRow
.
size
();
i
++
)
holes
[
i
].
push_back
(
holesRow
[
i
]);
holes
[
i
].
push_back
(
holesRow
[
i
]);
in
t
w
=
holes
[
0
].
size
();
size_
t
w
=
holes
[
0
].
size
();
in
t
h
=
holes
.
size
();
size_
t
h
=
holes
.
size
();
parameters
.
minGraphConfidence
=
holes
.
size
()
*
parameters
.
existingVertexGain
;
parameters
.
minGraphConfidence
=
holes
.
size
()
*
parameters
.
existingVertexGain
;
for
(
in
t
i
=
w
;
i
<
patternSize
.
width
;
i
++
)
for
(
size_
t
i
=
w
;
i
<
patternSize
.
width
;
i
++
)
{
{
addHolesByGraph
(
basisGraphs
,
false
,
basis
[
0
]);
addHolesByGraph
(
basisGraphs
,
false
,
basis
[
0
]);
}
}
parameters
.
minGraphConfidence
=
holes
[
0
].
size
()
*
parameters
.
existingVertexGain
;
parameters
.
minGraphConfidence
=
holes
[
0
].
size
()
*
parameters
.
existingVertexGain
;
for
(
in
t
i
=
h
;
i
<
patternSize
.
height
;
i
++
)
for
(
size_
t
i
=
h
;
i
<
patternSize
.
height
;
i
++
)
{
{
addHolesByGraph
(
basisGraphs
,
true
,
basis
[
1
]);
addHolesByGraph
(
basisGraphs
,
true
,
basis
[
1
]);
}
}
...
@@ -292,9 +473,9 @@ Mat CirclesGridFinder::rectifyGrid(Size detectedGridSize, const vector<Point2f>&
...
@@ -292,9 +473,9 @@ Mat CirclesGridFinder::rectifyGrid(Size detectedGridSize, const vector<Point2f>&
return
H
;
return
H
;
}
}
in
t
CirclesGridFinder
::
findNearestKeypoint
(
Point2f
pt
)
const
size_
t
CirclesGridFinder
::
findNearestKeypoint
(
Point2f
pt
)
const
{
{
in
t
bestIdx
=
-
1
;
size_
t
bestIdx
=
-
1
;
double
minDist
=
std
::
numeric_limits
<
double
>::
max
();
double
minDist
=
std
::
numeric_limits
<
double
>::
max
();
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
i
++
)
{
{
...
@@ -308,9 +489,9 @@ int CirclesGridFinder::findNearestKeypoint(Point2f pt) const
...
@@ -308,9 +489,9 @@ int CirclesGridFinder::findNearestKeypoint(Point2f pt) const
return
bestIdx
;
return
bestIdx
;
}
}
void
CirclesGridFinder
::
addPoint
(
Point2f
pt
,
vector
<
in
t
>
&
points
)
void
CirclesGridFinder
::
addPoint
(
Point2f
pt
,
vector
<
size_
t
>
&
points
)
{
{
in
t
ptIdx
=
findNearestKeypoint
(
pt
);
size_
t
ptIdx
=
findNearestKeypoint
(
pt
);
if
(
norm
(
keypoints
[
ptIdx
]
-
pt
)
>
parameters
.
minDistanceToAddKeypoint
)
if
(
norm
(
keypoints
[
ptIdx
]
-
pt
)
>
parameters
.
minDistanceToAddKeypoint
)
{
{
Point2f
kpt
=
Point2f
(
pt
);
Point2f
kpt
=
Point2f
(
pt
);
...
@@ -323,8 +504,8 @@ void CirclesGridFinder::addPoint(Point2f pt, vector<int> &points)
...
@@ -323,8 +504,8 @@ void CirclesGridFinder::addPoint(Point2f pt, vector<int> &points)
}
}
}
}
void
CirclesGridFinder
::
findCandidateLine
(
vector
<
int
>
&
line
,
in
t
seedLineIdx
,
bool
addRow
,
Point2f
basisVec
,
void
CirclesGridFinder
::
findCandidateLine
(
vector
<
size_t
>
&
line
,
size_
t
seedLineIdx
,
bool
addRow
,
Point2f
basisVec
,
vector
<
in
t
>
&
seeds
)
vector
<
size_
t
>
&
seeds
)
{
{
line
.
clear
();
line
.
clear
();
seeds
.
clear
();
seeds
.
clear
();
...
@@ -351,8 +532,8 @@ void CirclesGridFinder::findCandidateLine(vector<int> &line, int seedLineIdx, bo
...
@@ -351,8 +532,8 @@ void CirclesGridFinder::findCandidateLine(vector<int> &line, int seedLineIdx, bo
assert
(
line
.
size
()
==
seeds
.
size
()
);
assert
(
line
.
size
()
==
seeds
.
size
()
);
}
}
void
CirclesGridFinder
::
findCandidateHoles
(
vector
<
int
>
&
above
,
vector
<
in
t
>
&
below
,
bool
addRow
,
Point2f
basisVec
,
void
CirclesGridFinder
::
findCandidateHoles
(
vector
<
size_t
>
&
above
,
vector
<
size_
t
>
&
below
,
bool
addRow
,
Point2f
basisVec
,
vector
<
int
>
&
aboveSeeds
,
vector
<
in
t
>
&
belowSeeds
)
vector
<
size_t
>
&
aboveSeeds
,
vector
<
size_
t
>
&
belowSeeds
)
{
{
above
.
clear
();
above
.
clear
();
below
.
clear
();
below
.
clear
();
...
@@ -360,7 +541,7 @@ void CirclesGridFinder::findCandidateHoles(vector<int> &above, vector<int> &belo
...
@@ -360,7 +541,7 @@ void CirclesGridFinder::findCandidateHoles(vector<int> &above, vector<int> &belo
belowSeeds
.
clear
();
belowSeeds
.
clear
();
findCandidateLine
(
above
,
0
,
addRow
,
-
basisVec
,
aboveSeeds
);
findCandidateLine
(
above
,
0
,
addRow
,
-
basisVec
,
aboveSeeds
);
in
t
lastIdx
=
addRow
?
holes
.
size
()
-
1
:
holes
[
0
].
size
()
-
1
;
size_
t
lastIdx
=
addRow
?
holes
.
size
()
-
1
:
holes
[
0
].
size
()
-
1
;
findCandidateLine
(
below
,
lastIdx
,
addRow
,
basisVec
,
belowSeeds
);
findCandidateLine
(
below
,
lastIdx
,
addRow
,
basisVec
,
belowSeeds
);
assert
(
below
.
size
()
==
above
.
size
()
);
assert
(
below
.
size
()
==
above
.
size
()
);
...
@@ -368,7 +549,7 @@ void CirclesGridFinder::findCandidateHoles(vector<int> &above, vector<int> &belo
...
@@ -368,7 +549,7 @@ void CirclesGridFinder::findCandidateHoles(vector<int> &above, vector<int> &belo
assert
(
below
.
size
()
==
belowSeeds
.
size
()
);
assert
(
below
.
size
()
==
belowSeeds
.
size
()
);
}
}
bool
CirclesGridFinder
::
areCentersNew
(
const
vector
<
int
>
&
newCenters
,
const
vector
<
vector
<
in
t
>
>
&
holes
)
bool
CirclesGridFinder
::
areCentersNew
(
const
vector
<
size_t
>
&
newCenters
,
const
vector
<
vector
<
size_
t
>
>
&
holes
)
{
{
for
(
size_t
i
=
0
;
i
<
newCenters
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
newCenters
.
size
();
i
++
)
{
{
...
@@ -385,7 +566,8 @@ bool CirclesGridFinder::areCentersNew(const vector<int> &newCenters, const vecto
...
@@ -385,7 +566,8 @@ bool CirclesGridFinder::areCentersNew(const vector<int> &newCenters, const vecto
}
}
void
CirclesGridFinder
::
insertWinner
(
float
aboveConfidence
,
float
belowConfidence
,
float
minConfidence
,
bool
addRow
,
void
CirclesGridFinder
::
insertWinner
(
float
aboveConfidence
,
float
belowConfidence
,
float
minConfidence
,
bool
addRow
,
const
vector
<
int
>
&
above
,
const
vector
<
int
>
&
below
,
vector
<
vector
<
int
>
>
&
holes
)
const
vector
<
size_t
>
&
above
,
const
vector
<
size_t
>
&
below
,
vector
<
vector
<
size_t
>
>
&
holes
)
{
{
if
(
aboveConfidence
<
minConfidence
&&
belowConfidence
<
minConfidence
)
if
(
aboveConfidence
<
minConfidence
&&
belowConfidence
<
minConfidence
)
return
;
return
;
...
@@ -432,30 +614,12 @@ void CirclesGridFinder::insertWinner(float aboveConfidence, float belowConfidenc
...
@@ -432,30 +614,12 @@ void CirclesGridFinder::insertWinner(float aboveConfidence, float belowConfidenc
}
}
}
}
/*
bool CirclesGridFinder::areVerticesAdjacent(const Graph &graph, int vertex1, int vertex2)
{
property_map<Graph, vertex_index_t>::type index = get(vertex_index, graph);
bool areAdjacent = false;
graph_traits<Graph>::adjacency_iterator ai;
graph_traits<Graph>::adjacency_iterator ai_end;
for (tie(ai, ai_end) = adjacent_vertices(vertex1, graph); ai != ai_end; ++ai)
{
if (*ai == index[vertex2])
areAdjacent = true;
}
return areAdjacent;
}*/
float
CirclesGridFinder
::
computeGraphConfidence
(
const
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
float
CirclesGridFinder
::
computeGraphConfidence
(
const
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
const
vector
<
int
>
&
points
,
const
vector
<
in
t
>
&
seeds
)
const
vector
<
size_t
>
&
points
,
const
vector
<
size_
t
>
&
seeds
)
{
{
assert
(
points
.
size
()
==
seeds
.
size
()
);
assert
(
points
.
size
()
==
seeds
.
size
()
);
float
confidence
=
0
;
float
confidence
=
0
;
const
in
t
vCount
=
basisGraphs
[
0
].
getVerticesCount
();
const
size_
t
vCount
=
basisGraphs
[
0
].
getVerticesCount
();
assert
(
basisGraphs
[
0
].
getVerticesCount
()
==
basisGraphs
[
1
].
getVerticesCount
()
);
assert
(
basisGraphs
[
0
].
getVerticesCount
()
==
basisGraphs
[
1
].
getVerticesCount
()
);
for
(
size_t
i
=
0
;
i
<
seeds
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
seeds
.
size
();
i
++
)
...
@@ -498,7 +662,7 @@ float CirclesGridFinder::computeGraphConfidence(const vector<Graph> &basisGraphs
...
@@ -498,7 +662,7 @@ float CirclesGridFinder::computeGraphConfidence(const vector<Graph> &basisGraphs
void
CirclesGridFinder
::
addHolesByGraph
(
const
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
Point2f
basisVec
)
void
CirclesGridFinder
::
addHolesByGraph
(
const
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
Point2f
basisVec
)
{
{
vector
<
in
t
>
above
,
below
,
aboveSeeds
,
belowSeeds
;
vector
<
size_
t
>
above
,
below
,
aboveSeeds
,
belowSeeds
;
findCandidateHoles
(
above
,
below
,
addRow
,
basisVec
,
aboveSeeds
,
belowSeeds
);
findCandidateHoles
(
above
,
below
,
addRow
,
basisVec
,
aboveSeeds
,
belowSeeds
);
float
aboveConfidence
=
computeGraphConfidence
(
basisGraphs
,
addRow
,
above
,
aboveSeeds
);
float
aboveConfidence
=
computeGraphConfidence
(
basisGraphs
,
addRow
,
above
,
aboveSeeds
);
float
belowConfidence
=
computeGraphConfidence
(
basisGraphs
,
addRow
,
below
,
belowSeeds
);
float
belowConfidence
=
computeGraphConfidence
(
basisGraphs
,
addRow
,
below
,
belowSeeds
);
...
@@ -537,7 +701,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
...
@@ -537,7 +701,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
Mat
bestLabels
;
Mat
bestLabels
;
TermCriteria
termCriteria
;
TermCriteria
termCriteria
;
Mat
centers
;
Mat
centers
;
int
clustersCount
=
4
;
const
int
clustersCount
=
4
;
kmeans
(
Mat
(
samples
).
reshape
(
1
,
0
),
clustersCount
,
bestLabels
,
termCriteria
,
parameters
.
kmeansAttempts
,
kmeans
(
Mat
(
samples
).
reshape
(
1
,
0
),
clustersCount
,
bestLabels
,
termCriteria
,
parameters
.
kmeansAttempts
,
KMEANS_RANDOM_CENTERS
,
&
centers
);
KMEANS_RANDOM_CENTERS
,
&
centers
);
assert
(
centers
.
type
()
==
CV_32FC1
);
assert
(
centers
.
type
()
==
CV_32FC1
);
...
@@ -555,7 +719,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
...
@@ -555,7 +719,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
}
}
}
}
if
(
basis
.
size
()
!=
2
)
if
(
basis
.
size
()
!=
2
)
CV_Error
(
0
,
"Basis size is not 2"
);
CV_Error
(
0
,
"Basis size is not 2"
);
if
(
basis
[
1
].
x
>
basis
[
0
].
x
)
if
(
basis
[
1
].
x
>
basis
[
0
].
x
)
{
{
...
@@ -565,7 +729,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
...
@@ -565,7 +729,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
const
float
minBasisDif
=
2
;
const
float
minBasisDif
=
2
;
if
(
norm
(
basis
[
0
]
-
basis
[
1
])
<
minBasisDif
)
if
(
norm
(
basis
[
0
]
-
basis
[
1
])
<
minBasisDif
)
CV_Error
(
0
,
"degenerate basis"
);
CV_Error
(
0
,
"degenerate basis"
);
vector
<
vector
<
Point2f
>
>
clusters
(
2
),
hulls
(
2
);
vector
<
vector
<
Point2f
>
>
clusters
(
2
),
hulls
(
2
);
for
(
size_t
k
=
0
;
k
<
samples
.
size
();
k
++
)
for
(
size_t
k
=
0
;
k
<
samples
.
size
();
k
++
)
...
@@ -605,10 +769,13 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
...
@@ -605,10 +769,13 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
}
}
}
}
}
}
if
(
basisGraphs
.
size
()
!=
2
)
CV_Error
(
0
,
"Number of basis graphs is not 2"
);
}
}
void
CirclesGridFinder
::
compute
EdgeVectorsOfRNG
(
vector
<
Point2f
>
&
vectors
,
Mat
*
drawImage
)
const
void
CirclesGridFinder
::
compute
RNG
(
Graph
&
rng
,
std
::
vector
<
cv
::
Point2f
>
&
vectors
,
Mat
*
drawImage
)
const
{
{
rng
=
Graph
(
keypoints
.
size
());
vectors
.
clear
();
vectors
.
clear
();
//TODO: use more fast algorithm instead of naive N^3
//TODO: use more fast algorithm instead of naive N^3
...
@@ -639,6 +806,7 @@ void CirclesGridFinder::computeEdgeVectorsOfRNG(vector<Point2f> &vectors, Mat *d
...
@@ -639,6 +806,7 @@ void CirclesGridFinder::computeEdgeVectorsOfRNG(vector<Point2f> &vectors, Mat *d
if
(
isNeighbors
)
if
(
isNeighbors
)
{
{
rng
.
addEdge
(
i
,
j
);
vectors
.
push_back
(
keypoints
[
i
]
-
keypoints
[
j
]);
vectors
.
push_back
(
keypoints
[
i
]
-
keypoints
[
j
]);
if
(
drawImage
!=
0
)
if
(
drawImage
!=
0
)
{
{
...
@@ -673,7 +841,7 @@ void computePredecessorMatrix(const Mat &dm, int verticesCount, Mat &predecessor
...
@@ -673,7 +841,7 @@ void computePredecessorMatrix(const Mat &dm, int verticesCount, Mat &predecessor
}
}
}
}
void
computeShortestPath
(
Mat
&
predecessorMatrix
,
int
v1
,
int
v2
,
vector
<
in
t
>
&
path
)
void
computeShortestPath
(
Mat
&
predecessorMatrix
,
size_t
v1
,
size_t
v2
,
vector
<
size_
t
>
&
path
)
{
{
if
(
predecessorMatrix
.
at
<
int
>
(
v1
,
v2
)
<
0
)
if
(
predecessorMatrix
.
at
<
int
>
(
v1
,
v2
)
<
0
)
{
{
...
@@ -714,7 +882,11 @@ size_t CirclesGridFinder::findLongestPath(vector<Graph> &basisGraphs, Path &best
...
@@ -714,7 +882,11 @@ size_t CirclesGridFinder::findLongestPath(vector<Graph> &basisGraphs, Path &best
if
(
longestPaths
.
empty
()
||
(
maxVal
==
longestPaths
[
0
].
length
&&
graphIdx
==
bestGraphIdx
))
if
(
longestPaths
.
empty
()
||
(
maxVal
==
longestPaths
[
0
].
length
&&
graphIdx
==
bestGraphIdx
))
{
{
Path
path
=
Path
(
maxLoc
.
x
,
maxLoc
.
y
,
cvRound
(
maxVal
));
Path
path
=
Path
(
maxLoc
.
x
,
maxLoc
.
y
,
cvRound
(
maxVal
));
computeShortestPath
(
predecessorMatrix
,
maxLoc
.
x
,
maxLoc
.
y
,
path
.
vertices
);
CV_Assert
(
maxLoc
.
x
>=
0
&&
maxLoc
.
y
>=
0
)
;
size_t
id1
=
static_cast
<
size_t
>
(
maxLoc
.
x
);
size_t
id2
=
static_cast
<
size_t
>
(
maxLoc
.
y
);
computeShortestPath
(
predecessorMatrix
,
id1
,
id2
,
path
.
vertices
);
longestPaths
.
push_back
(
path
);
longestPaths
.
push_back
(
path
);
int
conf
=
0
;
int
conf
=
0
;
...
@@ -848,3 +1020,190 @@ void CirclesGridFinder::getHoles(vector<Point2f> &outHoles) const
...
@@ -848,3 +1020,190 @@ void CirclesGridFinder::getHoles(vector<Point2f> &outHoles) const
}
}
}
}
}
}
bool
areIndicesCorrect
(
Point
pos
,
vector
<
vector
<
size_t
>
>
*
points
)
{
if
(
pos
.
y
<
0
||
pos
.
x
<
0
)
return
false
;
return
(
static_cast
<
size_t
>
(
pos
.
y
)
<
points
->
size
()
&&
static_cast
<
size_t
>
(
pos
.
x
)
<
points
->
at
(
pos
.
y
).
size
());
}
void
CirclesGridFinder
::
getAsymmetricHoles
(
std
::
vector
<
cv
::
Point2f
>
&
outHoles
)
const
{
outHoles
.
clear
();
vector
<
Point
>
largeCornerIndices
,
smallCornerIndices
;
vector
<
Point
>
firstSteps
,
secondSteps
;
size_t
cornerIdx
=
getFirstCorner
(
largeCornerIndices
,
smallCornerIndices
,
firstSteps
,
secondSteps
);
CV_Assert
(
largeHoles
!=
0
&&
smallHoles
!=
0
)
;
Point
srcLargePos
=
largeCornerIndices
[
cornerIdx
];
Point
srcSmallPos
=
smallCornerIndices
[
cornerIdx
];
while
(
areIndicesCorrect
(
srcLargePos
,
largeHoles
)
||
areIndicesCorrect
(
srcSmallPos
,
smallHoles
))
{
Point
largePos
=
srcLargePos
;
while
(
areIndicesCorrect
(
largePos
,
largeHoles
))
{
outHoles
.
push_back
(
keypoints
[
largeHoles
->
at
(
largePos
.
y
)[
largePos
.
x
]]);
largePos
+=
firstSteps
[
cornerIdx
];
}
srcLargePos
+=
secondSteps
[
cornerIdx
];
Point
smallPos
=
srcSmallPos
;
while
(
areIndicesCorrect
(
smallPos
,
smallHoles
))
{
outHoles
.
push_back
(
keypoints
[
smallHoles
->
at
(
smallPos
.
y
)[
smallPos
.
x
]]);
smallPos
+=
firstSteps
[
cornerIdx
];
}
srcSmallPos
+=
secondSteps
[
cornerIdx
];
}
}
double
CirclesGridFinder
::
getDirection
(
Point2f
p1
,
Point2f
p2
,
Point2f
p3
)
{
Point2f
a
=
p3
-
p1
;
Point2f
b
=
p2
-
p1
;
return
a
.
x
*
b
.
y
-
a
.
y
*
b
.
x
;
}
bool
CirclesGridFinder
::
areSegmentsIntersecting
(
Segment
seg1
,
Segment
seg2
)
{
bool
doesStraddle1
=
(
getDirection
(
seg2
.
s
,
seg2
.
e
,
seg1
.
s
)
*
getDirection
(
seg2
.
s
,
seg2
.
e
,
seg1
.
e
))
<
0
;
bool
doesStraddle2
=
(
getDirection
(
seg1
.
s
,
seg1
.
e
,
seg2
.
s
)
*
getDirection
(
seg1
.
s
,
seg1
.
e
,
seg2
.
e
))
<
0
;
return
doesStraddle1
&&
doesStraddle2
;
/*
Point2f t1 = e1-s1;
Point2f n1(t1.y, -t1.x);
double c1 = -n1.ddot(s1);
Point2f t2 = e2-s2;
Point2f n2(t2.y, -t2.x);
double c2 = -n2.ddot(s2);
bool seg1 = ((n1.ddot(s2) + c1) * (n1.ddot(e2) + c1)) <= 0;
bool seg1 = ((n2.ddot(s1) + c2) * (n2.ddot(e1) + c2)) <= 0;
return seg1 && seg2;
*/
}
void
CirclesGridFinder
::
getCornerSegments
(
const
vector
<
vector
<
size_t
>
>
&
points
,
vector
<
vector
<
Segment
>
>
&
segments
,
vector
<
Point
>
&
cornerIndices
,
vector
<
Point
>
&
firstSteps
,
vector
<
Point
>
&
secondSteps
)
const
{
segments
.
clear
();
cornerIndices
.
clear
();
firstSteps
.
clear
();
secondSteps
.
clear
();
size_t
h
=
points
.
size
();
size_t
w
=
points
[
0
].
size
();
CV_Assert
(
h
>=
2
&&
w
>=
2
)
;
//all 8 segments with one end in a corner
vector
<
Segment
>
corner
;
corner
.
push_back
(
Segment
(
keypoints
[
points
[
1
][
0
]],
keypoints
[
points
[
0
][
0
]]));
corner
.
push_back
(
Segment
(
keypoints
[
points
[
0
][
0
]],
keypoints
[
points
[
0
][
1
]]));
segments
.
push_back
(
corner
);
cornerIndices
.
push_back
(
Point
(
0
,
0
));
firstSteps
.
push_back
(
Point
(
1
,
0
));
secondSteps
.
push_back
(
Point
(
0
,
1
));
corner
.
clear
();
corner
.
push_back
(
Segment
(
keypoints
[
points
[
0
][
w
-
2
]],
keypoints
[
points
[
0
][
w
-
1
]]));
corner
.
push_back
(
Segment
(
keypoints
[
points
[
0
][
w
-
1
]],
keypoints
[
points
[
1
][
w
-
1
]]));
segments
.
push_back
(
corner
);
cornerIndices
.
push_back
(
Point
(
w
-
1
,
0
));
firstSteps
.
push_back
(
Point
(
0
,
1
));
secondSteps
.
push_back
(
Point
(
-
1
,
0
));
corner
.
clear
();
corner
.
push_back
(
Segment
(
keypoints
[
points
[
h
-
2
][
w
-
1
]],
keypoints
[
points
[
h
-
1
][
w
-
1
]]));
corner
.
push_back
(
Segment
(
keypoints
[
points
[
h
-
1
][
w
-
1
]],
keypoints
[
points
[
h
-
1
][
w
-
2
]]));
segments
.
push_back
(
corner
);
cornerIndices
.
push_back
(
Point
(
w
-
1
,
h
-
1
));
firstSteps
.
push_back
(
Point
(
-
1
,
0
));
secondSteps
.
push_back
(
Point
(
0
,
-
1
));
corner
.
clear
();
corner
.
push_back
(
Segment
(
keypoints
[
points
[
h
-
1
][
1
]],
keypoints
[
points
[
h
-
1
][
0
]]));
corner
.
push_back
(
Segment
(
keypoints
[
points
[
h
-
1
][
0
]],
keypoints
[
points
[
h
-
2
][
0
]]));
cornerIndices
.
push_back
(
Point
(
0
,
h
-
1
));
firstSteps
.
push_back
(
Point
(
0
,
-
1
));
secondSteps
.
push_back
(
Point
(
1
,
0
));
segments
.
push_back
(
corner
);
corner
.
clear
();
//y axis is inverted in computer vision so we check < 0
bool
isClockwise
=
getDirection
(
keypoints
[
points
[
0
][
0
]],
keypoints
[
points
[
0
][
w
-
1
]],
keypoints
[
points
[
h
-
1
][
w
-
1
]])
<
0
;
if
(
!
isClockwise
)
{
#ifdef DEBUG_CIRCLES
cout
<<
"Corners are counterclockwise"
<<
endl
;
#endif
std
::
reverse
(
segments
.
begin
(),
segments
.
end
());
}
}
bool
CirclesGridFinder
::
doesIntersectionExist
(
const
vector
<
Segment
>
&
corner
,
const
vector
<
vector
<
Segment
>
>
&
segments
)
{
for
(
size_t
i
=
0
;
i
<
corner
.
size
();
i
++
)
{
for
(
size_t
j
=
0
;
j
<
segments
.
size
();
j
++
)
{
for
(
size_t
k
=
0
;
k
<
segments
[
j
].
size
();
k
++
)
{
if
(
areSegmentsIntersecting
(
corner
[
i
],
segments
[
j
][
k
]))
return
true
;
}
}
}
return
false
;
}
size_t
CirclesGridFinder
::
getFirstCorner
(
vector
<
Point
>
&
largeCornerIndices
,
vector
<
Point
>
&
smallCornerIndices
,
vector
<
Point
>
&
firstSteps
,
vector
<
Point
>
&
secondSteps
)
const
{
vector
<
vector
<
Segment
>
>
largeSegments
;
vector
<
vector
<
Segment
>
>
smallSegments
;
getCornerSegments
(
*
largeHoles
,
largeSegments
,
largeCornerIndices
,
firstSteps
,
secondSteps
);
getCornerSegments
(
*
smallHoles
,
smallSegments
,
smallCornerIndices
,
firstSteps
,
secondSteps
);
const
size_t
cornersCount
=
4
;
CV_Assert
(
largeSegments
.
size
()
==
cornersCount
)
;
bool
isInsider
[
cornersCount
];
for
(
size_t
i
=
0
;
i
<
cornersCount
;
i
++
)
{
isInsider
[
i
]
=
doesIntersectionExist
(
largeSegments
[
i
],
smallSegments
);
}
int
cornerIdx
=
0
;
bool
waitOutsider
=
true
;
while
(
true
)
{
if
(
waitOutsider
)
{
if
(
!
isInsider
[(
cornerIdx
+
1
)
%
cornersCount
])
waitOutsider
=
false
;
}
else
{
if
(
isInsider
[(
cornerIdx
+
1
)
%
cornersCount
])
break
;
}
cornerIdx
=
(
cornerIdx
+
1
)
%
cornersCount
;
}
return
cornerIdx
;
}
modules/calib3d/src/circlesgrid.hpp
View file @
f8e9f65e
/*M///////////////////////////////////////////////////////////////////////////////////////
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//
// By downloading, copying, installing or using the software you agree to this license.
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// If you do not agree to this license, do not download, install,
// copy or use the software.
// copy or use the software.
//
//
//
//
// License Agreement
// License Agreement
// For Open Source Computer Vision Library
// For Open Source Computer Vision Library
//
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
// Third party copyrights are property of their respective owners.
//
//
// Redistribution and use in source and binary forms, with or without modification,
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// are permitted provided that the following conditions are met:
//
//
// * Redistribution's of source code must retain the above copyright notice,
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// this list of conditions and the following disclaimer.
//
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// and/or other materials provided with the distribution.
//
//
// * The name of the copyright holders may not be used to endorse or promote products
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
// derived from this software without specific prior written permission.
//
//
// This software is provided by the copyright holders and contributors "as is" and
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
// the use of this software, even if advised of the possibility of such damage.
//
//
//M*/
//M*/
#ifndef CIRCLESGRID_HPP_
#ifndef CIRCLESGRID_HPP_
#define CIRCLESGRID_HPP_
#define CIRCLESGRID_HPP_
...
@@ -51,22 +51,23 @@
...
@@ -51,22 +51,23 @@
class
Graph
class
Graph
{
{
public
:
public
:
typedef
std
::
set
<
in
t
>
Neighbors
;
typedef
std
::
set
<
size_
t
>
Neighbors
;
struct
Vertex
struct
Vertex
{
{
Neighbors
neighbors
;
Neighbors
neighbors
;
};
};
typedef
std
::
map
<
int
,
Vertex
>
Vertices
;
typedef
std
::
map
<
size_t
,
Vertex
>
Vertices
;
Graph
(
int
n
);
Graph
(
size_t
n
);
bool
doesVertexExist
(
int
id
)
const
;
void
addVertex
(
size_t
id
);
void
addVertex
(
int
id
);
void
addEdge
(
size_t
id1
,
size_t
id2
);
void
addEdge
(
int
id1
,
int
id2
);
void
removeEdge
(
size_t
id1
,
size_t
id2
);
bool
areVerticesAdjacent
(
int
id1
,
int
id2
)
const
;
bool
doesVertexExist
(
size_t
id
)
const
;
bool
areVerticesAdjacent
(
size_t
id1
,
size_t
id2
)
const
;
size_t
getVerticesCount
()
const
;
size_t
getVerticesCount
()
const
;
size_t
getDegree
(
int
id
)
const
;
size_t
getDegree
(
size_t
id
)
const
;
const
Neighbors
&
getNeighbors
(
size_t
id
)
const
;
void
floydWarshall
(
cv
::
Mat
&
distanceMatrix
,
int
infinity
=
-
1
)
const
;
void
floydWarshall
(
cv
::
Mat
&
distanceMatrix
,
int
infinity
=
-
1
)
const
;
private
:
private
:
Vertices
vertices
;
Vertices
vertices
;
};
};
...
@@ -77,7 +78,7 @@ struct Path
...
@@ -77,7 +78,7 @@ struct Path
int
lastVertex
;
int
lastVertex
;
int
length
;
int
length
;
std
::
vector
<
in
t
>
vertices
;
std
::
vector
<
size_
t
>
vertices
;
Path
(
int
first
=
-
1
,
int
last
=
-
1
,
int
len
=
-
1
)
Path
(
int
first
=
-
1
,
int
last
=
-
1
,
int
len
=
-
1
)
{
{
...
@@ -102,6 +103,13 @@ struct CirclesGridFinderParameters
...
@@ -102,6 +103,13 @@ struct CirclesGridFinderParameters
float
edgeGain
;
float
edgeGain
;
float
edgePenalty
;
float
edgePenalty
;
float
convexHullFactor
;
float
convexHullFactor
;
float
minRNGEdgeSwitchDist
;
enum
GridType
{
SYMMETRIC_GRID
,
ASYMMETRIC_GRID
};
GridType
gridType
;
};
};
class
CirclesGridFinder
class
CirclesGridFinder
...
@@ -110,43 +118,68 @@ public:
...
@@ -110,43 +118,68 @@ public:
CirclesGridFinder
(
cv
::
Size
patternSize
,
const
std
::
vector
<
cv
::
Point2f
>
&
testKeypoints
,
CirclesGridFinder
(
cv
::
Size
patternSize
,
const
std
::
vector
<
cv
::
Point2f
>
&
testKeypoints
,
const
CirclesGridFinderParameters
&
parameters
=
CirclesGridFinderParameters
());
const
CirclesGridFinderParameters
&
parameters
=
CirclesGridFinderParameters
());
bool
findHoles
();
bool
findHoles
();
static
cv
::
Mat
rectifyGrid
(
cv
::
Size
detectedGridSize
,
const
std
::
vector
<
cv
::
Point2f
>&
centers
,
static
cv
::
Mat
rectifyGrid
(
cv
::
Size
detectedGridSize
,
const
std
::
vector
<
cv
::
Point2f
>&
centers
,
const
std
::
vector
<
const
std
::
vector
<
cv
::
Point2f
>
&
keypoint
,
std
::
vector
<
cv
::
Point2f
>
&
warpedKeypoints
);
cv
::
Point2f
>
&
keypoint
,
std
::
vector
<
cv
::
Point2f
>
&
warpedKeypoints
);
void
getHoles
(
std
::
vector
<
cv
::
Point2f
>
&
holes
)
const
;
void
getHoles
(
std
::
vector
<
cv
::
Point2f
>
&
holes
)
const
;
void
getAsymmetricHoles
(
std
::
vector
<
cv
::
Point2f
>
&
holes
)
const
;
cv
::
Size
getDetectedGridSize
()
const
;
cv
::
Size
getDetectedGridSize
()
const
;
void
drawBasis
(
const
std
::
vector
<
cv
::
Point2f
>
&
basis
,
cv
::
Point2f
origin
,
cv
::
Mat
&
drawImg
)
const
;
void
drawBasis
(
const
std
::
vector
<
cv
::
Point2f
>
&
basis
,
cv
::
Point2f
origin
,
cv
::
Mat
&
drawImg
)
const
;
void
drawBasisGraphs
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
cv
::
Mat
&
drawImg
,
bool
drawEdges
=
true
,
bool
drawVertices
=
void
drawBasisGraphs
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
cv
::
Mat
&
drawImg
,
bool
drawEdges
=
true
,
true
)
const
;
bool
drawVertices
=
true
)
const
;
void
drawHoles
(
const
cv
::
Mat
&
srcImage
,
cv
::
Mat
&
drawImage
)
const
;
void
drawHoles
(
const
cv
::
Mat
&
srcImage
,
cv
::
Mat
&
drawImage
)
const
;
private
:
private
:
void
computeEdgeVectorsOfRNG
(
std
::
vector
<
cv
::
Point2f
>
&
vectors
,
cv
::
Mat
*
drawImage
=
0
)
const
;
void
computeRNG
(
Graph
&
rng
,
std
::
vector
<
cv
::
Point2f
>
&
vectors
,
cv
::
Mat
*
drawImage
=
0
)
const
;
void
rng2gridGraph
(
Graph
&
rng
,
std
::
vector
<
cv
::
Point2f
>
&
vectors
)
const
;
void
eraseUsedGraph
(
vector
<
Graph
>
&
basisGraphs
)
const
;
void
filterOutliersByDensity
(
const
std
::
vector
<
cv
::
Point2f
>
&
samples
,
std
::
vector
<
cv
::
Point2f
>
&
filteredSamples
);
void
filterOutliersByDensity
(
const
std
::
vector
<
cv
::
Point2f
>
&
samples
,
std
::
vector
<
cv
::
Point2f
>
&
filteredSamples
);
void
findBasis
(
const
std
::
vector
<
cv
::
Point2f
>
&
samples
,
std
::
vector
<
cv
::
Point2f
>
&
basis
,
std
::
vector
<
Graph
>
&
basisGraphs
);
void
findBasis
(
const
std
::
vector
<
cv
::
Point2f
>
&
samples
,
std
::
vector
<
cv
::
Point2f
>
&
basis
,
std
::
vector
<
Graph
>
&
basisGraphs
);
void
findMCS
(
const
std
::
vector
<
cv
::
Point2f
>
&
basis
,
std
::
vector
<
Graph
>
&
basisGraphs
);
void
findMCS
(
const
std
::
vector
<
cv
::
Point2f
>
&
basis
,
std
::
vector
<
Graph
>
&
basisGraphs
);
size_t
findLongestPath
(
std
::
vector
<
Graph
>
&
basisGraphs
,
Path
&
bestPath
);
size_t
findLongestPath
(
std
::
vector
<
Graph
>
&
basisGraphs
,
Path
&
bestPath
);
float
computeGraphConfidence
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
const
std
::
vector
<
int
>
&
points
,
const
std
::
vector
<
float
computeGraphConfidence
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
const
std
::
vector
<
size_t
>
&
points
,
in
t
>
&
seeds
);
const
std
::
vector
<
size_
t
>
&
seeds
);
void
addHolesByGraph
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
cv
::
Point2f
basisVec
);
void
addHolesByGraph
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
cv
::
Point2f
basisVec
);
int
findNearestKeypoint
(
cv
::
Point2f
pt
)
const
;
size_t
findNearestKeypoint
(
cv
::
Point2f
pt
)
const
;
void
addPoint
(
cv
::
Point2f
pt
,
std
::
vector
<
int
>
&
points
);
void
addPoint
(
cv
::
Point2f
pt
,
std
::
vector
<
size_t
>
&
points
);
void
findCandidateLine
(
std
::
vector
<
int
>
&
line
,
int
seedLineIdx
,
bool
addRow
,
cv
::
Point2f
basisVec
,
std
::
vector
<
int
>
&
seeds
);
void
findCandidateLine
(
std
::
vector
<
size_t
>
&
line
,
size_t
seedLineIdx
,
bool
addRow
,
cv
::
Point2f
basisVec
,
std
::
vector
<
void
findCandidateHoles
(
std
::
vector
<
int
>
&
above
,
std
::
vector
<
int
>
&
below
,
bool
addRow
,
cv
::
Point2f
basisVec
,
size_t
>
&
seeds
);
std
::
vector
<
int
>
&
aboveSeeds
,
std
::
vector
<
int
>
&
belowSeeds
);
void
findCandidateHoles
(
std
::
vector
<
size_t
>
&
above
,
std
::
vector
<
size_t
>
&
below
,
bool
addRow
,
cv
::
Point2f
basisVec
,
static
bool
areCentersNew
(
const
std
::
vector
<
int
>
&
newCenters
,
const
std
::
vector
<
std
::
vector
<
int
>
>
&
holes
);
std
::
vector
<
size_t
>
&
aboveSeeds
,
std
::
vector
<
size_t
>
&
belowSeeds
);
static
bool
areCentersNew
(
const
std
::
vector
<
size_t
>
&
newCenters
,
const
std
::
vector
<
std
::
vector
<
size_t
>
>
&
holes
);
bool
isDetectionCorrect
();
bool
isDetectionCorrect
();
static
void
insertWinner
(
float
aboveConfidence
,
float
belowConfidence
,
float
minConfidence
,
static
void
insertWinner
(
float
aboveConfidence
,
float
belowConfidence
,
float
minConfidence
,
bool
addRow
,
bool
addRow
,
const
std
::
vector
<
size_t
>
&
above
,
const
std
::
vector
<
size_t
>
&
below
,
std
::
vector
<
std
::
vector
<
const
std
::
vector
<
int
>
&
above
,
const
std
::
vector
<
int
>
&
below
,
std
::
vector
<
std
::
vector
<
int
>
>
&
holes
);
size_t
>
>
&
holes
);
static
bool
areVerticesAdjacent
(
const
Graph
&
graph
,
int
vertex1
,
int
vertex2
);
struct
Segment
{
cv
::
Point2f
s
;
cv
::
Point2f
e
;
Segment
(
cv
::
Point2f
_s
,
cv
::
Point2f
_e
);
};
//if endpoint is on a segment then function return false
static
bool
areSegmentsIntersecting
(
Segment
seg1
,
Segment
seg2
);
static
bool
doesIntersectionExist
(
const
vector
<
Segment
>
&
corner
,
const
vector
<
vector
<
Segment
>
>
&
segments
);
void
getCornerSegments
(
const
vector
<
vector
<
size_t
>
>
&
points
,
vector
<
vector
<
Segment
>
>
&
segments
,
vector
<
cv
::
Point
>
&
cornerIndices
,
vector
<
cv
::
Point
>
&
firstSteps
,
vector
<
cv
::
Point
>
&
secondSteps
)
const
;
size_t
getFirstCorner
(
vector
<
cv
::
Point
>
&
largeCornerIndices
,
vector
<
cv
::
Point
>
&
smallCornerIndices
,
vector
<
cv
::
Point
>
&
firstSteps
,
vector
<
cv
::
Point
>
&
secondSteps
)
const
;
static
double
getDirection
(
cv
::
Point2f
p1
,
cv
::
Point2f
p2
,
cv
::
Point2f
p3
);
std
::
vector
<
cv
::
Point2f
>
keypoints
;
std
::
vector
<
cv
::
Point2f
>
keypoints
;
std
::
vector
<
std
::
vector
<
int
>
>
holes
;
std
::
vector
<
std
::
vector
<
size_t
>
>
holes
;
const
cv
::
Size
patternSize
;
std
::
vector
<
std
::
vector
<
size_t
>
>
holes2
;
std
::
vector
<
std
::
vector
<
size_t
>
>
*
largeHoles
;
std
::
vector
<
std
::
vector
<
size_t
>
>
*
smallHoles
;
const
cv
::
Size_
<
size_t
>
patternSize
;
CirclesGridFinderParameters
parameters
;
CirclesGridFinderParameters
parameters
;
};
};
...
...
modules/features2d/src/blobdetector.cpp
View file @
f8e9f65e
/*M///////////////////////////////////////////////////////////////////////////////////////
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//
// By downloading, copying, installing or using the software you agree to this license.
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// If you do not agree to this license, do not download, install,
// copy or use the software.
// copy or use the software.
//
//
//
//
// License Agreement
// License Agreement
// For Open Source Computer Vision Library
// For Open Source Computer Vision Library
//
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
// Third party copyrights are property of their respective owners.
//
//
// Redistribution and use in source and binary forms, with or without modification,
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// are permitted provided that the following conditions are met:
//
//
// * Redistribution's of source code must retain the above copyright notice,
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// this list of conditions and the following disclaimer.
//
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// and/or other materials provided with the distribution.
//
//
// * The name of the copyright holders may not be used to endorse or promote products
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
// derived from this software without specific prior written permission.
//
//
// This software is provided by the copyright holders and contributors "as is" and
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
// the use of this software, even if advised of the possibility of such damage.
//
//
//M*/
//M*/
#include "precomp.hpp"
#include "precomp.hpp"
//#define DEBUG_BLOB_DETECTOR
#ifdef DEBUG_BLOB_DETECTOR
#include <opencv2/highgui/highgui.hpp>
#endif
using
namespace
cv
;
using
namespace
cv
;
/*
/*
...
@@ -116,17 +122,19 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
...
@@ -116,17 +122,19 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
{
{
centers
.
clear
();
centers
.
clear
();
vector
<
vector
<
Point
>
>
contours
;
vector
<
vector
<
Point
>
>
contours
;
Mat
tmpBinaryImage
=
binaryImage
.
clone
();
Mat
tmpBinaryImage
=
binaryImage
.
clone
();
findContours
(
tmpBinaryImage
,
contours
,
CV_RETR_LIST
,
CV_CHAIN_APPROX_NONE
);
findContours
(
tmpBinaryImage
,
contours
,
CV_RETR_LIST
,
CV_CHAIN_APPROX_NONE
);
//Mat keypointsImage;
#ifdef DEBUG_BLOB_DETECTOR
//cvtColor( binaryImage, keypointsImage, CV_GRAY2RGB );
Mat
keypointsImage
;
cvtColor
(
binaryImage
,
keypointsImage
,
CV_GRAY2RGB
);
//Mat contoursImage;
Mat
contoursImage
;
//cvtColor( binaryImage, contoursImage, CV_GRAY2RGB );
cvtColor
(
binaryImage
,
contoursImage
,
CV_GRAY2RGB
);
//drawContours( contoursImage, contours, -1, Scalar(0,255,0) );
drawContours
(
contoursImage
,
contours
,
-
1
,
Scalar
(
0
,
255
,
0
)
);
//imshow("contours", contoursImage );
imshow
(
"contours"
,
contoursImage
);
#endif
for
(
size_t
contourIdx
=
0
;
contourIdx
<
contours
.
size
();
contourIdx
++
)
for
(
size_t
contourIdx
=
0
;
contourIdx
<
contours
.
size
();
contourIdx
++
)
{
{
...
@@ -178,7 +186,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
...
@@ -178,7 +186,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
if
(
params
.
filterByConvexity
)
if
(
params
.
filterByConvexity
)
{
{
vector
<
Point
>
hull
;
vector
<
Point
>
hull
;
convexHull
(
Mat
(
contours
[
contourIdx
]),
hull
);
convexHull
(
Mat
(
contours
[
contourIdx
]),
hull
);
double
area
=
contourArea
(
Mat
(
contours
[
contourIdx
]));
double
area
=
contourArea
(
Mat
(
contours
[
contourIdx
]));
double
hullArea
=
contourArea
(
Mat
(
hull
));
double
hullArea
=
contourArea
(
Mat
(
hull
));
...
@@ -212,14 +220,19 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
...
@@ -212,14 +220,19 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
centers
.
push_back
(
center
);
centers
.
push_back
(
center
);
//circle( keypointsImage, center.location, 1, Scalar(0,0,255), 1 );
#ifdef DEBUG_BLOB_DETECTOR
circle
(
keypointsImage
,
center
.
location
,
1
,
Scalar
(
0
,
0
,
255
),
1
);
#endif
}
}
//imshow("bk", keypointsImage );
#ifdef DEBUG_BLOB_DETECTOR
//waitKey();
imshow
(
"bk"
,
keypointsImage
);
waitKey
();
#endif
}
}
void
SimpleBlobDetector
::
detectImpl
(
const
cv
::
Mat
&
image
,
std
::
vector
<
cv
::
KeyPoint
>&
keypoints
,
const
cv
::
Mat
&
mask
)
const
void
SimpleBlobDetector
::
detectImpl
(
const
cv
::
Mat
&
image
,
std
::
vector
<
cv
::
KeyPoint
>&
keypoints
,
const
cv
::
Mat
&
)
const
{
{
//TODO: support mask
keypoints
.
clear
();
keypoints
.
clear
();
Mat
grayscaleImage
;
Mat
grayscaleImage
;
if
(
image
.
channels
()
==
3
)
if
(
image
.
channels
()
==
3
)
...
@@ -227,7 +240,7 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
...
@@ -227,7 +240,7 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
else
else
grayscaleImage
=
image
;
grayscaleImage
=
image
;
vector
<
vector
<
Center
>
>
centers
;
vector
<
vector
<
Center
>
>
centers
;
for
(
double
thresh
=
params
.
minThreshold
;
thresh
<
params
.
maxThreshold
;
thresh
+=
params
.
thresholdStep
)
for
(
double
thresh
=
params
.
minThreshold
;
thresh
<
params
.
maxThreshold
;
thresh
+=
params
.
thresholdStep
)
{
{
Mat
binarizedImage
;
Mat
binarizedImage
;
...
@@ -236,8 +249,9 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
...
@@ -236,8 +249,9 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
//Mat keypointsImage;
//Mat keypointsImage;
//cvtColor( binarizedImage, keypointsImage, CV_GRAY2RGB );
//cvtColor( binarizedImage, keypointsImage, CV_GRAY2RGB );
vector
<
Center
>
curCenters
;
vector
<
Center
>
curCenters
;
findBlobs
(
grayscaleImage
,
binarizedImage
,
curCenters
);
findBlobs
(
grayscaleImage
,
binarizedImage
,
curCenters
);
vector
<
vector
<
Center
>
>
newCenters
;
for
(
size_t
i
=
0
;
i
<
curCenters
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
curCenters
.
size
();
i
++
)
{
{
//circle(keypointsImage, curCenters[i].location, 1, Scalar(0,0,255),-1);
//circle(keypointsImage, curCenters[i].location, 1, Scalar(0,0,255),-1);
...
@@ -262,9 +276,12 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
...
@@ -262,9 +276,12 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
}
}
if
(
isNew
)
if
(
isNew
)
{
{
centers
.
push_back
(
vector
<
Center
>
(
1
,
curCenters
[
i
]));
newCenters
.
push_back
(
vector
<
Center
>
(
1
,
curCenters
[
i
]));
//centers.push_back(vector<Center> (1, curCenters[i]));
}
}
}
}
std
::
copy
(
newCenters
.
begin
(),
newCenters
.
end
(),
std
::
back_inserter
(
centers
));
//imshow("binarized", keypointsImage );
//imshow("binarized", keypointsImage );
//waitKey();
//waitKey();
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment