Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
4d793ddd
Commit
4d793ddd
authored
Apr 26, 2018
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added some utility routines to the hough_transform object.
parent
26c2cc4e
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
280 additions
and
29 deletions
+280
-29
hough_transform.h
dlib/image_transforms/hough_transform.h
+136
-18
hough_transform_abstract.h
dlib/image_transforms/hough_transform_abstract.h
+144
-11
No files found.
dlib/image_transforms/hough_transform.h
View file @
4d793ddd
...
@@ -81,17 +81,15 @@ namespace dlib
...
@@ -81,17 +81,15 @@ namespace dlib
// First we compute the radius measured in pixels from the center and the theta
// First we compute the radius measured in pixels from the center and the theta
// angle in radians.
// angle in radians.
typedef
dlib
::
vector
<
double
,
2
>
vect
;
double
theta
,
radius
;
const
rectangle
box
(
0
,
0
,
size
()
-
1
,
size
()
-
1
);
get_line_properties
(
p
,
theta
,
radius
);
const
vect
cent
=
center
(
box
);
theta
*=
pi
/
180
;
double
theta
=
p
.
x
()
-
cent
.
x
();
double
radius
=
p
.
y
()
-
cent
.
y
();
theta
=
theta
*
pi
/
even_size
;
radius
=
radius
*
sqrt_2
+
0
.
5
;
// now make a line segment on the line.
// now make a line segment on the line.
vect
v1
=
cent
+
vect
(
size
()
+
1000
,
0
)
+
vect
(
0
,
radius
);
const
rectangle
box
=
get_rect
(
*
this
);
vect
v2
=
cent
-
vect
(
size
()
+
1000
,
0
)
+
vect
(
0
,
radius
);
const
dpoint
cent
=
center
(
box
);
dpoint
v1
=
cent
+
dpoint
(
size
()
+
1000
,
0
)
+
dpoint
(
0
,
radius
);
dpoint
v2
=
cent
-
dpoint
(
size
()
+
1000
,
0
)
+
dpoint
(
0
,
radius
);
point
p1
=
rotate_point
(
cent
,
v1
,
theta
);
point
p1
=
rotate_point
(
cent
,
v1
,
theta
);
point
p2
=
rotate_point
(
cent
,
v2
,
theta
);
point
p2
=
rotate_point
(
cent
,
v2
,
theta
);
...
@@ -100,6 +98,28 @@ namespace dlib
...
@@ -100,6 +98,28 @@ namespace dlib
return
std
::
make_pair
(
p1
,
p2
);
return
std
::
make_pair
(
p1
,
p2
);
}
}
double
get_line_angle_in_degrees
(
const
point
&
p
)
const
{
double
angle
,
radius
;
get_line_properties
(
p
,
angle
,
radius
);
return
angle
;
}
void
get_line_properties
(
const
point
&
p
,
double
&
angle_in_degrees
,
double
&
radius
)
const
{
const
dpoint
cent
=
center
(
get_rect
(
*
this
));
double
theta
=
p
.
x
()
-
cent
.
x
();
radius
=
p
.
y
()
-
cent
.
y
();
angle_in_degrees
=
180
*
theta
/
even_size
;
radius
=
radius
*
sqrt_2
+
0
.
5
;
}
template
<
template
<
typename
image_type
typename
image_type
>
>
...
@@ -274,7 +294,7 @@ namespace dlib
...
@@ -274,7 +294,7 @@ namespace dlib
{
{
himg
[
hough_point
.
y
()][
hough_point
.
x
()]
+=
val
;
himg
[
hough_point
.
y
()][
hough_point
.
x
()]
+=
val
;
};
};
perform_hough_transform
(
img_
,
box
,
record_hit
);
perform_
generic_
hough_transform
(
img_
,
box
,
record_hit
);
}
}
template
<
template
<
...
@@ -296,12 +316,16 @@ namespace dlib
...
@@ -296,12 +316,16 @@ namespace dlib
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
const
in_image_type
&
img
,
const
in_image_type
&
img
,
const
rectangle
&
box
,
const
rectangle
&
box
,
const
std
::
vector
<
point
>&
hough_points
const
std
::
vector
<
point
>&
hough_points
,
const
unsigned
long
angle_window_size
=
1
,
const
unsigned
long
radius_window_size
=
1
)
const
)
const
{
{
typedef
typename
image_traits
<
in_image_type
>::
pixel_type
in_pixel_type
;
typedef
typename
image_traits
<
in_image_type
>::
pixel_type
in_pixel_type
;
DLIB_CASSERT
(
angle_window_size
>=
1
);
DLIB_CASSERT
(
radius_window_size
>=
1
);
DLIB_CASSERT
(
box
.
width
()
==
size
()
&&
box
.
height
()
==
size
(),
DLIB_CASSERT
(
box
.
width
()
==
size
()
&&
box
.
height
()
==
size
(),
"
\t
std::vector<std::vector<point>> hough_transform::find_pixels_voting_for_lines()"
"
\t
std::vector<std::vector<point>> hough_transform::find_pixels_voting_for_lines()"
<<
"
\n\t
Invalid arguments given to this function."
<<
"
\n\t
Invalid arguments given to this function."
...
@@ -325,7 +349,16 @@ namespace dlib
...
@@ -325,7 +349,16 @@ namespace dlib
matrix
<
uint32
>
hmap
(
size
(),
size
());
matrix
<
uint32
>
hmap
(
size
(),
size
());
hmap
=
hough_points
.
size
();
hmap
=
hough_points
.
size
();
for
(
size_t
i
=
0
;
i
<
hough_points
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
hough_points
.
size
();
++
i
)
hmap
(
hough_points
[
i
].
y
(),
hough_points
[
i
].
x
())
=
i
;
{
rectangle
area
=
centered_rect
(
hough_points
[
i
],
angle_window_size
,
radius_window_size
).
intersect
(
get_rect
(
hmap
));
for
(
long
r
=
area
.
top
();
r
<=
area
.
bottom
();
++
r
)
{
for
(
long
c
=
area
.
left
();
c
<=
area
.
right
();
++
c
)
{
hmap
(
r
,
c
)
=
i
;
}
}
}
// record that this image point voted for this Hough point
// record that this image point voted for this Hough point
auto
record_hit
=
[
&
](
const
point
&
hough_point
,
const
point
&
img_point
,
in_pixel_type
)
auto
record_hit
=
[
&
](
const
point
&
hough_point
,
const
point
&
img_point
,
in_pixel_type
)
...
@@ -335,7 +368,7 @@ namespace dlib
...
@@ -335,7 +368,7 @@ namespace dlib
constituent_points
[
idx
].
push_back
(
img_point
);
constituent_points
[
idx
].
push_back
(
img_point
);
};
};
perform_hough_transform
(
img
,
box
,
record_hit
);
perform_
generic_
hough_transform
(
img
,
box
,
record_hit
);
return
constituent_points
;
return
constituent_points
;
}
}
...
@@ -345,20 +378,90 @@ namespace dlib
...
@@ -345,20 +378,90 @@ namespace dlib
>
>
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
const
in_image_type
&
img
,
const
in_image_type
&
img
,
const
std
::
vector
<
point
>&
hough_points
const
std
::
vector
<
point
>&
hough_points
,
const
unsigned
long
angle_window_size
=
1
,
const
unsigned
long
radius_window_size
=
1
)
const
)
const
{
{
rectangle
box
(
0
,
0
,
num_columns
(
img
)
-
1
,
num_rows
(
img
)
-
1
);
rectangle
box
(
0
,
0
,
num_columns
(
img
)
-
1
,
num_rows
(
img
)
-
1
);
return
find_pixels_voting_for_lines
(
img
,
box
,
hough_points
);
return
find_pixels_voting_for_lines
(
img
,
box
,
hough_points
,
angle_window_size
,
radius_window_size
);
}
template
<
typename
image_type
,
typename
thresh_type
>
std
::
vector
<
point
>
find_strong_hough_points
(
const
image_type
&
himg_
,
const
thresh_type
hough_count_threshold
,
const
double
angle_nms_thresh
,
const
double
radius_nms_thresh
)
{
const_image_view
<
image_type
>
himg
(
himg_
);
DLIB_CASSERT
(
himg
.
nr
()
==
size
());
DLIB_CASSERT
(
himg
.
nc
()
==
size
());
DLIB_CASSERT
(
angle_nms_thresh
>=
0
)
DLIB_CASSERT
(
radius_nms_thresh
>=
0
)
std
::
vector
<
std
::
pair
<
double
,
point
>>
initial_lines
;
for
(
long
r
=
0
;
r
<
himg
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
himg
.
nc
();
++
c
)
{
if
(
himg
[
r
][
c
]
>=
hough_count_threshold
)
initial_lines
.
emplace_back
(
himg
[
r
][
c
],
point
(
c
,
r
));
}
}
std
::
vector
<
point
>
final_lines
;
std
::
vector
<
std
::
pair
<
double
,
double
>>
final_angle_and_radius
;
// Now do non-max suppression. First, sort the initial_lines so the best lines come first.
std
::
sort
(
initial_lines
.
rbegin
(),
initial_lines
.
rend
(),
[](
const
std
::
pair
<
double
,
point
>&
a
,
const
std
::
pair
<
double
,
point
>&
b
){
return
a
.
first
<
b
.
first
;});
for
(
auto
&
r
:
initial_lines
)
{
double
angle
,
radius
;
get_line_properties
(
r
.
second
,
angle
,
radius
);
// check if anything in final_lines is too close to r.second. If
// something is found then discard r.second.
auto
too_close
=
false
;
for
(
auto
&
ref
:
final_angle_and_radius
)
{
auto
&
ref_angle
=
ref
.
first
;
auto
&
ref_radius
=
ref
.
second
;
// We need to check for wrap around in angle since, for instance, a
// line with angle and radius of 90 and 10 is the same line as one with
// angle -90 and radius -10.
if
((
std
::
abs
(
ref_angle
-
angle
)
<
angle_nms_thresh
&&
std
::
abs
(
ref_radius
-
radius
)
<
radius_nms_thresh
)
||
(
180
-
std
::
abs
(
ref_angle
-
angle
)
<
angle_nms_thresh
&&
std
::
abs
(
ref_radius
+
radius
)
<
radius_nms_thresh
))
{
too_close
=
true
;
break
;
}
}
if
(
!
too_close
)
{
final_lines
.
emplace_back
(
r
.
second
);
final_angle_and_radius
.
emplace_back
(
angle
,
radius
);
}
}
return
final_lines
;
}
}
private
:
template
<
template
<
typename
in_image_type
,
typename
in_image_type
,
typename
record_hit_function_type
typename
record_hit_function_type
>
>
void
perform_hough_transform
(
void
perform_
generic_
hough_transform
(
const
in_image_type
&
img_
,
const
in_image_type
&
img_
,
const
rectangle
&
box
,
const
rectangle
&
box
,
record_hit_function_type
record_hit
record_hit_function_type
record_hit
...
@@ -368,7 +471,7 @@ namespace dlib
...
@@ -368,7 +471,7 @@ namespace dlib
typedef
typename
image_traits
<
in_image_type
>::
pixel_type
in_pixel_type
;
typedef
typename
image_traits
<
in_image_type
>::
pixel_type
in_pixel_type
;
DLIB_ASSERT
(
box
.
width
()
==
size
()
&&
box
.
height
()
==
size
(),
DLIB_ASSERT
(
box
.
width
()
==
size
()
&&
box
.
height
()
==
size
(),
"
\t
void hough_transform::perform_hough_transform()"
"
\t
void hough_transform::perform_
generic_
hough_transform()"
<<
"
\n\t
Invalid arguments given to this function."
<<
"
\n\t
Invalid arguments given to this function."
<<
"
\n\t
box.width(): "
<<
box
.
width
()
<<
"
\n\t
box.width(): "
<<
box
.
width
()
<<
"
\n\t
box.height(): "
<<
box
.
height
()
<<
"
\n\t
box.height(): "
<<
box
.
height
()
...
@@ -458,6 +561,21 @@ namespace dlib
...
@@ -458,6 +561,21 @@ namespace dlib
}
}
}
}
template
<
typename
in_image_type
,
typename
record_hit_function_type
>
void
perform_generic_hough_transform
(
const
in_image_type
&
img_
,
record_hit_function_type
record_hit
)
const
{
rectangle
box
(
0
,
0
,
num_columns
(
img_
)
-
1
,
num_rows
(
img_
)
-
1
);
perform_generic_hough_transform
(
img_
,
box
,
record_hit
);
}
private
:
unsigned
long
_size
;
unsigned
long
_size
;
unsigned
long
even_size
;
// equal to _size if _size is even, otherwise equal to _size-1.
unsigned
long
even_size
;
// equal to _size if _size is even, otherwise equal to _size-1.
matrix
<
int32
>
xcos_theta
,
ysin_theta
;
matrix
<
int32
>
xcos_theta
,
ysin_theta
;
...
...
dlib/image_transforms/hough_transform_abstract.h
View file @
4d793ddd
...
@@ -78,6 +78,37 @@ namespace dlib
...
@@ -78,6 +78,37 @@ namespace dlib
- The returned points are inside rectangle(0,0,size()-1,size()-1).
- The returned points are inside rectangle(0,0,size()-1,size()-1).
!*/
!*/
double
get_line_angle_in_degrees
(
const
point
&
p
)
const
;
/*!
requires
- rectangle(0,0,size()-1,size()-1).contains(p) == true
(i.e. p must be a point inside the Hough accumulator array)
ensures
- returns the angle, in degrees, of the line corresponding to the Hough
transform point p.
!*/
void
get_line_properties
(
const
point
&
p
,
double
&
angle_in_degrees
,
double
&
radius
)
const
;
/*!
requires
- rectangle(0,0,size()-1,size()-1).contains(p) == true
(i.e. p must be a point inside the Hough accumulator array)
ensures
- Converts a point in the Hough transform space into an angle, in degrees,
and a radius, measured in pixels from the center of the input image.
- #angle_in_degrees == the angle of the line corresponding to the Hough
transform point p. Moreover: -90 <= #angle_in_degrees < 90.
- #radius == the distance from the center of the input image, measured in
pixels, and the line corresponding to the Hough transform point p.
Moreover: -sqrt(size()*size()/2) <= #radius <= sqrt(size()*size()/2)
!*/
template
<
template
<
typename
image_type
typename
image_type
>
>
...
@@ -134,7 +165,9 @@ namespace dlib
...
@@ -134,7 +165,9 @@ namespace dlib
point in #himg corresponds to a line in the input box. In particular,
point in #himg corresponds to a line in the input box. In particular,
the line for #himg[y][x] is given by get_line(point(x,y)). Also, when
the line for #himg[y][x] is given by get_line(point(x,y)). Also, when
viewing the #himg image, the x-axis gives the angle of the line and the
viewing the #himg image, the x-axis gives the angle of the line and the
y-axis the distance of the line from the center of the box.
y-axis the distance of the line from the center of the box. The
conversion between Hough coordinates and angle and pixel distance can be
obtained by calling get_line_properties().
!*/
!*/
template
<
template
<
...
@@ -164,7 +197,9 @@ namespace dlib
...
@@ -164,7 +197,9 @@ namespace dlib
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
const
in_image_type
&
img
,
const
in_image_type
&
img
,
const
rectangle
&
box
,
const
rectangle
&
box
,
const
std
::
vector
<
point
>&
hough_points
const
std
::
vector
<
point
>&
hough_points
,
const
unsigned
long
angle_window_size
=
1
,
const
unsigned
long
radius_window_size
=
1
)
const
;
)
const
;
/*!
/*!
requires
requires
...
@@ -176,9 +211,11 @@ namespace dlib
...
@@ -176,9 +211,11 @@ namespace dlib
- get_rect(*this).contains(hough_points[i]) == true
- get_rect(*this).contains(hough_points[i]) == true
(i.e. hough_points must contain points in the output Hough transform
(i.e. hough_points must contain points in the output Hough transform
space generated by this object.)
space generated by this object.)
- angle_window_size >= 1
- radius_window_size >= 1
ensures
ensures
- This function computes the Hough transform of the part of img contained
- This function computes the Hough transform of the part of img contained
within box. It does the same computation as operator() define above,
within box. It does the same computation as operator() define
d
above,
except instead of accumulating into an image we create an explicit list
except instead of accumulating into an image we create an explicit list
of all the points in img that contributed to each line (i.e each point in
of all the points in img that contributed to each line (i.e each point in
the Hough image). To do this we take a list of Hough points as input and
the Hough image). To do this we take a list of Hough points as input and
...
@@ -191,13 +228,19 @@ namespace dlib
...
@@ -191,13 +228,19 @@ namespace dlib
It has the following properties:
It has the following properties:
- #CONSTITUENT_POINTS.size() == hough_points.size()
- #CONSTITUENT_POINTS.size() == hough_points.size()
- for all valid i:
- for all valid i:
- Any point in img with a non-zero value that lies on the line
- Let HP[i] = centered_rect(hough_points[i], angle_window_size, radius_window_size)
corresponding to the Hough point hough_points[i] is added to
- Any point in img with a non-zero value that lies on a line
corresponding to one of the Hough points in HP[i] is added to
CONSTITUENT_POINTS[i]. Therefore, when this routine finishes,
CONSTITUENT_POINTS[i]. Therefore, when this routine finishes,
#CONSTITUENT_POINTS[i] will contain all the points in img that voted
#CONSTITUENT_POINTS[i] will contain all the points in img that voted
for the line hough_points[i].
for the lines associated with the Hough accumulator bins in HP[i].
- #CONSTITUENT_POINTS[i].size() == the number of points in img that voted for
- #CONSTITUENT_POINTS[i].size() == the number of points in img that
the line hough_points[i].
voted for any of the lines HP[i] in Hough space. Note, however, that if
angle_window_size or radius_window_size are made so large that HP[i]
overlaps HP[j] for i!=j then the overlapping regions of Hough space
are assign to HP[i] or HP[j] arbitrarily. Therefore, all points in
CONSTITUENT_POINTS are unique, that is, there is no overlap in points
between any element of CONSTITUENT_POINTS.
!*/
!*/
template
<
template
<
...
@@ -205,7 +248,9 @@ namespace dlib
...
@@ -205,7 +248,9 @@ namespace dlib
>
>
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
std
::
vector
<
std
::
vector
<
point
>>
find_pixels_voting_for_lines
(
const
in_image_type
&
img
,
const
in_image_type
&
img
,
const
std
::
vector
<
point
>&
hough_points
const
std
::
vector
<
point
>&
hough_points
,
const
unsigned
long
angle_window_size
=
1
,
const
unsigned
long
radius_window_size
=
1
)
const
;
)
const
;
/*!
/*!
requires
requires
...
@@ -217,9 +262,97 @@ namespace dlib
...
@@ -217,9 +262,97 @@ namespace dlib
- get_rect(*this).contains(hough_points[i]) == true
- get_rect(*this).contains(hough_points[i]) == true
(i.e. hough_points must contain points in the output Hough transform
(i.e. hough_points must contain points in the output Hough transform
space generated by this object.)
space generated by this object.)
- angle_window_size >= 1
- radius_window_size >= 1
ensures
ensures
- performs: return find_pixels_voting_for_lines(img, get_rect(img), hough_points);
- performs: return find_pixels_voting_for_lines(img, get_rect(img), hough_points, angle_window_size, radius_window_size);
That is, just runs the hough transform on the whole input image.
That is, just runs the routine on the whole input image.
!*/
template
<
typename
image_type
,
typename
thresh_type
>
std
::
vector
<
point
>
find_strong_hough_points
(
const
image_type
&
himg
,
const
thresh_type
hough_count_threshold
,
const
double
angle_nms_thresh
,
const
double
radius_nms_thresh
);
/*!
requires
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h and it must contain grayscale pixels.
- himg.nr() == size()
- himg.nc() == size()
- angle_nms_thresh >= 0
- radius_nms_thresh >= 0
ensures
- This routine finds strong lines in a Hough transform and performs
non-maximum suppression on the detected lines. Recall that each point in
Hough space is associated with a line. Therefore, this routine finds all
the pixels in himg (a Hough transform image) with values >=
hough_count_threshold and performs non-maximum suppression on the
identified list of pixels. It does this by discarding lines that are
within angle_nms_thresh degrees of a stronger line or within
radius_nms_thresh distance (in terms of radius as defined by
get_line_properties()) to a stronger Hough point.
- The identified lines is returned as a list of coordinates in himg.
!*/
template
<
typename
in_image_type
,
typename
record_hit_function_type
>
void
perform_generic_hough_transform
(
const
in_image_type
&
img
,
const
rectangle
&
box
,
record_hit_function_type
record_hit
)
const
;
/*!
requires
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h and it must contain grayscale pixels.
- box.width() == size()
- box.height() == size()
- record_hit is a function object with the signature:
void record_hit(const point& hough_point, const point& img_point, in_image_pixel_type value)
ensures
- Computes the Hough transform of the part of img contained within box.
This routine is very general and allows you to implement a wide variety
of Hough transforms, in fact, the operator() and
find_pixels_voting_for_lines() routines defined above are implemented in
terms of perform_generic_hough_transform(). The behavior is described by
the following pseudo-code:
for (image_coordinate : all_coordinates_in_img)
for (hough_point : all_Hough_space_coordinates_for_lines_passing_through_image_coordinate)
record_hit(hough_point, image_coordinate, img[image_coordinate.y][image_coordinate.x()]);
That is, we perform the Hough transform, but rather than accumulating
into a Hough accumulator image, we call record_hit() and record_hit()
does whatever it wants. For example, in the operator() method defined
above record_hit() simply accumulates into an image, and therefor
performs the classic Hough transform. But there are many other options.
!*/
template
<
typename
in_image_type
,
typename
record_hit_function_type
>
void
perform_generic_hough_transform
(
const
in_image_type
&
img
,
record_hit_function_type
record_hit
)
const
;
/*!
requires
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h and it must contain grayscale pixels.
- record_hit is a function object with the signature:
void record_hit(const point& hough_point, const point& img_point, in_image_pixel_type value)
- num_rows(img) == size()
- num_columns(img) == size()
ensures
- performs: perform_generic_hough_transform(img, get_rect(img), record_hit);
That is, just runs the routine on the whole input image.
!*/
!*/
};
};
...
...
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