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
aa19fd50
Commit
aa19fd50
authored
Mar 18, 2012
by
Marina Kolpakova
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed bug #1654
parent
2ca6a505
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
755 additions
and
752 deletions
+755
-752
chamfermatching.cpp
modules/contrib/src/chamfermatching.cpp
+755
-752
No files found.
modules/contrib/src/chamfermatching.cpp
View file @
aa19fd50
...
@@ -36,11 +36,11 @@
...
@@ -36,11 +36,11 @@
// The original code was written by
// The original code was written by
// Marius Muja
// Marius Muja
// and later modified and prepared
// and later modified and prepared
// for integration into OpenCV by
// for integration into OpenCV by
// Antonella Cascitelli,
// Antonella Cascitelli,
// Marco Di Stefano and
// Marco Di Stefano and
// Stefano Fabri
// Stefano Fabri
// from Univ. of Rome
// from Univ. of Rome
//
//
#include "precomp.hpp"
#include "precomp.hpp"
...
@@ -52,7 +52,7 @@ namespace cv
...
@@ -52,7 +52,7 @@ namespace cv
{
{
using
std
::
queue
;
using
std
::
queue
;
typedef
std
::
pair
<
int
,
int
>
coordinate_t
;
typedef
std
::
pair
<
int
,
int
>
coordinate_t
;
typedef
float
orientation_t
;
typedef
float
orientation_t
;
typedef
std
::
vector
<
coordinate_t
>
template_coords_t
;
typedef
std
::
vector
<
coordinate_t
>
template_coords_t
;
...
@@ -61,14 +61,14 @@ typedef std::pair<Point, float> location_scale_t;
...
@@ -61,14 +61,14 @@ typedef std::pair<Point, float> location_scale_t;
class
ChamferMatcher
class
ChamferMatcher
{
{
private
:
private
:
class
Matching
;
class
Matching
;
int
max_matches_
;
int
max_matches_
;
float
min_match_distance_
;
float
min_match_distance_
;
///////////////////////// Image iterators ////////////////////////////
///////////////////////// Image iterators ////////////////////////////
class
ImageIterator
class
ImageIterator
{
{
public
:
public
:
...
@@ -76,15 +76,15 @@ private:
...
@@ -76,15 +76,15 @@ private:
virtual
bool
hasNext
()
const
=
0
;
virtual
bool
hasNext
()
const
=
0
;
virtual
location_scale_t
next
()
=
0
;
virtual
location_scale_t
next
()
=
0
;
};
};
class
ImageRange
class
ImageRange
{
{
public
:
public
:
virtual
ImageIterator
*
iterator
()
const
=
0
;
virtual
ImageIterator
*
iterator
()
const
=
0
;
};
};
// Sliding window
// Sliding window
class
SlidingWindowImageRange
:
public
ImageRange
class
SlidingWindowImageRange
:
public
ImageRange
{
{
int
width_
;
int
width_
;
...
@@ -94,64 +94,64 @@ private:
...
@@ -94,64 +94,64 @@ private:
int
scales_
;
int
scales_
;
float
min_scale_
;
float
min_scale_
;
float
max_scale_
;
float
max_scale_
;
public
:
public
:
SlidingWindowImageRange
(
int
width
,
int
height
,
int
x_step
=
3
,
int
y_step
=
3
,
int
scales
=
5
,
float
min_scale
=
0.6
,
float
max_scale
=
1.6
)
:
SlidingWindowImageRange
(
int
width
,
int
height
,
int
x_step
=
3
,
int
y_step
=
3
,
int
scales
=
5
,
float
min_scale
=
0.6
,
float
max_scale
=
1.6
)
:
width_
(
width
),
height_
(
height
),
x_step_
(
x_step
),
y_step_
(
y_step
),
scales_
(
scales
),
min_scale_
(
min_scale
),
max_scale_
(
max_scale
)
width_
(
width
),
height_
(
height
),
x_step_
(
x_step
),
y_step_
(
y_step
),
scales_
(
scales
),
min_scale_
(
min_scale
),
max_scale_
(
max_scale
)
{
{
}
}
ImageIterator
*
iterator
()
const
;
ImageIterator
*
iterator
()
const
;
};
};
class
LocationImageRange
:
public
ImageRange
class
LocationImageRange
:
public
ImageRange
{
{
const
std
::
vector
<
Point
>&
locations_
;
const
std
::
vector
<
Point
>&
locations_
;
int
scales_
;
int
scales_
;
float
min_scale_
;
float
min_scale_
;
float
max_scale_
;
float
max_scale_
;
LocationImageRange
(
const
LocationImageRange
&
);
LocationImageRange
(
const
LocationImageRange
&
);
LocationImageRange
&
operator
=
(
const
LocationImageRange
&
);
LocationImageRange
&
operator
=
(
const
LocationImageRange
&
);
public
:
public
:
LocationImageRange
(
const
std
::
vector
<
Point
>&
locations
,
int
scales
=
5
,
float
min_scale
=
0.6
,
float
max_scale
=
1.6
)
:
LocationImageRange
(
const
std
::
vector
<
Point
>&
locations
,
int
scales
=
5
,
float
min_scale
=
0.6
,
float
max_scale
=
1.6
)
:
locations_
(
locations
),
scales_
(
scales
),
min_scale_
(
min_scale
),
max_scale_
(
max_scale
)
locations_
(
locations
),
scales_
(
scales
),
min_scale_
(
min_scale
),
max_scale_
(
max_scale
)
{
{
}
}
ImageIterator
*
iterator
()
const
ImageIterator
*
iterator
()
const
{
{
return
new
LocationImageIterator
(
locations_
,
scales_
,
min_scale_
,
max_scale_
);
return
new
LocationImageIterator
(
locations_
,
scales_
,
min_scale_
,
max_scale_
);
}
}
};
};
class
LocationScaleImageRange
:
public
ImageRange
class
LocationScaleImageRange
:
public
ImageRange
{
{
const
std
::
vector
<
Point
>&
locations_
;
const
std
::
vector
<
Point
>&
locations_
;
const
std
::
vector
<
float
>&
scales_
;
const
std
::
vector
<
float
>&
scales_
;
LocationScaleImageRange
(
const
LocationScaleImageRange
&
);
LocationScaleImageRange
(
const
LocationScaleImageRange
&
);
LocationScaleImageRange
&
operator
=
(
const
LocationScaleImageRange
&
);
LocationScaleImageRange
&
operator
=
(
const
LocationScaleImageRange
&
);
public
:
public
:
LocationScaleImageRange
(
const
std
::
vector
<
Point
>&
locations
,
const
std
::
vector
<
float
>&
scales
)
:
LocationScaleImageRange
(
const
std
::
vector
<
Point
>&
locations
,
const
std
::
vector
<
float
>&
scales
)
:
locations_
(
locations
),
scales_
(
scales
)
locations_
(
locations
),
scales_
(
scales
)
{
{
assert
(
locations
.
size
()
==
scales
.
size
());
assert
(
locations
.
size
()
==
scales
.
size
());
}
}
ImageIterator
*
iterator
()
const
ImageIterator
*
iterator
()
const
{
{
return
new
LocationScaleImageIterator
(
locations_
,
scales_
);
return
new
LocationScaleImageIterator
(
locations_
,
scales_
);
}
}
};
};
public
:
public
:
/**
/**
* Class that represents a template for chamfer matching.
* Class that represents a template for chamfer matching.
...
@@ -160,26 +160,26 @@ public:
...
@@ -160,26 +160,26 @@ public:
{
{
friend
class
ChamferMatcher
::
Matching
;
friend
class
ChamferMatcher
::
Matching
;
friend
class
ChamferMatcher
;
friend
class
ChamferMatcher
;
public
:
public
:
std
::
vector
<
Template
*>
scaled_templates
;
std
::
vector
<
Template
*>
scaled_templates
;
std
::
vector
<
int
>
addr
;
std
::
vector
<
int
>
addr
;
int
addr_width
;
int
addr_width
;
float
scale
;
float
scale
;
template_coords_t
coords
;
template_coords_t
coords
;
template_orientations_t
orientations
;
template_orientations_t
orientations
;
Size
size
;
Size
size
;
Point
center
;
Point
center
;
public
:
public
:
Template
()
:
addr_width
(
-
1
)
Template
()
:
addr_width
(
-
1
)
{
{
}
}
Template
(
Mat
&
edge_image
,
float
scale_
=
1
);
Template
(
Mat
&
edge_image
,
float
scale_
=
1
);
~
Template
()
~
Template
()
{
{
for
(
size_t
i
=
0
;
i
<
scaled_templates
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
scaled_templates
.
size
();
++
i
)
{
...
@@ -190,9 +190,9 @@ public:
...
@@ -190,9 +190,9 @@ public:
orientations
.
clear
();
orientations
.
clear
();
}
}
void
show
()
const
;
void
show
()
const
;
private
:
private
:
/**
/**
* Resizes a template
* Resizes a template
...
@@ -200,16 +200,16 @@ public:
...
@@ -200,16 +200,16 @@ public:
* @param scale Scale to be resized to
* @param scale Scale to be resized to
*/
*/
Template
*
rescale
(
float
scale
);
Template
*
rescale
(
float
scale
);
std
::
vector
<
int
>&
getTemplateAddresses
(
int
width
);
std
::
vector
<
int
>&
getTemplateAddresses
(
int
width
);
};
};
/**
/**
* Used to represent a matching result.
* Used to represent a matching result.
*/
*/
class
Match
class
Match
{
{
public
:
public
:
...
@@ -217,9 +217,9 @@ public:
...
@@ -217,9 +217,9 @@ public:
Point
offset
;
Point
offset
;
const
Template
*
tpl
;
const
Template
*
tpl
;
};
};
typedef
std
::
vector
<
Match
>
Matches
;
typedef
std
::
vector
<
Match
>
Matches
;
private
:
private
:
/**
/**
* Implements the chamfer matching algorithm on images taking into account both distance from
* Implements the chamfer matching algorithm on images taking into account both distance from
...
@@ -230,42 +230,42 @@ private:
...
@@ -230,42 +230,42 @@ private:
{
{
float
truncate_
;
float
truncate_
;
bool
use_orientation_
;
bool
use_orientation_
;
std
::
vector
<
Template
*>
templates
;
std
::
vector
<
Template
*>
templates
;
public
:
public
:
Matching
(
bool
use_orientation
=
true
,
float
truncate
=
10
)
:
truncate_
(
truncate
),
use_orientation_
(
use_orientation
)
Matching
(
bool
use_orientation
=
true
,
float
truncate
=
10
)
:
truncate_
(
truncate
),
use_orientation_
(
use_orientation
)
{
{
}
}
~
Matching
()
~
Matching
()
{
{
for
(
size_t
i
=
0
;
i
<
templates
.
size
();
i
++
)
{
for
(
size_t
i
=
0
;
i
<
templates
.
size
();
i
++
)
{
delete
templates
[
i
];
delete
templates
[
i
];
}
}
}
}
/**
/**
* Add a template to the detector from an edge image.
* Add a template to the detector from an edge image.
* @param templ An edge image
* @param templ An edge image
*/
*/
void
addTemplateFromImage
(
Mat
&
templ
,
float
scale
=
1.0
);
void
addTemplateFromImage
(
Mat
&
templ
,
float
scale
=
1.0
);
/**
/**
* Run matching using an edge image.
* Run matching using an edge image.
* @param edge_img Edge image
* @param edge_img Edge image
* @return a match object
* @return a match object
*/
*/
ChamferMatcher
::
Matches
*
matchEdgeImage
(
Mat
&
edge_img
,
const
ImageRange
&
range
,
float
orientation_weight
=
0.5
,
int
max_matches
=
20
,
float
min_match_distance
=
10.0
);
ChamferMatcher
::
Matches
*
matchEdgeImage
(
Mat
&
edge_img
,
const
ImageRange
&
range
,
float
orientation_weight
=
0.5
,
int
max_matches
=
20
,
float
min_match_distance
=
10.0
);
void
addTemplate
(
Template
&
template_
);
void
addTemplate
(
Template
&
template_
);
private
:
private
:
float
orientation_diff
(
float
o1
,
float
o2
)
float
orientation_diff
(
float
o1
,
float
o2
)
{
{
return
fabs
(
o1
-
o2
);
return
fabs
(
o1
-
o2
);
}
}
/**
/**
* Computes the chamfer matching cost for one position in the target image.
* Computes the chamfer matching cost for one position in the target image.
* @param offset Offset where to compute cost
* @param offset Offset where to compute cost
...
@@ -276,7 +276,7 @@ private:
...
@@ -276,7 +276,7 @@ private:
* @return matching result
* @return matching result
*/
*/
ChamferMatcher
::
Match
*
localChamferDistance
(
Point
offset
,
Mat
&
dist_img
,
Mat
&
orientation_img
,
Template
*
tpl
,
float
orientation_weight
);
ChamferMatcher
::
Match
*
localChamferDistance
(
Point
offset
,
Mat
&
dist_img
,
Mat
&
orientation_img
,
Template
*
tpl
,
float
orientation_weight
);
private
:
private
:
/**
/**
* Matches all templates.
* Matches all templates.
...
@@ -284,12 +284,12 @@ private:
...
@@ -284,12 +284,12 @@ private:
* @param orientation_img Orientation image.
* @param orientation_img Orientation image.
*/
*/
ChamferMatcher
::
Matches
*
matchTemplates
(
Mat
&
dist_img
,
Mat
&
orientation_img
,
const
ImageRange
&
range
,
float
orientation_weight
);
ChamferMatcher
::
Matches
*
matchTemplates
(
Mat
&
dist_img
,
Mat
&
orientation_img
,
const
ImageRange
&
range
,
float
orientation_weight
);
void
computeDistanceTransform
(
Mat
&
edges_img
,
Mat
&
dist_img
,
Mat
&
annotate_img
,
float
truncate_dt
,
float
a
,
float
b
);
void
computeDistanceTransform
(
Mat
&
edges_img
,
Mat
&
dist_img
,
Mat
&
annotate_img
,
float
truncate_dt
,
float
a
,
float
b
);
void
computeEdgeOrientations
(
Mat
&
edge_img
,
Mat
&
orientation_img
);
void
computeEdgeOrientations
(
Mat
&
edge_img
,
Mat
&
orientation_img
);
void
fillNonContourOrientations
(
Mat
&
annotated_img
,
Mat
&
orientation_img
);
void
fillNonContourOrientations
(
Mat
&
annotated_img
,
Mat
&
orientation_img
);
public
:
public
:
/**
/**
* Finds a contour in an edge image. The original image is altered by removing the found contour.
* Finds a contour in an edge image. The original image is altered by removing the found contour.
...
@@ -298,7 +298,7 @@ private:
...
@@ -298,7 +298,7 @@ private:
* @return True while a contour is still found in the image.
* @return True while a contour is still found in the image.
*/
*/
static
bool
findContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
);
static
bool
findContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
);
/**
/**
* Computes contour points orientations using the approach from:
* Computes contour points orientations using the approach from:
*
*
...
@@ -309,8 +309,8 @@ private:
...
@@ -309,8 +309,8 @@ private:
* @param orientations Contour points orientations
* @param orientations Contour points orientations
*/
*/
static
void
findContourOrientations
(
const
template_coords_t
&
coords
,
template_orientations_t
&
orientations
);
static
void
findContourOrientations
(
const
template_coords_t
&
coords
,
template_orientations_t
&
orientations
);
/**
/**
* Computes the angle of a line segment.
* Computes the angle of a line segment.
*
*
...
@@ -321,14 +321,14 @@ private:
...
@@ -321,14 +321,14 @@ private:
* @return Angle in radians.
* @return Angle in radians.
*/
*/
static
float
getAngle
(
coordinate_t
a
,
coordinate_t
b
,
int
&
dx
,
int
&
dy
);
static
float
getAngle
(
coordinate_t
a
,
coordinate_t
b
,
int
&
dx
,
int
&
dy
);
/**
/**
* Finds a point in the image from which to start contour following.
* Finds a point in the image from which to start contour following.
* @param templ_img
* @param templ_img
* @param p
* @param p
* @return
* @return
*/
*/
static
bool
findFirstContourPoint
(
Mat
&
templ_img
,
coordinate_t
&
p
);
static
bool
findFirstContourPoint
(
Mat
&
templ_img
,
coordinate_t
&
p
);
/**
/**
* Method that extracts a single continuous contour from an image given a starting point.
* Method that extracts a single continuous contour from an image given a starting point.
...
@@ -339,54 +339,54 @@ private:
...
@@ -339,54 +339,54 @@ private:
* @param direction
* @param direction
*/
*/
static
void
followContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
,
int
direction
);
static
void
followContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
,
int
direction
);
};
};
class
LocationImageIterator
:
public
ImageIterator
class
LocationImageIterator
:
public
ImageIterator
{
{
const
std
::
vector
<
Point
>&
locations_
;
const
std
::
vector
<
Point
>&
locations_
;
size_t
iter_
;
size_t
iter_
;
int
scales_
;
int
scales_
;
float
min_scale_
;
float
min_scale_
;
float
max_scale_
;
float
max_scale_
;
float
scale_
;
float
scale_
;
float
scale_step_
;
float
scale_step_
;
int
scale_cnt_
;
int
scale_cnt_
;
bool
has_next_
;
bool
has_next_
;
LocationImageIterator
(
const
LocationImageIterator
&
);
LocationImageIterator
(
const
LocationImageIterator
&
);
LocationImageIterator
&
operator
=
(
const
LocationImageIterator
&
);
LocationImageIterator
&
operator
=
(
const
LocationImageIterator
&
);
public
:
public
:
LocationImageIterator
(
const
std
::
vector
<
Point
>&
locations
,
int
scales
,
float
min_scale
,
float
max_scale
);
LocationImageIterator
(
const
std
::
vector
<
Point
>&
locations
,
int
scales
,
float
min_scale
,
float
max_scale
);
bool
hasNext
()
const
{
bool
hasNext
()
const
{
return
has_next_
;
return
has_next_
;
}
}
location_scale_t
next
();
location_scale_t
next
();
};
};
class
LocationScaleImageIterator
:
public
ImageIterator
class
LocationScaleImageIterator
:
public
ImageIterator
{
{
const
std
::
vector
<
Point
>&
locations_
;
const
std
::
vector
<
Point
>&
locations_
;
const
std
::
vector
<
float
>&
scales_
;
const
std
::
vector
<
float
>&
scales_
;
size_t
iter_
;
size_t
iter_
;
bool
has_next_
;
bool
has_next_
;
LocationScaleImageIterator
(
const
LocationScaleImageIterator
&
);
LocationScaleImageIterator
(
const
LocationScaleImageIterator
&
);
LocationScaleImageIterator
&
operator
=
(
const
LocationScaleImageIterator
&
);
LocationScaleImageIterator
&
operator
=
(
const
LocationScaleImageIterator
&
);
public
:
public
:
LocationScaleImageIterator
(
const
std
::
vector
<
Point
>&
locations
,
const
std
::
vector
<
float
>&
scales
)
:
LocationScaleImageIterator
(
const
std
::
vector
<
Point
>&
locations
,
const
std
::
vector
<
float
>&
scales
)
:
locations_
(
locations
),
scales_
(
scales
)
locations_
(
locations
),
scales_
(
scales
)
...
@@ -394,20 +394,20 @@ private:
...
@@ -394,20 +394,20 @@ private:
assert
(
locations
.
size
()
==
scales
.
size
());
assert
(
locations
.
size
()
==
scales
.
size
());
reset
();
reset
();
}
}
void
reset
()
void
reset
()
{
{
iter_
=
0
;
iter_
=
0
;
has_next_
=
(
locations_
.
size
()
==
0
?
false
:
true
);
has_next_
=
(
locations_
.
size
()
==
0
?
false
:
true
);
}
}
bool
hasNext
()
const
{
bool
hasNext
()
const
{
return
has_next_
;
return
has_next_
;
}
}
location_scale_t
next
();
location_scale_t
next
();
};
};
class
SlidingWindowImageIterator
:
public
ImageIterator
class
SlidingWindowImageIterator
:
public
ImageIterator
{
{
int
x_
;
int
x_
;
...
@@ -415,9 +415,9 @@ private:
...
@@ -415,9 +415,9 @@ private:
float
scale_
;
float
scale_
;
float
scale_step_
;
float
scale_step_
;
int
scale_cnt_
;
int
scale_cnt_
;
bool
has_next_
;
bool
has_next_
;
int
width_
;
int
width_
;
int
height_
;
int
height_
;
int
x_step_
;
int
x_step_
;
...
@@ -425,22 +425,22 @@ private:
...
@@ -425,22 +425,22 @@ private:
int
scales_
;
int
scales_
;
float
min_scale_
;
float
min_scale_
;
float
max_scale_
;
float
max_scale_
;
public
:
public
:
SlidingWindowImageIterator
(
int
width
,
int
height
,
int
x_step
,
int
y_step
,
int
scales
,
float
min_scale
,
float
max_scale
);
SlidingWindowImageIterator
(
int
width
,
int
height
,
int
x_step
,
int
y_step
,
int
scales
,
float
min_scale
,
float
max_scale
);
bool
hasNext
()
const
{
bool
hasNext
()
const
{
return
has_next_
;
return
has_next_
;
}
}
location_scale_t
next
();
location_scale_t
next
();
};
};
int
count
;
int
count
;
Matches
matches
;
Matches
matches
;
int
pad_x
;
int
pad_x
;
...
@@ -451,7 +451,7 @@ private:
...
@@ -451,7 +451,7 @@ private:
float
orientation_weight
;
float
orientation_weight
;
float
truncate
;
float
truncate
;
Matching
*
chamfer_
;
Matching
*
chamfer_
;
public
:
public
:
ChamferMatcher
(
int
_max_matches
=
20
,
float
_min_match_distance
=
1.0
,
int
_pad_x
=
3
,
ChamferMatcher
(
int
_max_matches
=
20
,
float
_min_match_distance
=
1.0
,
int
_pad_x
=
3
,
int
_pad_y
=
3
,
int
_scales
=
5
,
float
_minScale
=
0.6
,
float
_maxScale
=
1.6
,
int
_pad_y
=
3
,
int
_scales
=
5
,
float
_minScale
=
0.6
,
float
_maxScale
=
1.6
,
...
@@ -467,371 +467,371 @@ public:
...
@@ -467,371 +467,371 @@ public:
orientation_weight
=
_orientation_weight
;
orientation_weight
=
_orientation_weight
;
truncate
=
_truncate
;
truncate
=
_truncate
;
count
=
0
;
count
=
0
;
matches
.
resize
(
max_matches_
);
matches
.
resize
(
max_matches_
);
chamfer_
=
new
Matching
(
true
);
chamfer_
=
new
Matching
(
true
);
}
}
void
showMatch
(
Mat
&
img
,
int
index
=
0
);
void
showMatch
(
Mat
&
img
,
int
index
=
0
);
void
showMatch
(
Mat
&
img
,
Match
match_
);
void
showMatch
(
Mat
&
img
,
Match
match_
);
const
Matches
&
matching
(
Template
&
,
Mat
&
);
const
Matches
&
matching
(
Template
&
,
Mat
&
);
private
:
private
:
void
addMatch
(
float
cost
,
Point
offset
,
const
Template
*
tpl
);
void
addMatch
(
float
cost
,
Point
offset
,
const
Template
*
tpl
);
};
};
///////////////////// implementation ///////////////////////////
///////////////////// implementation ///////////////////////////
ChamferMatcher
::
SlidingWindowImageIterator
::
SlidingWindowImageIterator
(
int
width
,
ChamferMatcher
::
SlidingWindowImageIterator
::
SlidingWindowImageIterator
(
int
width
,
int
height
,
int
height
,
int
x_step
=
3
,
int
x_step
=
3
,
int
y_step
=
3
,
int
y_step
=
3
,
int
scales
=
5
,
int
scales
=
5
,
float
min_scale
=
0.6
,
float
min_scale
=
0.6
,
float
max_scale
=
1.6
)
:
float
max_scale
=
1.6
)
:
width_
(
width
),
width_
(
width
),
height_
(
height
),
height_
(
height
),
x_step_
(
x_step
),
x_step_
(
x_step
),
y_step_
(
y_step
),
y_step_
(
y_step
),
scales_
(
scales
),
scales_
(
scales
),
min_scale_
(
min_scale
),
min_scale_
(
min_scale
),
max_scale_
(
max_scale
)
max_scale_
(
max_scale
)
{
{
x_
=
0
;
x_
=
0
;
y_
=
0
;
y_
=
0
;
scale_cnt_
=
0
;
scale_cnt_
=
0
;
scale_
=
min_scale_
;
scale_
=
min_scale_
;
has_next_
=
true
;
has_next_
=
true
;
scale_step_
=
(
max_scale_
-
min_scale_
)
/
scales_
;
scale_step_
=
(
max_scale_
-
min_scale_
)
/
scales_
;
}
}
location_scale_t
ChamferMatcher
::
SlidingWindowImageIterator
::
next
()
location_scale_t
ChamferMatcher
::
SlidingWindowImageIterator
::
next
()
{
{
location_scale_t
next_val
=
std
::
make_pair
(
Point
(
x_
,
y_
),
scale_
);
location_scale_t
next_val
=
std
::
make_pair
(
Point
(
x_
,
y_
),
scale_
);
x_
+=
x_step_
;
x_
+=
x_step_
;
if
(
x_
>=
width_
)
{
if
(
x_
>=
width_
)
{
x_
=
0
;
x_
=
0
;
y_
+=
y_step_
;
y_
+=
y_step_
;
if
(
y_
>=
height_
)
{
if
(
y_
>=
height_
)
{
y_
=
0
;
y_
=
0
;
scale_
+=
scale_step_
;
scale_
+=
scale_step_
;
scale_cnt_
++
;
scale_cnt_
++
;
if
(
scale_cnt_
==
scales_
)
{
if
(
scale_cnt_
==
scales_
)
{
has_next_
=
false
;
has_next_
=
false
;
scale_cnt_
=
0
;
scale_cnt_
=
0
;
scale_
=
min_scale_
;
scale_
=
min_scale_
;
}
}
}
}
}
}
return
next_val
;
return
next_val
;
}
}
ChamferMatcher
::
ImageIterator
*
ChamferMatcher
::
SlidingWindowImageRange
::
iterator
()
const
ChamferMatcher
::
ImageIterator
*
ChamferMatcher
::
SlidingWindowImageRange
::
iterator
()
const
{
{
return
new
SlidingWindowImageIterator
(
width_
,
height_
,
x_step_
,
y_step_
,
scales_
,
min_scale_
,
max_scale_
);
return
new
SlidingWindowImageIterator
(
width_
,
height_
,
x_step_
,
y_step_
,
scales_
,
min_scale_
,
max_scale_
);
}
}
ChamferMatcher
::
LocationImageIterator
::
LocationImageIterator
(
const
std
::
vector
<
Point
>&
locations
,
ChamferMatcher
::
LocationImageIterator
::
LocationImageIterator
(
const
std
::
vector
<
Point
>&
locations
,
int
scales
=
5
,
int
scales
=
5
,
float
min_scale
=
0.6
,
float
min_scale
=
0.6
,
float
max_scale
=
1.6
)
:
float
max_scale
=
1.6
)
:
locations_
(
locations
),
locations_
(
locations
),
scales_
(
scales
),
scales_
(
scales
),
min_scale_
(
min_scale
),
min_scale_
(
min_scale
),
max_scale_
(
max_scale
)
max_scale_
(
max_scale
)
{
{
iter_
=
0
;
iter_
=
0
;
scale_cnt_
=
0
;
scale_cnt_
=
0
;
scale_
=
min_scale_
;
scale_
=
min_scale_
;
has_next_
=
(
locations_
.
size
()
==
0
?
false
:
true
);
has_next_
=
(
locations_
.
size
()
==
0
?
false
:
true
);
scale_step_
=
(
max_scale_
-
min_scale_
)
/
scales_
;
scale_step_
=
(
max_scale_
-
min_scale_
)
/
scales_
;
}
}
location_scale_t
ChamferMatcher
::
LocationImageIterator
::
next
()
location_scale_t
ChamferMatcher
::
LocationImageIterator
::
next
()
{
{
location_scale_t
next_val
=
std
::
make_pair
(
locations_
[
iter_
],
scale_
);
location_scale_t
next_val
=
std
::
make_pair
(
locations_
[
iter_
],
scale_
);
iter_
++
;
iter_
++
;
if
(
iter_
==
locations_
.
size
())
{
if
(
iter_
==
locations_
.
size
())
{
iter_
=
0
;
iter_
=
0
;
scale_
+=
scale_step_
;
scale_
+=
scale_step_
;
scale_cnt_
++
;
scale_cnt_
++
;
if
(
scale_cnt_
==
scales_
)
{
if
(
scale_cnt_
==
scales_
)
{
has_next_
=
false
;
has_next_
=
false
;
scale_cnt_
=
0
;
scale_cnt_
=
0
;
scale_
=
min_scale_
;
scale_
=
min_scale_
;
}
}
}
}
return
next_val
;
return
next_val
;
}
}
location_scale_t
ChamferMatcher
::
LocationScaleImageIterator
::
next
()
location_scale_t
ChamferMatcher
::
LocationScaleImageIterator
::
next
()
{
{
location_scale_t
next_val
=
std
::
make_pair
(
locations_
[
iter_
],
scales_
[
iter_
]);
location_scale_t
next_val
=
std
::
make_pair
(
locations_
[
iter_
],
scales_
[
iter_
]);
iter_
++
;
iter_
++
;
if
(
iter_
==
locations_
.
size
())
{
if
(
iter_
==
locations_
.
size
())
{
iter_
=
0
;
iter_
=
0
;
has_next_
=
false
;
has_next_
=
false
;
}
}
return
next_val
;
return
next_val
;
}
}
bool
ChamferMatcher
::
Matching
::
findFirstContourPoint
(
Mat
&
templ_img
,
coordinate_t
&
p
)
bool
ChamferMatcher
::
Matching
::
findFirstContourPoint
(
Mat
&
templ_img
,
coordinate_t
&
p
)
{
{
for
(
int
y
=
0
;
y
<
templ_img
.
rows
;
++
y
)
{
for
(
int
y
=
0
;
y
<
templ_img
.
rows
;
++
y
)
{
for
(
int
x
=
0
;
x
<
templ_img
.
cols
;
++
x
)
{
for
(
int
x
=
0
;
x
<
templ_img
.
cols
;
++
x
)
{
if
(
templ_img
.
at
<
uchar
>
(
y
,
x
)
!=
0
)
{
if
(
templ_img
.
at
<
uchar
>
(
y
,
x
)
!=
0
)
{
p
.
first
=
x
;
p
.
first
=
x
;
p
.
second
=
y
;
p
.
second
=
y
;
return
true
;
return
true
;
}
}
}
}
}
}
return
false
;
return
false
;
}
}
void
ChamferMatcher
::
Matching
::
followContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
,
int
direction
=
-
1
)
void
ChamferMatcher
::
Matching
::
followContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
,
int
direction
=
-
1
)
{
{
const
int
dir
[][
2
]
=
{
{
-
1
,
-
1
},
{
-
1
,
0
},
{
-
1
,
1
},
{
0
,
1
},
{
1
,
1
},
{
1
,
0
},
{
1
,
-
1
},
{
0
,
-
1
}
};
const
int
dir
[][
2
]
=
{
{
-
1
,
-
1
},
{
-
1
,
0
},
{
-
1
,
1
},
{
0
,
1
},
{
1
,
1
},
{
1
,
0
},
{
1
,
-
1
},
{
0
,
-
1
}
};
coordinate_t
next
;
coordinate_t
next
;
coordinate_t
next_temp
;
coordinate_t
next_temp
;
unsigned
char
ptr
;
unsigned
char
ptr
;
assert
(
direction
==-
1
||
!
coords
.
empty
());
assert
(
direction
==-
1
||
!
coords
.
empty
());
coordinate_t
crt
=
coords
.
back
();
coordinate_t
crt
=
coords
.
back
();
// mark the current pixel as visited
// mark the current pixel as visited
templ_img
.
at
<
uchar
>
(
crt
.
second
,
crt
.
first
)
=
0
;
templ_img
.
at
<
uchar
>
(
crt
.
second
,
crt
.
first
)
=
0
;
if
(
direction
==-
1
)
{
if
(
direction
==-
1
)
{
for
(
int
j
=
0
;
j
<
7
;
++
j
)
{
for
(
int
j
=
0
;
j
<
7
;
++
j
)
{
next
.
first
=
crt
.
first
+
dir
[
j
][
1
];
next
.
first
=
crt
.
first
+
dir
[
j
][
1
];
next
.
second
=
crt
.
second
+
dir
[
j
][
0
];
next
.
second
=
crt
.
second
+
dir
[
j
][
0
];
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
if
(
ptr
!=
0
)
{
if
(
ptr
!=
0
)
{
coords
.
push_back
(
next
);
coords
.
push_back
(
next
);
followContour
(
templ_img
,
coords
,
j
);
followContour
(
templ_img
,
coords
,
j
);
// try to continue contour in the other direction
// try to continue contour in the other direction
reverse
(
coords
.
begin
(),
coords
.
end
());
reverse
(
coords
.
begin
(),
coords
.
end
());
followContour
(
templ_img
,
coords
,
(
j
+
4
)
%
8
);
followContour
(
templ_img
,
coords
,
(
j
+
4
)
%
8
);
break
;
break
;
}
}
}
}
}
}
}
}
else
{
else
{
int
k
=
direction
;
int
k
=
direction
;
int
k_cost
=
3
;
int
k_cost
=
3
;
next
.
first
=
crt
.
first
+
dir
[
k
][
1
];
next
.
first
=
crt
.
first
+
dir
[
k
][
1
];
next
.
second
=
crt
.
second
+
dir
[
k
][
0
];
next
.
second
=
crt
.
second
+
dir
[
k
][
0
];
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
if
(
ptr
!=
0
)
{
if
(
ptr
!=
0
)
{
k_cost
=
std
::
abs
(
dir
[
k
][
1
])
+
std
::
abs
(
dir
[
k
][
0
]);
k_cost
=
std
::
abs
(
dir
[
k
][
1
])
+
std
::
abs
(
dir
[
k
][
0
]);
}
}
int
p
=
k
;
int
p
=
k
;
int
n
=
k
;
int
n
=
k
;
for
(
int
j
=
0
;
j
<
3
;
++
j
)
{
for
(
int
j
=
0
;
j
<
3
;
++
j
)
{
p
=
(
p
+
7
)
%
8
;
p
=
(
p
+
7
)
%
8
;
n
=
(
n
+
1
)
%
8
;
n
=
(
n
+
1
)
%
8
;
next
.
first
=
crt
.
first
+
dir
[
p
][
1
];
next
.
first
=
crt
.
first
+
dir
[
p
][
1
];
next
.
second
=
crt
.
second
+
dir
[
p
][
0
];
next
.
second
=
crt
.
second
+
dir
[
p
][
0
];
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
if
(
ptr
!=
0
)
{
if
(
ptr
!=
0
)
{
int
p_cost
=
std
::
abs
(
dir
[
p
][
1
])
+
std
::
abs
(
dir
[
p
][
0
]);
int
p_cost
=
std
::
abs
(
dir
[
p
][
1
])
+
std
::
abs
(
dir
[
p
][
0
]);
if
(
p_cost
<
k_cost
)
{
if
(
p_cost
<
k_cost
)
{
k_cost
=
p_cost
;
k_cost
=
p_cost
;
k
=
p
;
k
=
p
;
}
}
}
}
next
.
first
=
crt
.
first
+
dir
[
n
][
1
];
next
.
first
=
crt
.
first
+
dir
[
n
][
1
];
next
.
second
=
crt
.
second
+
dir
[
n
][
0
];
next
.
second
=
crt
.
second
+
dir
[
n
][
0
];
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
){
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
ptr
=
templ_img
.
at
<
uchar
>
(
next
.
second
,
next
.
first
);
if
(
ptr
!=
0
)
{
if
(
ptr
!=
0
)
{
int
n_cost
=
std
::
abs
(
dir
[
n
][
1
])
+
std
::
abs
(
dir
[
n
][
0
]);
int
n_cost
=
std
::
abs
(
dir
[
n
][
1
])
+
std
::
abs
(
dir
[
n
][
0
]);
if
(
n_cost
<
k_cost
)
{
if
(
n_cost
<
k_cost
)
{
k_cost
=
n_cost
;
k_cost
=
n_cost
;
k
=
n
;
k
=
n
;
}
}
}
}
}
}
}
}
}
}
if
(
k_cost
!=
3
)
{
if
(
k_cost
!=
3
)
{
next
.
first
=
crt
.
first
+
dir
[
k
][
1
];
next
.
first
=
crt
.
first
+
dir
[
k
][
1
];
next
.
second
=
crt
.
second
+
dir
[
k
][
0
];
next
.
second
=
crt
.
second
+
dir
[
k
][
0
];
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
if
(
next
.
first
>=
0
&&
next
.
first
<
templ_img
.
cols
&&
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
)
{
next
.
second
>=
0
&&
next
.
second
<
templ_img
.
rows
)
{
coords
.
push_back
(
next
);
coords
.
push_back
(
next
);
followContour
(
templ_img
,
coords
,
k
);
followContour
(
templ_img
,
coords
,
k
);
}
}
}
}
}
}
}
}
}
}
bool
ChamferMatcher
::
Matching
::
findContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
)
bool
ChamferMatcher
::
Matching
::
findContour
(
Mat
&
templ_img
,
template_coords_t
&
coords
)
{
{
coordinate_t
start_point
;
coordinate_t
start_point
;
bool
found
=
findFirstContourPoint
(
templ_img
,
start_point
);
bool
found
=
findFirstContourPoint
(
templ_img
,
start_point
);
if
(
found
)
{
if
(
found
)
{
coords
.
push_back
(
start_point
);
coords
.
push_back
(
start_point
);
followContour
(
templ_img
,
coords
);
followContour
(
templ_img
,
coords
);
return
true
;
return
true
;
}
}
return
false
;
return
false
;
}
}
float
ChamferMatcher
::
Matching
::
getAngle
(
coordinate_t
a
,
coordinate_t
b
,
int
&
dx
,
int
&
dy
)
float
ChamferMatcher
::
Matching
::
getAngle
(
coordinate_t
a
,
coordinate_t
b
,
int
&
dx
,
int
&
dy
)
{
{
dx
=
b
.
first
-
a
.
first
;
dx
=
b
.
first
-
a
.
first
;
dy
=
-
(
b
.
second
-
a
.
second
);
// in image coordinated Y axis points downward
dy
=
-
(
b
.
second
-
a
.
second
);
// in image coordinated Y axis points downward
float
angle
=
atan2
((
float
)
dy
,(
float
)
dx
);
float
angle
=
atan2
((
float
)
dy
,(
float
)
dx
);
if
(
angle
<
0
)
{
if
(
angle
<
0
)
{
angle
+=
(
float
)
CV_PI
;
angle
+=
(
float
)
CV_PI
;
}
}
return
angle
;
return
angle
;
}
}
void
ChamferMatcher
::
Matching
::
findContourOrientations
(
const
template_coords_t
&
coords
,
template_orientations_t
&
orientations
)
void
ChamferMatcher
::
Matching
::
findContourOrientations
(
const
template_coords_t
&
coords
,
template_orientations_t
&
orientations
)
{
{
const
int
M
=
5
;
const
int
M
=
5
;
int
coords_size
=
(
int
)
coords
.
size
();
int
coords_size
=
(
int
)
coords
.
size
();
std
::
vector
<
float
>
angles
(
2
*
M
);
std
::
vector
<
float
>
angles
(
2
*
M
);
orientations
.
insert
(
orientations
.
begin
(),
coords_size
,
float
(
-
3
*
CV_PI
));
// mark as invalid in the beginning
orientations
.
insert
(
orientations
.
begin
(),
coords_size
,
float
(
-
3
*
CV_PI
));
// mark as invalid in the beginning
if
(
coords_size
<
2
*
M
+
1
)
{
// if contour not long enough to estimate orientations, abort
if
(
coords_size
<
2
*
M
+
1
)
{
// if contour not long enough to estimate orientations, abort
return
;
return
;
}
}
for
(
int
i
=
M
;
i
<
coords_size
-
M
;
++
i
)
{
for
(
int
i
=
M
;
i
<
coords_size
-
M
;
++
i
)
{
coordinate_t
crt
=
coords
[
i
];
coordinate_t
crt
=
coords
[
i
];
coordinate_t
other
;
coordinate_t
other
;
int
k
=
0
;
int
k
=
0
;
int
dx
,
dy
;
int
dx
,
dy
;
// compute previous M angles
// compute previous M angles
for
(
int
j
=
M
;
j
>
0
;
--
j
)
{
for
(
int
j
=
M
;
j
>
0
;
--
j
)
{
other
=
coords
[
i
-
j
];
other
=
coords
[
i
-
j
];
angles
[
k
++
]
=
getAngle
(
other
,
crt
,
dx
,
dy
);
angles
[
k
++
]
=
getAngle
(
other
,
crt
,
dx
,
dy
);
}
}
// compute next M angles
// compute next M angles
for
(
int
j
=
1
;
j
<=
M
;
++
j
)
{
for
(
int
j
=
1
;
j
<=
M
;
++
j
)
{
other
=
coords
[
i
+
j
];
other
=
coords
[
i
+
j
];
angles
[
k
++
]
=
getAngle
(
crt
,
other
,
dx
,
dy
);
angles
[
k
++
]
=
getAngle
(
crt
,
other
,
dx
,
dy
);
}
}
// get the middle two angles
// get the middle two angles
nth_element
(
angles
.
begin
(),
angles
.
begin
()
+
M
-
1
,
angles
.
end
());
nth_element
(
angles
.
begin
(),
angles
.
begin
()
+
M
-
1
,
angles
.
end
());
nth_element
(
angles
.
begin
()
+
M
-
1
,
angles
.
begin
()
+
M
,
angles
.
end
());
nth_element
(
angles
.
begin
()
+
M
-
1
,
angles
.
begin
()
+
M
,
angles
.
end
());
//
sort(angles.begin(), angles.end());
//
sort(angles.begin(), angles.end());
// average them to compute tangent
// average them to compute tangent
orientations
[
i
]
=
(
angles
[
M
-
1
]
+
angles
[
M
])
/
2
;
orientations
[
i
]
=
(
angles
[
M
-
1
]
+
angles
[
M
])
/
2
;
}
}
}
}
//////////////////////// Template /////////////////////////////////////
//////////////////////// Template /////////////////////////////////////
ChamferMatcher
::
Template
::
Template
(
Mat
&
edge_image
,
float
scale_
)
:
addr_width
(
-
1
),
scale
(
scale_
)
ChamferMatcher
::
Template
::
Template
(
Mat
&
edge_image
,
float
scale_
)
:
addr_width
(
-
1
),
scale
(
scale_
)
{
{
template_coords_t
local_coords
;
template_coords_t
local_coords
;
template_orientations_t
local_orientations
;
template_orientations_t
local_orientations
;
while
(
ChamferMatcher
::
Matching
::
findContour
(
edge_image
,
local_coords
))
{
while
(
ChamferMatcher
::
Matching
::
findContour
(
edge_image
,
local_coords
))
{
ChamferMatcher
::
Matching
::
findContourOrientations
(
local_coords
,
local_orientations
);
ChamferMatcher
::
Matching
::
findContourOrientations
(
local_coords
,
local_orientations
);
coords
.
insert
(
coords
.
end
(),
local_coords
.
begin
(),
local_coords
.
end
());
coords
.
insert
(
coords
.
end
(),
local_coords
.
begin
(),
local_coords
.
end
());
orientations
.
insert
(
orientations
.
end
(),
local_orientations
.
begin
(),
local_orientations
.
end
());
orientations
.
insert
(
orientations
.
end
(),
local_orientations
.
begin
(),
local_orientations
.
end
());
local_coords
.
clear
();
local_coords
.
clear
();
local_orientations
.
clear
();
local_orientations
.
clear
();
}
}
size
=
edge_image
.
size
();
size
=
edge_image
.
size
();
Point
min
,
max
;
Point
min
,
max
;
min
.
x
=
size
.
width
;
min
.
x
=
size
.
width
;
min
.
y
=
size
.
height
;
min
.
y
=
size
.
height
;
max
.
x
=
0
;
max
.
x
=
0
;
max
.
y
=
0
;
max
.
y
=
0
;
center
=
Point
(
0
,
0
);
center
=
Point
(
0
,
0
);
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
center
.
x
+=
coords
[
i
].
first
;
center
.
x
+=
coords
[
i
].
first
;
center
.
y
+=
coords
[
i
].
second
;
center
.
y
+=
coords
[
i
].
second
;
if
(
min
.
x
>
coords
[
i
].
first
)
min
.
x
=
coords
[
i
].
first
;
if
(
min
.
x
>
coords
[
i
].
first
)
min
.
x
=
coords
[
i
].
first
;
if
(
min
.
y
>
coords
[
i
].
second
)
min
.
y
=
coords
[
i
].
second
;
if
(
min
.
y
>
coords
[
i
].
second
)
min
.
y
=
coords
[
i
].
second
;
if
(
max
.
x
<
coords
[
i
].
first
)
max
.
x
=
coords
[
i
].
first
;
if
(
max
.
x
<
coords
[
i
].
first
)
max
.
x
=
coords
[
i
].
first
;
if
(
max
.
y
<
coords
[
i
].
second
)
max
.
y
=
coords
[
i
].
second
;
if
(
max
.
y
<
coords
[
i
].
second
)
max
.
y
=
coords
[
i
].
second
;
}
}
size
.
width
=
max
.
x
-
min
.
x
;
size
.
width
=
max
.
x
-
min
.
x
;
size
.
height
=
max
.
y
-
min
.
y
;
size
.
height
=
max
.
y
-
min
.
y
;
int
coords_size
=
(
int
)
coords
.
size
();
int
coords_size
=
(
int
)
coords
.
size
();
center
.
x
/=
MAX
(
coords_size
,
1
);
center
.
x
/=
MAX
(
coords_size
,
1
);
center
.
y
/=
MAX
(
coords_size
,
1
);
center
.
y
/=
MAX
(
coords_size
,
1
);
for
(
int
i
=
0
;
i
<
coords_size
;
++
i
)
{
for
(
int
i
=
0
;
i
<
coords_size
;
++
i
)
{
coords
[
i
].
first
-=
center
.
x
;
coords
[
i
].
first
-=
center
.
x
;
coords
[
i
].
second
-=
center
.
y
;
coords
[
i
].
second
-=
center
.
y
;
}
}
}
}
vector
<
int
>&
ChamferMatcher
::
Template
::
getTemplateAddresses
(
int
width
)
vector
<
int
>&
ChamferMatcher
::
Template
::
getTemplateAddresses
(
int
width
)
{
{
if
(
addr_width
!=
width
)
{
if
(
addr_width
!=
width
)
{
addr
.
resize
(
coords
.
size
());
addr
.
resize
(
coords
.
size
());
addr_width
=
width
;
addr_width
=
width
;
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
addr
[
i
]
=
coords
[
i
].
second
*
width
+
coords
[
i
].
first
;
addr
[
i
]
=
coords
[
i
].
second
*
width
+
coords
[
i
].
first
;
}
}
}
}
return
addr
;
return
addr
;
}
}
...
@@ -843,35 +843,35 @@ vector<int>& ChamferMatcher::Template::getTemplateAddresses(int width)
...
@@ -843,35 +843,35 @@ vector<int>& ChamferMatcher::Template::getTemplateAddresses(int width)
ChamferMatcher
::
Template
*
ChamferMatcher
::
Template
::
rescale
(
float
new_scale
)
ChamferMatcher
::
Template
*
ChamferMatcher
::
Template
::
rescale
(
float
new_scale
)
{
{
if
(
fabs
(
scale
-
new_scale
)
<
1e-6
)
return
this
;
if
(
fabs
(
scale
-
new_scale
)
<
1e-6
)
return
this
;
for
(
size_t
i
=
0
;
i
<
scaled_templates
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
scaled_templates
.
size
();
++
i
)
{
if
(
fabs
(
scaled_templates
[
i
]
->
scale
-
new_scale
)
<
1e-6
)
{
if
(
fabs
(
scaled_templates
[
i
]
->
scale
-
new_scale
)
<
1e-6
)
{
return
scaled_templates
[
i
];
return
scaled_templates
[
i
];
}
}
}
}
float
scale_factor
=
new_scale
/
scale
;
float
scale_factor
=
new_scale
/
scale
;
Template
*
tpl
=
new
Template
();
Template
*
tpl
=
new
Template
();
tpl
->
scale
=
new_scale
;
tpl
->
scale
=
new_scale
;
tpl
->
center
.
x
=
int
(
center
.
x
*
scale_factor
+
0.5
);
tpl
->
center
.
x
=
int
(
center
.
x
*
scale_factor
+
0.5
);
tpl
->
center
.
y
=
int
(
center
.
y
*
scale_factor
+
0.5
);
tpl
->
center
.
y
=
int
(
center
.
y
*
scale_factor
+
0.5
);
tpl
->
size
.
width
=
int
(
size
.
width
*
scale_factor
+
0.5
);
tpl
->
size
.
width
=
int
(
size
.
width
*
scale_factor
+
0.5
);
tpl
->
size
.
height
=
int
(
size
.
height
*
scale_factor
+
0.5
);
tpl
->
size
.
height
=
int
(
size
.
height
*
scale_factor
+
0.5
);
tpl
->
coords
.
resize
(
coords
.
size
());
tpl
->
coords
.
resize
(
coords
.
size
());
tpl
->
orientations
.
resize
(
orientations
.
size
());
tpl
->
orientations
.
resize
(
orientations
.
size
());
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
tpl
->
coords
[
i
].
first
=
int
(
coords
[
i
].
first
*
scale_factor
+
0.5
);
tpl
->
coords
[
i
].
first
=
int
(
coords
[
i
].
first
*
scale_factor
+
0.5
);
tpl
->
coords
[
i
].
second
=
int
(
coords
[
i
].
second
*
scale_factor
+
0.5
);
tpl
->
coords
[
i
].
second
=
int
(
coords
[
i
].
second
*
scale_factor
+
0.5
);
tpl
->
orientations
[
i
]
=
orientations
[
i
];
tpl
->
orientations
[
i
]
=
orientations
[
i
];
}
}
scaled_templates
.
push_back
(
tpl
);
scaled_templates
.
push_back
(
tpl
);
return
tpl
;
return
tpl
;
}
}
...
@@ -879,42 +879,42 @@ ChamferMatcher::Template* ChamferMatcher::Template::rescale(float new_scale)
...
@@ -879,42 +879,42 @@ ChamferMatcher::Template* ChamferMatcher::Template::rescale(float new_scale)
void
ChamferMatcher
::
Template
::
show
()
const
void
ChamferMatcher
::
Template
::
show
()
const
{
{
int
pad
=
50
;
int
pad
=
50
;
//Attention size is not correct
//Attention size is not correct
Mat
templ_color
(
Size
(
size
.
width
+
(
pad
*
2
),
size
.
height
+
(
pad
*
2
)),
CV_8UC3
);
Mat
templ_color
(
Size
(
size
.
width
+
(
pad
*
2
),
size
.
height
+
(
pad
*
2
)),
CV_8UC3
);
templ_color
.
setTo
(
0
);
templ_color
.
setTo
(
0
);
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
int
x
=
center
.
x
+
coords
[
i
].
first
+
pad
;
int
x
=
center
.
x
+
coords
[
i
].
first
+
pad
;
int
y
=
center
.
y
+
coords
[
i
].
second
+
pad
;
int
y
=
center
.
y
+
coords
[
i
].
second
+
pad
;
templ_color
.
at
<
Vec3b
>
(
y
,
x
)[
1
]
=
255
;
templ_color
.
at
<
Vec3b
>
(
y
,
x
)[
1
]
=
255
;
//CV_PIXEL(unsigned char, templ_color,x,y)[1] = 255;
//CV_PIXEL(unsigned char, templ_color,x,y)[1] = 255;
if
(
i
%
3
==
0
)
{
if
(
i
%
3
==
0
)
{
if
(
orientations
[
i
]
<
-
CV_PI
)
{
if
(
orientations
[
i
]
<
-
CV_PI
)
{
continue
;
continue
;
}
}
Point
p1
;
Point
p1
;
p1
.
x
=
x
;
p1
.
x
=
x
;
p1
.
y
=
y
;
p1
.
y
=
y
;
Point
p2
;
Point
p2
;
p2
.
x
=
x
+
pad
*
(
int
)(
sin
(
orientations
[
i
])
*
100
)
/
100
;
p2
.
x
=
x
+
pad
*
(
int
)(
sin
(
orientations
[
i
])
*
100
)
/
100
;
p2
.
y
=
y
+
pad
*
(
int
)(
cos
(
orientations
[
i
])
*
100
)
/
100
;
p2
.
y
=
y
+
pad
*
(
int
)(
cos
(
orientations
[
i
])
*
100
)
/
100
;
line
(
templ_color
,
p1
,
p2
,
CV_RGB
(
255
,
0
,
0
));
line
(
templ_color
,
p1
,
p2
,
CV_RGB
(
255
,
0
,
0
));
}
}
}
}
circle
(
templ_color
,
Point
(
center
.
x
+
pad
,
center
.
y
+
pad
),
1
,
CV_RGB
(
0
,
255
,
0
));
circle
(
templ_color
,
Point
(
center
.
x
+
pad
,
center
.
y
+
pad
),
1
,
CV_RGB
(
0
,
255
,
0
));
namedWindow
(
"templ"
,
1
);
namedWindow
(
"templ"
,
1
);
imshow
(
"templ"
,
templ_color
);
imshow
(
"templ"
,
templ_color
);
cvWaitKey
(
0
);
cvWaitKey
(
0
);
templ_color
.
release
();
templ_color
.
release
();
}
}
...
@@ -923,17 +923,17 @@ void ChamferMatcher::Template::show() const
...
@@ -923,17 +923,17 @@ void ChamferMatcher::Template::show() const
void
ChamferMatcher
::
Matching
::
addTemplateFromImage
(
Mat
&
templ
,
float
scale
)
void
ChamferMatcher
::
Matching
::
addTemplateFromImage
(
Mat
&
templ
,
float
scale
)
{
{
Template
*
cmt
=
new
Template
(
templ
,
scale
);
Template
*
cmt
=
new
Template
(
templ
,
scale
);
if
(
templates
.
size
()
>
0
)
if
(
templates
.
size
()
>
0
)
templates
.
clear
();
templates
.
clear
();
templates
.
push_back
(
cmt
);
templates
.
push_back
(
cmt
);
cmt
->
show
();
cmt
->
show
();
}
}
void
ChamferMatcher
::
Matching
::
addTemplate
(
Template
&
template_
){
void
ChamferMatcher
::
Matching
::
addTemplate
(
Template
&
template_
){
if
(
templates
.
size
()
>
0
)
if
(
templates
.
size
()
>
0
)
templates
.
clear
();
templates
.
clear
();
templates
.
push_back
(
&
template_
);
templates
.
push_back
(
&
template_
);
}
}
/**
/**
* Alternative version of computeDistanceTransform, will probably be used to compute distance
* Alternative version of computeDistanceTransform, will probably be used to compute distance
...
@@ -941,224 +941,227 @@ void ChamferMatcher::Matching::addTemplate(Template& template_){
...
@@ -941,224 +941,227 @@ void ChamferMatcher::Matching::addTemplate(Template& template_){
*/
*/
void
ChamferMatcher
::
Matching
::
computeDistanceTransform
(
Mat
&
edges_img
,
Mat
&
dist_img
,
Mat
&
annotate_img
,
float
truncate_dt
,
float
a
=
1.0
,
float
b
=
1.5
)
void
ChamferMatcher
::
Matching
::
computeDistanceTransform
(
Mat
&
edges_img
,
Mat
&
dist_img
,
Mat
&
annotate_img
,
float
truncate_dt
,
float
a
=
1.0
,
float
b
=
1.5
)
{
{
int
d
[][
2
]
=
{
{
-
1
,
-
1
},
{
0
,
-
1
},
{
1
,
-
1
},
int
d
[][
2
]
=
{
{
-
1
,
-
1
},
{
0
,
-
1
},
{
1
,
-
1
},
{
-
1
,
0
},
{
1
,
0
},
{
-
1
,
0
},
{
1
,
0
},
{
-
1
,
1
},
{
0
,
1
},
{
1
,
1
}
};
{
-
1
,
1
},
{
0
,
1
},
{
1
,
1
}
};
Size
s
=
edges_img
.
size
();
Size
s
=
edges_img
.
size
();
int
w
=
s
.
width
;
int
w
=
s
.
width
;
int
h
=
s
.
height
;
int
h
=
s
.
height
;
// set distance to the edge pixels to 0 and put them in the queue
// set distance to the edge pixels to 0 and put them in the queue
std
::
queue
<
std
::
pair
<
int
,
int
>
>
q
;
std
::
queue
<
std
::
pair
<
int
,
int
>
>
q
;
for
(
int
y
=
0
;
y
<
h
;
++
y
)
{
for
(
int
y
=
0
;
y
<
h
;
++
y
)
{
for
(
int
x
=
0
;
x
<
w
;
++
x
)
{
for
(
int
x
=
0
;
x
<
w
;
++
x
)
{
unsigned
char
edge_val
=
edges_img
.
at
<
uchar
>
(
y
,
x
);
unsigned
char
edge_val
=
edges_img
.
at
<
uchar
>
(
y
,
x
);
if
(
(
edge_val
!=
0
)
)
{
if
(
(
edge_val
!=
0
)
)
{
q
.
push
(
std
::
make_pair
(
x
,
y
));
q
.
push
(
std
::
make_pair
(
x
,
y
));
dist_img
.
at
<
float
>
(
y
,
x
)
=
0
;
dist_img
.
at
<
float
>
(
y
,
x
)
=
0
;
if
(
&
annotate_img
!=
NULL
)
{
if
(
&
annotate_img
!=
NULL
)
{
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
0
]
=
x
;
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
0
]
=
x
;
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
1
]
=
y
;
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
1
]
=
y
;
}
}
}
}
else
{
else
{
dist_img
.
at
<
float
>
(
y
,
x
)
=-
1
;
dist_img
.
at
<
float
>
(
y
,
x
)
=-
1
;
}
}
}
}
}
}
// breadth first computation of distance transform
// breadth first computation of distance transform
std
::
pair
<
int
,
int
>
crt
;
std
::
pair
<
int
,
int
>
crt
;
while
(
!
q
.
empty
())
{
while
(
!
q
.
empty
())
{
crt
=
q
.
front
();
crt
=
q
.
front
();
q
.
pop
();
q
.
pop
();
int
x
=
crt
.
first
;
int
x
=
crt
.
first
;
int
y
=
crt
.
second
;
int
y
=
crt
.
second
;
float
dist_orig
=
dist_img
.
at
<
float
>
(
y
,
x
);
float
dist_orig
=
dist_img
.
at
<
float
>
(
y
,
x
);
float
dist
;
float
dist
;
for
(
size_t
i
=
0
;
i
<
sizeof
(
d
)
/
sizeof
(
d
[
0
]);
++
i
)
{
for
(
size_t
i
=
0
;
i
<
sizeof
(
d
)
/
sizeof
(
d
[
0
]);
++
i
)
{
int
nx
=
x
+
d
[
i
][
0
];
int
nx
=
x
+
d
[
i
][
0
];
int
ny
=
y
+
d
[
i
][
1
];
int
ny
=
y
+
d
[
i
][
1
];
if
(
nx
<
0
||
ny
<
0
||
nx
>=
w
||
ny
>=
h
)
continue
;
if
(
nx
<
0
||
ny
<
0
||
nx
>=
w
||
ny
>=
h
)
continue
;
if
(
std
::
abs
(
d
[
i
][
0
]
+
d
[
i
][
1
])
==
1
)
{
if
(
std
::
abs
(
d
[
i
][
0
]
+
d
[
i
][
1
])
==
1
)
{
dist
=
(
dist_orig
)
+
a
;
dist
=
(
dist_orig
)
+
a
;
}
}
else
{
else
{
dist
=
(
dist_orig
)
+
b
;
dist
=
(
dist_orig
)
+
b
;
}
}
float
dt
=
dist_img
.
at
<
float
>
(
ny
,
nx
);
float
dt
=
dist_img
.
at
<
float
>
(
ny
,
nx
);
if
(
dt
==-
1
||
dt
>
dist
)
{
if
(
dt
==-
1
||
dt
>
dist
)
{
dist_img
.
at
<
float
>
(
ny
,
nx
)
=
dist
;
dist_img
.
at
<
float
>
(
ny
,
nx
)
=
dist
;
q
.
push
(
std
::
make_pair
(
nx
,
ny
));
q
.
push
(
std
::
make_pair
(
nx
,
ny
));
if
(
&
annotate_img
!=
NULL
)
{
if
(
&
annotate_img
!=
NULL
)
{
annotate_img
.
at
<
Vec2i
>
(
ny
,
nx
)[
0
]
=
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
0
];
annotate_img
.
at
<
Vec2i
>
(
ny
,
nx
)[
0
]
=
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
0
];
annotate_img
.
at
<
Vec2i
>
(
ny
,
nx
)[
1
]
=
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
1
];
annotate_img
.
at
<
Vec2i
>
(
ny
,
nx
)[
1
]
=
annotate_img
.
at
<
Vec2i
>
(
y
,
x
)[
1
];
}
}
}
}
}
}
}
}
// truncate dt
// truncate dt
if
(
truncate_dt
>
0
)
{
if
(
truncate_dt
>
0
)
{
Mat
dist_img_thr
=
dist_img
.
clone
();
Mat
dist_img_thr
=
dist_img
.
clone
();
threshold
(
dist_img
,
dist_img_thr
,
truncate_dt
,
0.0
,
THRESH_TRUNC
);
threshold
(
dist_img
,
dist_img_thr
,
truncate_dt
,
0.0
,
THRESH_TRUNC
);
dist_img_thr
.
copyTo
(
dist_img
);
dist_img_thr
.
copyTo
(
dist_img
);
}
}
}
}
void
ChamferMatcher
::
Matching
::
computeEdgeOrientations
(
Mat
&
edge_img
,
Mat
&
orientation_img
)
void
ChamferMatcher
::
Matching
::
computeEdgeOrientations
(
Mat
&
edge_img
,
Mat
&
orientation_img
)
{
{
Mat
contour_img
(
edge_img
.
size
(),
CV_8UC1
);
Mat
contour_img
(
edge_img
.
size
(),
CV_8UC1
);
orientation_img
.
setTo
(
3
*
(
-
CV_PI
));
orientation_img
.
setTo
(
3
*
(
-
CV_PI
));
template_coords_t
coords
;
template_coords_t
coords
;
template_orientations_t
orientations
;
template_orientations_t
orientations
;
while
(
ChamferMatcher
::
Matching
::
findContour
(
edge_img
,
coords
))
{
while
(
ChamferMatcher
::
Matching
::
findContour
(
edge_img
,
coords
))
{
ChamferMatcher
::
Matching
::
findContourOrientations
(
coords
,
orientations
);
ChamferMatcher
::
Matching
::
findContourOrientations
(
coords
,
orientations
);
// set orientation pixel in orientation image
// set orientation pixel in orientation image
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
coords
.
size
();
++
i
)
{
int
x
=
coords
[
i
].
first
;
int
x
=
coords
[
i
].
first
;
int
y
=
coords
[
i
].
second
;
int
y
=
coords
[
i
].
second
;
//
if (orientations[i]>-CV_PI)
//
if (orientations[i]>-CV_PI)
//
{
//
{
//CV_PIXEL(unsigned char, contour_img, x, y)[0] = 255;
//CV_PIXEL(unsigned char, contour_img, x, y)[0] = 255;
contour_img
.
at
<
uchar
>
(
y
,
x
)
=
255
;
contour_img
.
at
<
uchar
>
(
y
,
x
)
=
255
;
//
}
//
}
//CV_PIXEL(float, orientation_img, x, y)[0] = orientations[i];
//CV_PIXEL(float, orientation_img, x, y)[0] = orientations[i];
orientation_img
.
at
<
float
>
(
y
,
x
)
=
orientations
[
i
];
orientation_img
.
at
<
float
>
(
y
,
x
)
=
orientations
[
i
];
}
}
coords
.
clear
();
coords
.
clear
();
orientations
.
clear
();
orientations
.
clear
();
}
}
//imwrite("contours.pgm", contour_img);
//imwrite("contours.pgm", contour_img);
}
}
void
ChamferMatcher
::
Matching
::
fillNonContourOrientations
(
Mat
&
annotated_img
,
Mat
&
orientation_img
)
void
ChamferMatcher
::
Matching
::
fillNonContourOrientations
(
Mat
&
annotated_img
,
Mat
&
orientation_img
)
{
{
int
cols
=
annotated_img
.
cols
;
int
cols
=
annotated_img
.
cols
;
int
rows
=
annotated_img
.
rows
;
int
rows
=
annotated_img
.
rows
;
assert
(
orientation_img
.
cols
==
cols
&&
orientation_img
.
rows
==
rows
);
assert
(
orientation_img
.
cols
==
cols
&&
orientation_img
.
rows
==
rows
);
for
(
int
y
=
0
;
y
<
rows
;
++
y
)
{
for
(
int
y
=
0
;
y
<
rows
;
++
y
)
{
for
(
int
x
=
0
;
x
<
cols
;
++
x
)
{
for
(
int
x
=
0
;
x
<
cols
;
++
x
)
{
int
xorig
=
annotated_img
.
at
<
Vec2i
>
(
y
,
x
)[
0
];
int
xorig
=
annotated_img
.
at
<
Vec2i
>
(
y
,
x
)[
0
];
int
yorig
=
annotated_img
.
at
<
Vec2i
>
(
y
,
x
)[
1
];
int
yorig
=
annotated_img
.
at
<
Vec2i
>
(
y
,
x
)[
1
];
if
(
x
!=
xorig
||
y
!=
yorig
)
{
if
(
x
!=
xorig
||
y
!=
yorig
)
{
//orientation_img.at<float>(yorig,xorig)=orientation_img.at<float>(y,x);
//orientation_img.at<float>(yorig,xorig)=orientation_img.at<float>(y,x);
orientation_img
.
at
<
float
>
(
y
,
x
)
=
orientation_img
.
at
<
float
>
(
yorig
,
xorig
);
orientation_img
.
at
<
float
>
(
y
,
x
)
=
orientation_img
.
at
<
float
>
(
yorig
,
xorig
);
}
}
}
}
}
}
}
}
ChamferMatcher
::
Match
*
ChamferMatcher
::
Matching
::
localChamferDistance
(
Point
offset
,
Mat
&
dist_img
,
Mat
&
orientation_img
,
ChamferMatcher
::
Match
*
ChamferMatcher
::
Matching
::
localChamferDistance
(
Point
offset
,
Mat
&
dist_img
,
Mat
&
orientation_img
,
ChamferMatcher
::
Template
*
tpl
,
float
alpha
)
ChamferMatcher
::
Template
*
tpl
,
float
alpha
)
{
{
int
x
=
offset
.
x
;
int
x
=
offset
.
x
;
int
y
=
offset
.
y
;
int
y
=
offset
.
y
;
float
beta
=
1
-
alpha
;
float
beta
=
1
-
alpha
;
std
::
vector
<
int
>&
addr
=
tpl
->
getTemplateAddresses
(
dist_img
.
cols
);
std
::
vector
<
int
>&
addr
=
tpl
->
getTemplateAddresses
(
dist_img
.
cols
);
float
*
ptr
=
dist_img
.
ptr
<
float
>
(
y
)
+
x
;
float
*
ptr
=
dist_img
.
ptr
<
float
>
(
y
)
+
x
;
float
sum_distance
=
0
;
float
sum_distance
=
0
;
for
(
size_t
i
=
0
;
i
<
addr
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
addr
.
size
();
++
i
)
{
if
(
addr
[
i
]
<
(
dist_img
.
cols
*
dist_img
.
rows
)
-
(
offset
.
y
*
dist_img
.
cols
+
offset
.
x
)){
if
(
addr
[
i
]
<
(
dist_img
.
cols
*
dist_img
.
rows
)
-
(
offset
.
y
*
dist_img
.
cols
+
offset
.
x
)){
sum_distance
+=
*
(
ptr
+
addr
[
i
]);
sum_distance
+=
*
(
ptr
+
addr
[
i
]);
}
}
}
}
float
cost
=
(
sum_distance
/
truncate_
)
/
addr
.
size
();
float
cost
=
(
sum_distance
/
truncate_
)
/
addr
.
size
();
if
(
&
orientation_img
!=
NULL
)
{
if
(
&
orientation_img
!=
NULL
)
{
float
*
optr
=
orientation_img
.
ptr
<
float
>
(
y
)
+
x
;
float
*
optr
=
orientation_img
.
ptr
<
float
>
(
y
)
+
x
;
float
sum_orientation
=
0
;
float
sum_orientation
=
0
;
int
cnt_orientation
=
0
;
int
cnt_orientation
=
0
;
for
(
size_t
i
=
0
;
i
<
addr
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
addr
.
size
();
++
i
)
{
if
(
addr
[
i
]
<
(
orientation_img
.
cols
*
orientation_img
.
rows
)
-
(
offset
.
y
*
orientation_img
.
cols
+
offset
.
x
)){
if
(
addr
[
i
]
<
(
orientation_img
.
cols
*
orientation_img
.
rows
)
-
(
offset
.
y
*
orientation_img
.
cols
+
offset
.
x
)){
if
(
tpl
->
orientations
[
i
]
>=-
CV_PI
&&
(
*
(
optr
+
addr
[
i
]))
>=-
CV_PI
)
{
if
(
tpl
->
orientations
[
i
]
>=-
CV_PI
&&
(
*
(
optr
+
addr
[
i
]))
>=-
CV_PI
)
{
sum_orientation
+=
orientation_diff
(
tpl
->
orientations
[
i
],
(
*
(
optr
+
addr
[
i
])));
sum_orientation
+=
orientation_diff
(
tpl
->
orientations
[
i
],
(
*
(
optr
+
addr
[
i
])));
cnt_orientation
++
;
cnt_orientation
++
;
}
}
}
}
}
}
if
(
cnt_orientation
>
0
)
{
if
(
cnt_orientation
>
0
)
{
cost
=
(
float
)(
beta
*
cost
+
alpha
*
(
sum_orientation
/
(
2
*
CV_PI
))
/
cnt_orientation
);
cost
=
(
float
)(
beta
*
cost
+
alpha
*
(
sum_orientation
/
(
2
*
CV_PI
))
/
cnt_orientation
);
}
}
}
}
if
(
cost
>
0
){
if
(
cost
>
0
){
ChamferMatcher
::
Match
*
istance
(
new
ChamferMatcher
::
Match
()
);
ChamferMatcher
::
Match
*
istance
=
new
ChamferMatcher
::
Match
(
);
istance
->
cost
=
cost
;
istance
->
cost
=
cost
;
istance
->
offset
=
offset
;
istance
->
offset
=
offset
;
istance
->
tpl
=
tpl
;
istance
->
tpl
=
tpl
;
return
istance
;
return
istance
;
}
}
return
NULL
;
return
NULL
;
}
}
ChamferMatcher
::
Matches
*
ChamferMatcher
::
Matching
::
matchTemplates
(
Mat
&
dist_img
,
Mat
&
orientation_img
,
const
ImageRange
&
range
,
float
orientation_weight
)
ChamferMatcher
::
Matches
*
ChamferMatcher
::
Matching
::
matchTemplates
(
Mat
&
dist_img
,
Mat
&
orientation_img
,
const
ImageRange
&
range
,
float
orientation_weight
)
{
{
ChamferMatcher
::
Matches
*
matches
(
new
Matches
());
ChamferMatcher
::
Matches
*
matches
(
new
Matches
());
// try each template
// try each template
for
(
size_t
i
=
0
;
i
<
templates
.
size
();
i
++
)
{
for
(
size_t
i
=
0
;
i
<
templates
.
size
();
i
++
)
{
ImageIterator
*
it
=
range
.
iterator
();
ImageIterator
*
it
=
range
.
iterator
();
while
(
it
->
hasNext
())
{
while
(
it
->
hasNext
())
{
location_scale_t
crt
=
it
->
next
();
location_scale_t
crt
=
it
->
next
();
Point
loc
=
crt
.
first
;
Point
loc
=
crt
.
first
;
float
scale
=
crt
.
second
;
float
scale
=
crt
.
second
;
Template
*
tpl
=
templates
[
i
]
->
rescale
(
scale
);
Template
*
tpl
=
templates
[
i
]
->
rescale
(
scale
);
if
(
loc
.
x
-
tpl
->
center
.
x
<
0
||
loc
.
x
+
tpl
->
size
.
width
/
2
>=
dist_img
.
cols
)
continue
;
if
(
loc
.
x
-
tpl
->
center
.
x
<
0
||
loc
.
x
+
tpl
->
size
.
width
/
2
>=
dist_img
.
cols
)
continue
;
if
(
loc
.
y
-
tpl
->
center
.
y
<
0
||
loc
.
y
+
tpl
->
size
.
height
/
2
>=
dist_img
.
rows
)
continue
;
if
(
loc
.
y
-
tpl
->
center
.
y
<
0
||
loc
.
y
+
tpl
->
size
.
height
/
2
>=
dist_img
.
rows
)
continue
;
ChamferMatcher
::
Match
*
is
=
localChamferDistance
(
loc
,
dist_img
,
orientation_img
,
tpl
,
orientation_weight
);
ChamferMatcher
::
Match
*
is
=
localChamferDistance
(
loc
,
dist_img
,
orientation_img
,
tpl
,
orientation_weight
);
if
(
is
)
if
(
is
)
matches
->
push_back
(
*
is
);
{
}
matches
->
push_back
(
*
is
);
delete
is
;
delete
it
;
}
}
}
return
matches
;
delete
it
;
}
return
matches
;
}
}
...
@@ -1170,184 +1173,184 @@ ChamferMatcher::Matches* ChamferMatcher::Matching::matchTemplates(Mat& dist_img,
...
@@ -1170,184 +1173,184 @@ ChamferMatcher::Matches* ChamferMatcher::Matching::matchTemplates(Mat& dist_img,
*/
*/
ChamferMatcher
::
Matches
*
ChamferMatcher
::
Matching
::
matchEdgeImage
(
Mat
&
edge_img
,
const
ImageRange
&
range
,
float
orientation_weight
,
int
/*max_matches*/
,
float
/*min_match_distance*/
)
ChamferMatcher
::
Matches
*
ChamferMatcher
::
Matching
::
matchEdgeImage
(
Mat
&
edge_img
,
const
ImageRange
&
range
,
float
orientation_weight
,
int
/*max_matches*/
,
float
/*min_match_distance*/
)
{
{
CV_Assert
(
edge_img
.
channels
()
==
1
);
CV_Assert
(
edge_img
.
channels
()
==
1
);
Mat
dist_img
;
Mat
dist_img
;
Mat
annotated_img
;
Mat
annotated_img
;
Mat
orientation_img
;
Mat
orientation_img
;
annotated_img
.
create
(
edge_img
.
size
(),
CV_32SC2
);
annotated_img
.
create
(
edge_img
.
size
(),
CV_32SC2
);
dist_img
.
create
(
edge_img
.
size
(),
CV_32FC1
);
dist_img
.
create
(
edge_img
.
size
(),
CV_32FC1
);
dist_img
.
setTo
(
0
);
dist_img
.
setTo
(
0
);
// Computing distance transform
// Computing distance transform
computeDistanceTransform
(
edge_img
,
dist_img
,
annotated_img
,
truncate_
);
computeDistanceTransform
(
edge_img
,
dist_img
,
annotated_img
,
truncate_
);
//orientation_img = NULL;
//orientation_img = NULL;
if
(
use_orientation_
)
{
if
(
use_orientation_
)
{
orientation_img
.
create
(
edge_img
.
size
(),
CV_32FC1
);
orientation_img
.
create
(
edge_img
.
size
(),
CV_32FC1
);
orientation_img
.
setTo
(
0
);
orientation_img
.
setTo
(
0
);
Mat
edge_clone
=
edge_img
.
clone
();
Mat
edge_clone
=
edge_img
.
clone
();
computeEdgeOrientations
(
edge_clone
,
orientation_img
);
computeEdgeOrientations
(
edge_clone
,
orientation_img
);
edge_clone
.
release
();
edge_clone
.
release
();
fillNonContourOrientations
(
annotated_img
,
orientation_img
);
fillNonContourOrientations
(
annotated_img
,
orientation_img
);
}
}
// Template matching
// Template matching
ChamferMatcher
::
Matches
*
matches
=
matchTemplates
(
dist_img
,
ChamferMatcher
::
Matches
*
matches
=
matchTemplates
(
dist_img
,
orientation_img
,
orientation_img
,
range
,
range
,
orientation_weight
);
orientation_weight
);
if
(
use_orientation_
)
{
if
(
use_orientation_
)
{
orientation_img
.
release
();
orientation_img
.
release
();
}
}
dist_img
.
release
();
dist_img
.
release
();
annotated_img
.
release
();
annotated_img
.
release
();
return
matches
;
return
matches
;
}
}
void
ChamferMatcher
::
addMatch
(
float
cost
,
Point
offset
,
const
Template
*
tpl
)
void
ChamferMatcher
::
addMatch
(
float
cost
,
Point
offset
,
const
Template
*
tpl
)
{
{
bool
new_match
=
true
;
bool
new_match
=
true
;
for
(
int
i
=
0
;
i
<
count
;
++
i
)
{
for
(
int
i
=
0
;
i
<
count
;
++
i
)
{
if
(
std
::
abs
(
matches
[
i
].
offset
.
x
-
offset
.
x
)
+
std
::
abs
(
matches
[
i
].
offset
.
y
-
offset
.
y
)
<
min_match_distance_
)
{
if
(
std
::
abs
(
matches
[
i
].
offset
.
x
-
offset
.
x
)
+
std
::
abs
(
matches
[
i
].
offset
.
y
-
offset
.
y
)
<
min_match_distance_
)
{
// too close, not a new match
// too close, not a new match
new_match
=
false
;
new_match
=
false
;
// if better cost, replace existing match
// if better cost, replace existing match
if
(
cost
<
matches
[
i
].
cost
)
{
if
(
cost
<
matches
[
i
].
cost
)
{
matches
[
i
].
cost
=
cost
;
matches
[
i
].
cost
=
cost
;
matches
[
i
].
offset
=
offset
;
matches
[
i
].
offset
=
offset
;
matches
[
i
].
tpl
=
tpl
;
matches
[
i
].
tpl
=
tpl
;
}
}
// re-bubble to keep ordered
// re-bubble to keep ordered
int
k
=
i
;
int
k
=
i
;
while
(
k
>
0
)
{
while
(
k
>
0
)
{
if
(
matches
[
k
-
1
].
cost
>
matches
[
k
].
cost
)
{
if
(
matches
[
k
-
1
].
cost
>
matches
[
k
].
cost
)
{
std
::
swap
(
matches
[
k
-
1
],
matches
[
k
]);
std
::
swap
(
matches
[
k
-
1
],
matches
[
k
]);
}
}
k
--
;
k
--
;
}
}
break
;
break
;
}
}
}
}
if
(
new_match
)
{
if
(
new_match
)
{
// if we don't have enough matches yet, add it to the array
// if we don't have enough matches yet, add it to the array
if
(
count
<
max_matches_
)
{
if
(
count
<
max_matches_
)
{
matches
[
count
].
cost
=
cost
;
matches
[
count
].
cost
=
cost
;
matches
[
count
].
offset
=
offset
;
matches
[
count
].
offset
=
offset
;
matches
[
count
].
tpl
=
tpl
;
matches
[
count
].
tpl
=
tpl
;
count
++
;
count
++
;
}
}
// otherwise find the right position to insert it
// otherwise find the right position to insert it
else
{
else
{
// if higher cost than the worst current match, just ignore it
// if higher cost than the worst current match, just ignore it
if
(
matches
[
count
-
1
].
cost
<
cost
)
{
if
(
matches
[
count
-
1
].
cost
<
cost
)
{
return
;
return
;
}
}
int
j
=
0
;
int
j
=
0
;
// skip all matches better than current one
// skip all matches better than current one
while
(
matches
[
j
].
cost
<
cost
)
j
++
;
while
(
matches
[
j
].
cost
<
cost
)
j
++
;
// shift matches one position
// shift matches one position
int
k
=
count
-
2
;
int
k
=
count
-
2
;
while
(
k
>=
j
)
{
while
(
k
>=
j
)
{
matches
[
k
+
1
]
=
matches
[
k
];
matches
[
k
+
1
]
=
matches
[
k
];
k
--
;
k
--
;
}
}
matches
[
j
].
cost
=
cost
;
matches
[
j
].
cost
=
cost
;
matches
[
j
].
offset
=
offset
;
matches
[
j
].
offset
=
offset
;
matches
[
j
].
tpl
=
tpl
;
matches
[
j
].
tpl
=
tpl
;
}
}
}
}
}
}
void
ChamferMatcher
::
showMatch
(
Mat
&
img
,
int
index
)
void
ChamferMatcher
::
showMatch
(
Mat
&
img
,
int
index
)
{
{
if
(
index
>=
count
)
{
if
(
index
>=
count
)
{
std
::
cout
<<
"Index too big.
\n
"
<<
std
::
endl
;
std
::
cout
<<
"Index too big.
\n
"
<<
std
::
endl
;
}
}
assert
(
img
.
channels
()
==
3
);
assert
(
img
.
channels
()
==
3
);
Match
match
=
matches
[
index
];
Match
match
=
matches
[
index
];
const
template_coords_t
&
templ_coords
=
match
.
tpl
->
coords
;
const
template_coords_t
&
templ_coords
=
match
.
tpl
->
coords
;
int
x
,
y
;
int
x
,
y
;
for
(
size_t
i
=
0
;
i
<
templ_coords
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
templ_coords
.
size
();
++
i
)
{
x
=
match
.
offset
.
x
+
templ_coords
[
i
].
first
;
x
=
match
.
offset
.
x
+
templ_coords
[
i
].
first
;
y
=
match
.
offset
.
y
+
templ_coords
[
i
].
second
;
y
=
match
.
offset
.
y
+
templ_coords
[
i
].
second
;
if
(
x
>
img
.
cols
-
1
||
x
<
0
||
y
>
img
.
rows
-
1
||
y
<
0
)
continue
;
if
(
x
>
img
.
cols
-
1
||
x
<
0
||
y
>
img
.
rows
-
1
||
y
<
0
)
continue
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
0
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
0
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
2
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
2
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
1
]
=
255
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
1
]
=
255
;
}
}
}
}
void
ChamferMatcher
::
showMatch
(
Mat
&
img
,
Match
match
)
void
ChamferMatcher
::
showMatch
(
Mat
&
img
,
Match
match
)
{
{
assert
(
img
.
channels
()
==
3
);
assert
(
img
.
channels
()
==
3
);
const
template_coords_t
&
templ_coords
=
match
.
tpl
->
coords
;
const
template_coords_t
&
templ_coords
=
match
.
tpl
->
coords
;
for
(
size_t
i
=
0
;
i
<
templ_coords
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
templ_coords
.
size
();
++
i
)
{
int
x
=
match
.
offset
.
x
+
templ_coords
[
i
].
first
;
int
x
=
match
.
offset
.
x
+
templ_coords
[
i
].
first
;
int
y
=
match
.
offset
.
y
+
templ_coords
[
i
].
second
;
int
y
=
match
.
offset
.
y
+
templ_coords
[
i
].
second
;
if
(
x
>
img
.
cols
-
1
||
x
<
0
||
y
>
img
.
rows
-
1
||
y
<
0
)
continue
;
if
(
x
>
img
.
cols
-
1
||
x
<
0
||
y
>
img
.
rows
-
1
||
y
<
0
)
continue
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
0
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
0
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
2
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
2
]
=
0
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
1
]
=
255
;
img
.
at
<
Vec3b
>
(
y
,
x
)[
1
]
=
255
;
}
}
match
.
tpl
->
show
();
match
.
tpl
->
show
();
}
}
const
ChamferMatcher
::
Matches
&
ChamferMatcher
::
matching
(
Template
&
tpl
,
Mat
&
image_
){
const
ChamferMatcher
::
Matches
&
ChamferMatcher
::
matching
(
Template
&
tpl
,
Mat
&
image_
){
chamfer_
->
addTemplate
(
tpl
);
chamfer_
->
addTemplate
(
tpl
);
matches
.
clear
();
matches
.
clear
();
matches
.
resize
(
max_matches_
);
matches
.
resize
(
max_matches_
);
count
=
0
;
count
=
0
;
Matches
*
matches_
=
chamfer_
->
matchEdgeImage
(
image_
,
Matches
*
matches_
=
chamfer_
->
matchEdgeImage
(
image_
,
ChamferMatcher
::
ChamferMatcher
::
SlidingWindowImageRange
(
image_
.
cols
,
SlidingWindowImageRange
(
image_
.
cols
,
image_
.
rows
,
image_
.
rows
,
pad_x
,
pad_x
,
pad_y
,
pad_y
,
scales
,
scales
,
minScale
,
minScale
,
maxScale
),
maxScale
),
orientation_weight
,
orientation_weight
,
max_matches_
,
max_matches_
,
min_match_distance_
);
min_match_distance_
);
for
(
int
i
=
0
;
i
<
(
int
)
matches_
->
size
();
i
++
){
addMatch
(
matches_
->
at
(
i
).
cost
,
matches_
->
at
(
i
).
offset
,
matches_
->
at
(
i
).
tpl
);
}
matches_
->
clear
();
for
(
int
i
=
0
;
i
<
(
int
)
matches_
->
size
();
i
++
){
delete
matches_
;
addMatch
(
matches_
->
at
(
i
).
cost
,
matches_
->
at
(
i
).
offset
,
matches_
->
at
(
i
).
tpl
)
;
matches_
=
NULL
;
}
matches
.
resize
(
count
);
matches_
->
clear
();
delete
matches_
;
matches_
=
NULL
;
matches
.
resize
(
count
);
return
matches
;
return
matches
;
}
}
int
chamerMatching
(
Mat
&
img
,
Mat
&
templ
,
int
chamerMatching
(
Mat
&
img
,
Mat
&
templ
,
std
::
vector
<
std
::
vector
<
Point
>
>&
results
,
std
::
vector
<
float
>&
costs
,
std
::
vector
<
std
::
vector
<
Point
>
>&
results
,
std
::
vector
<
float
>&
costs
,
double
templScale
,
int
maxMatches
,
double
minMatchDistance
,
int
padX
,
double
templScale
,
int
maxMatches
,
double
minMatchDistance
,
int
padX
,
...
@@ -1355,22 +1358,22 @@ int chamerMatching( Mat& img, Mat& templ,
...
@@ -1355,22 +1358,22 @@ int chamerMatching( Mat& img, Mat& templ,
double
orientationWeight
,
double
truncate
)
double
orientationWeight
,
double
truncate
)
{
{
CV_Assert
(
img
.
type
()
==
CV_8UC1
&&
templ
.
type
()
==
CV_8UC1
);
CV_Assert
(
img
.
type
()
==
CV_8UC1
&&
templ
.
type
()
==
CV_8UC1
);
ChamferMatcher
matcher_
(
maxMatches
,
(
float
)
minMatchDistance
,
padX
,
padY
,
scales
,
ChamferMatcher
matcher_
(
maxMatches
,
(
float
)
minMatchDistance
,
padX
,
padY
,
scales
,
(
float
)
minScale
,
(
float
)
maxScale
,
(
float
)
minScale
,
(
float
)
maxScale
,
(
float
)
orientationWeight
,
(
float
)
truncate
);
(
float
)
orientationWeight
,
(
float
)
truncate
);
ChamferMatcher
::
Template
template_
(
templ
,
(
float
)
templScale
);
ChamferMatcher
::
Template
template_
(
templ
,
(
float
)
templScale
);
ChamferMatcher
::
Matches
match_instances
=
matcher_
.
matching
(
template_
,
img
);
ChamferMatcher
::
Matches
match_instances
=
matcher_
.
matching
(
template_
,
img
);
size_t
i
,
nmatches
=
match_instances
.
size
();
size_t
i
,
nmatches
=
match_instances
.
size
();
results
.
resize
(
nmatches
);
results
.
resize
(
nmatches
);
costs
.
resize
(
nmatches
);
costs
.
resize
(
nmatches
);
int
bestIdx
=
-
1
;
int
bestIdx
=
-
1
;
double
minCost
=
DBL_MAX
;
double
minCost
=
DBL_MAX
;
for
(
i
=
0
;
i
<
nmatches
;
i
++
)
for
(
i
=
0
;
i
<
nmatches
;
i
++
)
{
{
const
ChamferMatcher
::
Match
&
match
=
match_instances
[
i
];
const
ChamferMatcher
::
Match
&
match
=
match_instances
[
i
];
...
@@ -1381,12 +1384,12 @@ int chamerMatching( Mat& img, Mat& templ,
...
@@ -1381,12 +1384,12 @@ int chamerMatching( Mat& img, Mat& templ,
bestIdx
=
(
int
)
i
;
bestIdx
=
(
int
)
i
;
}
}
costs
[
i
]
=
(
float
)
cval
;
costs
[
i
]
=
(
float
)
cval
;
const
template_coords_t
&
templ_coords
=
match
.
tpl
->
coords
;
const
template_coords_t
&
templ_coords
=
match
.
tpl
->
coords
;
std
::
vector
<
Point
>&
templPoints
=
results
[
i
];
std
::
vector
<
Point
>&
templPoints
=
results
[
i
];
size_t
j
,
npoints
=
templ_coords
.
size
();
size_t
j
,
npoints
=
templ_coords
.
size
();
templPoints
.
resize
(
npoints
);
templPoints
.
resize
(
npoints
);
for
(
j
=
0
;
j
<
npoints
;
j
++
)
for
(
j
=
0
;
j
<
npoints
;
j
++
)
{
{
int
x
=
match
.
offset
.
x
+
templ_coords
[
j
].
first
;
int
x
=
match
.
offset
.
x
+
templ_coords
[
j
].
first
;
...
@@ -1394,7 +1397,7 @@ int chamerMatching( Mat& img, Mat& templ,
...
@@ -1394,7 +1397,7 @@ int chamerMatching( Mat& img, Mat& templ,
templPoints
[
j
]
=
Point
(
x
,
y
);
templPoints
[
j
]
=
Point
(
x
,
y
);
}
}
}
}
return
bestIdx
;
return
bestIdx
;
}
}
...
...
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