Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
7e7d8e90
Commit
7e7d8e90
authored
May 19, 2018
by
Davis King
Browse files
Added python interface to threshold_image() and partition_pixels().
parent
27dbbe2d
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
124 additions
and
1 deletion
+124
-1
tools/python/src/image.cpp
tools/python/src/image.cpp
+107
-0
tools/python/test/test_numpy_returns.py
tools/python/test/test_numpy_returns.py
+17
-1
No files found.
tools/python/src/image.cpp
View file @
7e7d8e90
...
@@ -26,6 +26,62 @@ string print_rgb_pixel_repr(const rgb_pixel& p)
...
@@ -26,6 +26,62 @@ string print_rgb_pixel_repr(const rgb_pixel& p)
return
sout
.
str
();
return
sout
.
str
();
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
T
>
numpy_image
<
unsigned
char
>
py_threshold_image2
(
const
numpy_image
<
T
>&
in_img
,
typename
pixel_traits
<
T
>::
basic_pixel_type
thresh
)
{
numpy_image
<
unsigned
char
>
out_img
;
threshold_image
(
in_img
,
out_img
);
return
out_img
;
}
template
<
typename
T
>
numpy_image
<
unsigned
char
>
py_threshold_image
(
const
numpy_image
<
T
>&
in_img
)
{
numpy_image
<
unsigned
char
>
out_img
;
threshold_image
(
in_img
,
out_img
);
return
out_img
;
}
// ----------------------------------------------------------------------------------------
template
<
typename
T
>
typename
pixel_traits
<
T
>::
basic_pixel_type
py_partition_pixels
(
const
numpy_image
<
T
>&
img
)
{
return
partition_pixels
(
img
);
}
template
<
typename
T
>
py
::
tuple
py_partition_pixels2
(
const
numpy_image
<
T
>&
img
,
int
num_thresholds
)
{
DLIB_CASSERT
(
1
<=
num_thresholds
&&
num_thresholds
<=
6
);
typename
pixel_traits
<
T
>::
basic_pixel_type
t1
,
t2
,
t3
,
t4
,
t5
,
t6
;
switch
(
num_thresholds
)
{
case
1
:
partition_pixels
(
img
,
t1
);
return
py
::
make_tuple
(
t1
);
case
2
:
partition_pixels
(
img
,
t1
,
t2
);
return
py
::
make_tuple
(
t1
,
t2
);
case
3
:
partition_pixels
(
img
,
t1
,
t2
,
t3
);
return
py
::
make_tuple
(
t1
,
t2
,
t3
);
case
4
:
partition_pixels
(
img
,
t1
,
t2
,
t3
,
t4
);
return
py
::
make_tuple
(
t1
,
t2
,
t3
,
t4
);
case
5
:
partition_pixels
(
img
,
t1
,
t2
,
t3
,
t4
,
t5
);
return
py
::
make_tuple
(
t1
,
t2
,
t3
,
t4
,
t5
);
case
6
:
partition_pixels
(
img
,
t1
,
t2
,
t3
,
t4
,
t5
,
t6
);
return
py
::
make_tuple
(
t1
,
t2
,
t3
,
t4
,
t5
,
t6
);
}
DLIB_CASSERT
(
false
,
"This should never happen."
);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void
bind_image_classes
(
py
::
module
&
m
)
void
bind_image_classes
(
py
::
module
&
m
)
...
@@ -37,4 +93,55 @@ void bind_image_classes(py::module& m)
...
@@ -37,4 +93,55 @@ void bind_image_classes(py::module& m)
.
def_readwrite
(
"red"
,
&
rgb_pixel
::
red
)
.
def_readwrite
(
"red"
,
&
rgb_pixel
::
red
)
.
def_readwrite
(
"green"
,
&
rgb_pixel
::
green
)
.
def_readwrite
(
"green"
,
&
rgb_pixel
::
green
)
.
def_readwrite
(
"blue"
,
&
rgb_pixel
::
blue
);
.
def_readwrite
(
"blue"
,
&
rgb_pixel
::
blue
);
const
char
*
docs
=
"Thresholds img and returns the result. Pixels in img with grayscale values >= partition_pixels(img)
\n
"
"have an output value of 255 and all others have a value of 0."
;
m
.
def
(
"threshold_image"
,
&
py_threshold_image
<
unsigned
char
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image
<
uint16_t
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image
<
uint32_t
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image
<
float
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image
<
double
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image
<
rgb_pixel
>
,
docs
,
py
::
arg
(
"img"
)
);
docs
=
"Thresholds img and returns the result. Pixels in img with grayscale values >= thresh
\n
"
"have an output value of 255 and all others have a value of 0."
;
m
.
def
(
"threshold_image"
,
&
py_threshold_image2
<
unsigned
char
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"thresh"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image2
<
uint16_t
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"thresh"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image2
<
uint32_t
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"thresh"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image2
<
float
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"thresh"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image2
<
double
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"thresh"
)
);
m
.
def
(
"threshold_image"
,
&
py_threshold_image2
<
rgb_pixel
>
,
docs
,
py
::
arg
(
"img"
),
py
::
arg
(
"thresh"
)
);
docs
=
"Finds a threshold value that would be reasonable to use with
\n
\
threshold_image(img, threshold). It does this by finding the threshold that
\n
\
partitions the pixels in img into two groups such that the sum of absolute
\n
\
deviations between each pixel and the mean of its group is minimized."
;
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels
<
rgb_pixel
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels
<
unsigned
char
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels
<
uint16_t
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels
<
uint32_t
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels
<
float
>
,
py
::
arg
(
"img"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels
<
double
>
,
docs
,
py
::
arg
(
"img"
)
);
docs
=
"This version of partition_pixels() finds multiple partitions rather than just
\n
\
one partition. It does this by first partitioning the pixels just as the
\n
\
above partition_pixels(img) does. Then it forms a new image with only pixels
\n
\
>= that first partition value and recursively partitions this new image.
\n
\
However, the recursion is implemented in an efficient way which is faster than
\n
\
explicitly forming these images and calling partition_pixels(), but the
\n
\
output is the same as if you did. For example, suppose you called
\n
\
[t1,t2,t2] = partition_pixels(img). Then we would have:
\n
\
- t1 == partition_pixels(img)
\n
\
- t2 == partition_pixels(an image with only pixels with values >= t1 in it)
\n
\
- t3 == partition_pixels(an image with only pixels with values >= t2 in it)"
;
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels2
<
rgb_pixel
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"num_thresholds"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels2
<
unsigned
char
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"num_thresholds"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels2
<
uint16_t
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"num_thresholds"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels2
<
uint32_t
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"num_thresholds"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels2
<
float
>
,
py
::
arg
(
"img"
),
py
::
arg
(
"num_thresholds"
)
);
m
.
def
(
"partition_pixels"
,
&
py_partition_pixels2
<
double
>
,
docs
,
py
::
arg
(
"img"
),
py
::
arg
(
"num_thresholds"
)
);
}
}
tools/python/test/test_numpy_returns.py
View file @
7e7d8e90
...
@@ -26,6 +26,22 @@ def get_test_face_chip():
...
@@ -26,6 +26,22 @@ def get_test_face_chip():
rgb_img
,
shape
=
get_test_image_and_shape
()
rgb_img
,
shape
=
get_test_image_and_shape
()
return
dlib
.
get_face_chip
(
rgb_img
,
shape
)
return
dlib
.
get_face_chip
(
rgb_img
,
shape
)
def
test_partition_pixels
():
truth
=
(
102
,
159
,
181
);
img
,
shape
=
get_test_image_and_shape
()
assert
(
dlib
.
partition_pixels
(
img
)
==
truth
[
0
])
assert
(
dlib
.
partition_pixels
(
img
,
3
)
==
truth
)
# Call all these versions of this mainly to make sure binding to
# various image types works.
assert
(
dlib
.
partition_pixels
(
img
[:,:,
0
])
==
125
)
assert
(
dlib
.
partition_pixels
(
img
[:,:,
0
].
astype
(
'float32'
))
==
125
)
assert
(
dlib
.
partition_pixels
(
img
[:,:,
0
].
astype
(
'float64'
))
==
125
)
assert
(
dlib
.
partition_pixels
(
img
[:,:,
0
].
astype
(
'uint16'
))
==
125
)
assert
(
dlib
.
partition_pixels
(
img
[:,:,
0
].
astype
(
'uint32'
))
==
125
)
# The tests below will be skipped if Numpy is not installed
# The tests below will be skipped if Numpy is not installed
@
pytest
.
mark
.
skipif
(
not
utils
.
is_numpy_installed
(),
reason
=
"requires numpy"
)
@
pytest
.
mark
.
skipif
(
not
utils
.
is_numpy_installed
(),
reason
=
"requires numpy"
)
def
test_get_face_chip
():
def
test_get_face_chip
():
...
@@ -63,4 +79,4 @@ def test_regression_issue_1220_get_face_chips():
...
@@ -63,4 +79,4 @@ def test_regression_issue_1220_get_face_chips():
count
=
sys
.
getrefcount
(
face_chips
)
count
=
sys
.
getrefcount
(
face_chips
)
assert
count
==
2
assert
count
==
2
count
=
sys
.
getrefcount
(
face_chips
[
0
])
count
=
sys
.
getrefcount
(
face_chips
[
0
])
assert
count
==
2
assert
count
==
2
\ No newline at end of file
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