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,
const
vector
<
Point2f
>&
corners
,
bool
patternWasFound
);
enum
{
CALIB_CB_SYMMETRIC_GRID
=
1
,
CALIB_CB_ASYMMETRIC_GRID
=
2
};
//! finds circles' grid pattern of the specified size in the image
CV_EXPORTS_W
bool
findCirclesGrid
(
const
Mat
&
image
,
Size
patternSize
,
CV_OUT
vector
<
Point2f
>&
centers
,
int
flags
=
0
);
int
flags
=
CALIB_CB_SYMMETRIC_GRID
);
enum
{
...
...
modules/calib3d/src/calibinit.cpp
View file @
f8e9f65e
...
...
@@ -1935,7 +1935,7 @@ void drawChessboardCorners( 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<FeatureDetector> detector = new MserFeatureDetector();
...
...
@@ -1944,7 +1944,7 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
vector
<
Point2f
>
points
;
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
i
++
)
{
points
.
push_back
(
keypoints
[
i
].
pt
);
points
.
push_back
(
keypoints
[
i
].
pt
);
}
CirclesGridFinderParameters
parameters
;
...
...
@@ -1954,8 +1954,13 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
parameters
.
edgeGain
=
1
;
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
in
t
minHomographyPoints
=
4
;
const
size_
t
minHomographyPoints
=
4
;
Mat
H
;
for
(
int
i
=
0
;
i
<
attempts
;
i
++
)
{
...
...
@@ -1970,10 +1975,20 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
{
}
boxFinder
.
getHoles
(
centers
);
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
)
{
Mat
orgPointsMat
;
...
...
@@ -1983,7 +1998,8 @@ bool findCirclesGrid( const Mat& image, Size patternSize,
return
true
;
}
boxFinder
.
getHoles
(
centers
);
if
(
i
!=
attempts
-
1
)
{
if
(
centers
.
size
()
<
minHomographyPoints
)
...
...
modules/calib3d/src/circlesgrid.cpp
View file @
f8e9f65e
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// 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,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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
// 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,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// 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.
//
//M*/
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// 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,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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
// 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,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// 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.
//
//M*/
#include "circlesgrid.hpp"
//#define DEBUG_CIRCLES
using
namespace
cv
;
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
);
}
}
bool
Graph
::
doesVertexExist
(
in
t
id
)
const
bool
Graph
::
doesVertexExist
(
size_
t
id
)
const
{
return
(
vertices
.
find
(
id
)
!=
vertices
.
end
());
}
void
Graph
::
addVertex
(
in
t
id
)
void
Graph
::
addVertex
(
size_
t
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
(
id2
)
);
...
...
@@ -74,7 +75,16 @@ void Graph::addEdge(int id1, int id2)
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
(
id2
)
);
...
...
@@ -88,7 +98,7 @@ size_t Graph::getVerticesCount() const
return
vertices
.
size
();
}
size_t
Graph
::
getDegree
(
in
t
id
)
const
size_t
Graph
::
getDegree
(
size_
t
id
)
const
{
assert
(
doesVertexExist
(
id
)
);
...
...
@@ -126,13 +136,28 @@ void Graph::floydWarshall(cv::Mat &distanceMatrix, int infinity) const
==
infinity
)
val2
=
val1
;
else
{
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
computePredecessorMatrix
(
const
Mat
&
dm
,
int
verticesCount
,
Mat
&
predecessorMatrix
);
...
...
@@ -151,54 +176,210 @@ CirclesGridFinderParameters::CirclesGridFinderParameters()
edgeGain
=
1
;
edgePenalty
=
-
5
;
existingVertexGain
=
0
;
minRNGEdgeSwitchDist
=
5.
f
;
gridType
=
SYMMETRIC_GRID
;
}
CirclesGridFinder
::
CirclesGridFinder
(
Size
_patternSize
,
const
vector
<
Point2f
>
&
testKeypoints
,
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
;
parameters
=
_parameters
;
largeHoles
=
0
;
smallHoles
=
0
;
}
bool
CirclesGridFinder
::
findHoles
()
{
vector
<
Point2f
>
vectors
,
filteredVectors
,
basis
;
computeEdgeVectorsOfRNG
(
vectors
);
filterOutliersByDensity
(
vectors
,
filteredVectors
);
vector
<
Graph
>
basisGraphs
;
findBasis
(
filteredVectors
,
basis
,
basisGraphs
);
findMCS
(
basis
,
basisGraphs
);
switch
(
parameters
.
gridType
)
{
case
CirclesGridFinderParameters
:
:
SYMMETRIC_GRID
:
{
vector
<
Point2f
>
vectors
,
filteredVectors
,
basis
;
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
());
//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
)
return
false
;
for
(
size_t
i
=
0
;
i
<
rng
.
getVerticesCount
();
i
++
)
{
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
++
)
{
if
(
holes
[
i
].
size
()
!=
patternSize
.
width
)
return
false
;
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
)
{
holes
.
clear
();
Path
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
))
{
...
...
@@ -209,14 +390,14 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
if
(
bestGraphIdx
==
0
)
{
holes
.
push_back
(
holesRow
);
in
t
w
=
holes
[
0
].
size
();
in
t
h
=
holes
.
size
();
size_
t
w
=
holes
[
0
].
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() / 2) * parameters.edgeGain;
//parameters.minGraphConfidence = holes[0].size() * parameters.existingVertexGain + (holes[0].size() / 2) * parameters.edgeGain;
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
]);
}
...
...
@@ -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
;
for
(
in
t
i
=
w
;
i
<
patternSize
.
width
;
i
++
)
for
(
size_
t
i
=
w
;
i
<
patternSize
.
width
;
i
++
)
{
addHolesByGraph
(
basisGraphs
,
false
,
basis
[
0
]);
}
...
...
@@ -235,17 +416,17 @@ void CirclesGridFinder::findMCS(const vector<Point2f> &basis, vector<Graph> &bas
for
(
size_t
i
=
0
;
i
<
holesRow
.
size
();
i
++
)
holes
[
i
].
push_back
(
holesRow
[
i
]);
in
t
w
=
holes
[
0
].
size
();
in
t
h
=
holes
.
size
();
size_
t
w
=
holes
[
0
].
size
();
size_
t
h
=
holes
.
size
();
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
]);
}
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
]);
}
...
...
@@ -292,9 +473,9 @@ Mat CirclesGridFinder::rectifyGrid(Size detectedGridSize, const vector<Point2f>&
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
();
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
i
++
)
{
...
...
@@ -308,9 +489,9 @@ int CirclesGridFinder::findNearestKeypoint(Point2f pt) const
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
)
{
Point2f
kpt
=
Point2f
(
pt
);
...
...
@@ -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
,
vector
<
in
t
>
&
seeds
)
void
CirclesGridFinder
::
findCandidateLine
(
vector
<
size_t
>
&
line
,
size_
t
seedLineIdx
,
bool
addRow
,
Point2f
basisVec
,
vector
<
size_
t
>
&
seeds
)
{
line
.
clear
();
seeds
.
clear
();
...
...
@@ -351,8 +532,8 @@ void CirclesGridFinder::findCandidateLine(vector<int> &line, int seedLineIdx, bo
assert
(
line
.
size
()
==
seeds
.
size
()
);
}
void
CirclesGridFinder
::
findCandidateHoles
(
vector
<
int
>
&
above
,
vector
<
in
t
>
&
below
,
bool
addRow
,
Point2f
basisVec
,
vector
<
int
>
&
aboveSeeds
,
vector
<
in
t
>
&
belowSeeds
)
void
CirclesGridFinder
::
findCandidateHoles
(
vector
<
size_t
>
&
above
,
vector
<
size_
t
>
&
below
,
bool
addRow
,
Point2f
basisVec
,
vector
<
size_t
>
&
aboveSeeds
,
vector
<
size_
t
>
&
belowSeeds
)
{
above
.
clear
();
below
.
clear
();
...
...
@@ -360,7 +541,7 @@ void CirclesGridFinder::findCandidateHoles(vector<int> &above, vector<int> &belo
belowSeeds
.
clear
();
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
);
assert
(
below
.
size
()
==
above
.
size
()
);
...
...
@@ -368,7 +549,7 @@ void CirclesGridFinder::findCandidateHoles(vector<int> &above, vector<int> &belo
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
++
)
{
...
...
@@ -385,7 +566,8 @@ bool CirclesGridFinder::areCentersNew(const vector<int> &newCenters, const vecto
}
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
)
return
;
...
...
@@ -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
,
const
vector
<
int
>
&
points
,
const
vector
<
in
t
>
&
seeds
)
const
vector
<
size_t
>
&
points
,
const
vector
<
size_
t
>
&
seeds
)
{
assert
(
points
.
size
()
==
seeds
.
size
()
);
float
confidence
=
0
;
const
in
t
vCount
=
basisGraphs
[
0
].
getVerticesCount
();
const
size_
t
vCount
=
basisGraphs
[
0
].
getVerticesCount
();
assert
(
basisGraphs
[
0
].
getVerticesCount
()
==
basisGraphs
[
1
].
getVerticesCount
()
);
for
(
size_t
i
=
0
;
i
<
seeds
.
size
();
i
++
)
...
...
@@ -498,7 +662,7 @@ float CirclesGridFinder::computeGraphConfidence(const vector<Graph> &basisGraphs
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
);
float
aboveConfidence
=
computeGraphConfidence
(
basisGraphs
,
addRow
,
above
,
aboveSeeds
);
float
belowConfidence
=
computeGraphConfidence
(
basisGraphs
,
addRow
,
below
,
belowSeeds
);
...
...
@@ -537,7 +701,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
Mat
bestLabels
;
TermCriteria
termCriteria
;
Mat
centers
;
int
clustersCount
=
4
;
const
int
clustersCount
=
4
;
kmeans
(
Mat
(
samples
).
reshape
(
1
,
0
),
clustersCount
,
bestLabels
,
termCriteria
,
parameters
.
kmeansAttempts
,
KMEANS_RANDOM_CENTERS
,
&
centers
);
assert
(
centers
.
type
()
==
CV_32FC1
);
...
...
@@ -555,7 +719,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
}
}
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
)
{
...
...
@@ -565,7 +729,7 @@ void CirclesGridFinder::findBasis(const vector<Point2f> &samples, vector<Point2f
const
float
minBasisDif
=
2
;
if
(
norm
(
basis
[
0
]
-
basis
[
1
])
<
minBasisDif
)
CV_Error
(
0
,
"degenerate basis"
);
CV_Error
(
0
,
"degenerate basis"
);
vector
<
vector
<
Point2f
>
>
clusters
(
2
),
hulls
(
2
);
for
(
size_t
k
=
0
;
k
<
samples
.
size
();
k
++
)
...
...
@@ -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
();
//TODO: use more fast algorithm instead of naive N^3
...
...
@@ -639,6 +806,7 @@ void CirclesGridFinder::computeEdgeVectorsOfRNG(vector<Point2f> &vectors, Mat *d
if
(
isNeighbors
)
{
rng
.
addEdge
(
i
,
j
);
vectors
.
push_back
(
keypoints
[
i
]
-
keypoints
[
j
]);
if
(
drawImage
!=
0
)
{
...
...
@@ -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
)
{
...
...
@@ -714,7 +882,11 @@ size_t CirclesGridFinder::findLongestPath(vector<Graph> &basisGraphs, Path &best
if
(
longestPaths
.
empty
()
||
(
maxVal
==
longestPaths
[
0
].
length
&&
graphIdx
==
bestGraphIdx
))
{
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
);
int
conf
=
0
;
...
...
@@ -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///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// 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,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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
// 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,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// 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.
//
//M*/
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// 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,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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
// 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,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// 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.
//
//M*/
#ifndef CIRCLESGRID_HPP_
#define CIRCLESGRID_HPP_
...
...
@@ -51,22 +51,23 @@
class
Graph
{
public
:
typedef
std
::
set
<
in
t
>
Neighbors
;
typedef
std
::
set
<
size_
t
>
Neighbors
;
struct
Vertex
{
Neighbors
neighbors
;
};
typedef
std
::
map
<
int
,
Vertex
>
Vertices
;
Graph
(
int
n
);
bool
doesVertexExist
(
int
id
)
const
;
void
addVertex
(
int
id
);
void
addEdge
(
int
id1
,
int
id2
);
bool
areVerticesAdjacent
(
int
id1
,
int
id2
)
const
;
typedef
std
::
map
<
size_t
,
Vertex
>
Vertices
;
Graph
(
size_t
n
);
void
addVertex
(
size_t
id
);
void
addEdge
(
size_t
id1
,
size_t
id2
);
void
removeEdge
(
size_t
id1
,
size_t
id2
);
bool
doesVertexExist
(
size_t
id
)
const
;
bool
areVerticesAdjacent
(
size_t
id1
,
size_t
id2
)
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
;
private
:
Vertices
vertices
;
};
...
...
@@ -77,7 +78,7 @@ struct Path
int
lastVertex
;
int
length
;
std
::
vector
<
in
t
>
vertices
;
std
::
vector
<
size_
t
>
vertices
;
Path
(
int
first
=
-
1
,
int
last
=
-
1
,
int
len
=
-
1
)
{
...
...
@@ -102,6 +103,13 @@ struct CirclesGridFinderParameters
float
edgeGain
;
float
edgePenalty
;
float
convexHullFactor
;
float
minRNGEdgeSwitchDist
;
enum
GridType
{
SYMMETRIC_GRID
,
ASYMMETRIC_GRID
};
GridType
gridType
;
};
class
CirclesGridFinder
...
...
@@ -110,43 +118,68 @@ public:
CirclesGridFinder
(
cv
::
Size
patternSize
,
const
std
::
vector
<
cv
::
Point2f
>
&
testKeypoints
,
const
CirclesGridFinderParameters
&
parameters
=
CirclesGridFinderParameters
());
bool
findHoles
();
static
cv
::
Mat
rectifyGrid
(
cv
::
Size
detectedGridSize
,
const
std
::
vector
<
cv
::
Point2f
>&
centers
,
const
std
::
vector
<
cv
::
Point2f
>
&
keypoint
,
std
::
vector
<
cv
::
Point2f
>
&
warpedKeypoints
);
static
cv
::
Mat
rectifyGrid
(
cv
::
Size
detectedGridSize
,
const
std
::
vector
<
cv
::
Point2f
>&
centers
,
const
std
::
vector
<
cv
::
Point2f
>
&
keypoint
,
std
::
vector
<
cv
::
Point2f
>
&
warpedKeypoints
);
void
getHoles
(
std
::
vector
<
cv
::
Point2f
>
&
holes
)
const
;
void
getAsymmetricHoles
(
std
::
vector
<
cv
::
Point2f
>
&
holes
)
const
;
cv
::
Size
getDetectedGridSize
()
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
=
true
)
const
;
void
drawBasisGraphs
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
cv
::
Mat
&
drawImg
,
bool
drawEdges
=
true
,
bool
drawVertices
=
true
)
const
;
void
drawHoles
(
const
cv
::
Mat
&
srcImage
,
cv
::
Mat
&
drawImage
)
const
;
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
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
);
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
<
in
t
>
&
seeds
);
float
computeGraphConfidence
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
const
std
::
vector
<
size_t
>
&
points
,
const
std
::
vector
<
size_
t
>
&
seeds
);
void
addHolesByGraph
(
const
std
::
vector
<
Graph
>
&
basisGraphs
,
bool
addRow
,
cv
::
Point2f
basisVec
);
int
findNearestKeypoint
(
cv
::
Point2f
pt
)
const
;
void
addPoint
(
cv
::
Point2f
pt
,
std
::
vector
<
int
>
&
points
);
void
findCandidateLine
(
std
::
vector
<
int
>
&
line
,
int
seedLineIdx
,
bool
addRow
,
cv
::
Point2f
basisVec
,
std
::
vector
<
int
>
&
seeds
);
void
findCandidateHoles
(
std
::
vector
<
int
>
&
above
,
std
::
vector
<
int
>
&
below
,
bool
addRow
,
cv
::
Point2f
basisVec
,
std
::
vector
<
int
>
&
aboveSeeds
,
std
::
vector
<
int
>
&
belowSeeds
);
static
bool
areCentersNew
(
const
std
::
vector
<
int
>
&
newCenters
,
const
std
::
vector
<
std
::
vector
<
int
>
>
&
holes
);
size_t
findNearestKeypoint
(
cv
::
Point2f
pt
)
const
;
void
addPoint
(
cv
::
Point2f
pt
,
std
::
vector
<
size_t
>
&
points
);
void
findCandidateLine
(
std
::
vector
<
size_t
>
&
line
,
size_t
seedLineIdx
,
bool
addRow
,
cv
::
Point2f
basisVec
,
std
::
vector
<
size_t
>
&
seeds
);
void
findCandidateHoles
(
std
::
vector
<
size_t
>
&
above
,
std
::
vector
<
size_t
>
&
below
,
bool
addRow
,
cv
::
Point2f
basisVec
,
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
();
static
void
insertWinner
(
float
aboveConfidence
,
float
belowConfidence
,
float
minConfidence
,
bool
addRow
,
const
std
::
vector
<
int
>
&
above
,
const
std
::
vector
<
int
>
&
below
,
std
::
vector
<
std
::
vector
<
int
>
>
&
holes
);
static
bool
areVerticesAdjacent
(
const
Graph
&
graph
,
int
vertex1
,
int
vertex2
);
static
void
insertWinner
(
float
aboveConfidence
,
float
belowConfidence
,
float
minConfidence
,
bool
addRow
,
const
std
::
vector
<
size_t
>
&
above
,
const
std
::
vector
<
size_t
>
&
below
,
std
::
vector
<
std
::
vector
<
size_t
>
>
&
holes
);
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
<
std
::
vector
<
int
>
>
holes
;
const
cv
::
Size
patternSize
;
std
::
vector
<
std
::
vector
<
size_t
>
>
holes
;
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
;
};
...
...
modules/features2d/src/blobdetector.cpp
View file @
f8e9f65e
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// 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,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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
// 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,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// 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.
//
//M*/
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// 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,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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
// 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,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// 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.
//
//M*/
#include "precomp.hpp"
//#define DEBUG_BLOB_DETECTOR
#ifdef DEBUG_BLOB_DETECTOR
#include <opencv2/highgui/highgui.hpp>
#endif
using
namespace
cv
;
/*
...
...
@@ -116,17 +122,19 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
{
centers
.
clear
();
vector
<
vector
<
Point
>
>
contours
;
vector
<
vector
<
Point
>
>
contours
;
Mat
tmpBinaryImage
=
binaryImage
.
clone
();
findContours
(
tmpBinaryImage
,
contours
,
CV_RETR_LIST
,
CV_CHAIN_APPROX_NONE
);
//Mat keypointsImage;
//cvtColor( binaryImage, keypointsImage, CV_GRAY2RGB );
#ifdef DEBUG_BLOB_DETECTOR
Mat
keypointsImage
;
cvtColor
(
binaryImage
,
keypointsImage
,
CV_GRAY2RGB
);
//Mat contoursImage;
//cvtColor( binaryImage, contoursImage, CV_GRAY2RGB );
//drawContours( contoursImage, contours, -1, Scalar(0,255,0) );
//imshow("contours", contoursImage );
Mat
contoursImage
;
cvtColor
(
binaryImage
,
contoursImage
,
CV_GRAY2RGB
);
drawContours
(
contoursImage
,
contours
,
-
1
,
Scalar
(
0
,
255
,
0
)
);
imshow
(
"contours"
,
contoursImage
);
#endif
for
(
size_t
contourIdx
=
0
;
contourIdx
<
contours
.
size
();
contourIdx
++
)
{
...
...
@@ -178,7 +186,7 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
if
(
params
.
filterByConvexity
)
{
vector
<
Point
>
hull
;
vector
<
Point
>
hull
;
convexHull
(
Mat
(
contours
[
contourIdx
]),
hull
);
double
area
=
contourArea
(
Mat
(
contours
[
contourIdx
]));
double
hullArea
=
contourArea
(
Mat
(
hull
));
...
...
@@ -212,14 +220,19 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
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 );
//waitKey();
#ifdef DEBUG_BLOB_DETECTOR
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
();
Mat
grayscaleImage
;
if
(
image
.
channels
()
==
3
)
...
...
@@ -227,7 +240,7 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
else
grayscaleImage
=
image
;
vector
<
vector
<
Center
>
>
centers
;
vector
<
vector
<
Center
>
>
centers
;
for
(
double
thresh
=
params
.
minThreshold
;
thresh
<
params
.
maxThreshold
;
thresh
+=
params
.
thresholdStep
)
{
Mat
binarizedImage
;
...
...
@@ -236,8 +249,9 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
//Mat keypointsImage;
//cvtColor( binarizedImage, keypointsImage, CV_GRAY2RGB );
vector
<
Center
>
curCenters
;
vector
<
Center
>
curCenters
;
findBlobs
(
grayscaleImage
,
binarizedImage
,
curCenters
);
vector
<
vector
<
Center
>
>
newCenters
;
for
(
size_t
i
=
0
;
i
<
curCenters
.
size
();
i
++
)
{
//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
}
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 );
//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