Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
inovisao
pynovisao
Commits
40c35591
Commit
40c35591
authored
Jan 21, 2017
by
Alessandro dos Santos Ferreira
Browse files
Pynovisao - Documentando segmenters
parent
3c86801e
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
457 additions
and
2 deletions
+457
-2
src/main.py
src/main.py
+3
-1
src/segmentation/felzenszwalb.py
src/segmentation/felzenszwalb.py
+107
-0
src/segmentation/quickshift.py
src/segmentation/quickshift.py
+107
-0
src/segmentation/segmenter.py
src/segmentation/segmenter.py
+33
-1
src/segmentation/skimage_segmenter.py
src/segmentation/skimage_segmenter.py
+100
-0
src/segmentation/slic.py
src/segmentation/slic.py
+107
-0
No files found.
src/main.py
View file @
40c35591
...
...
@@ -12,7 +12,9 @@
As PEP 20 says, "Readability counts". So, follow the current conventions adopted in this project.
For more information access PEP 8 -- Style Guide for Python Code ( https://www.python.org/dev/peps/pep-0008/ ).
Use it as your guideline. Only use CamelCase in class names. DON'T USE CamelCase ou mixedCase in variable or functions.
Use it as your guideline. Only use CamelCase in class names. DON'T USE CamelCase ou mixedCase in variables or functions.
All declarations and comments in this project must be made in English.
Name: main.py
Author: Alessandro dos Santos Ferreira ( santosferreira.alessandro@gmail.com )
...
...
src/segmentation/felzenszwalb.py
View file @
40c35591
...
...
@@ -19,8 +19,24 @@ from segmenter import Segmenter
from
skimage_segmenter
import
SkimageSegmenter
class
Felzenszwalb
(
Segmenter
,
SkimageSegmenter
):
"""Run Felzenszwalb's method segmentation."""
def
__init__
(
self
,
scale
=
100.0
,
sigma
=
1.0
,
min_size
=
20
,
border_color
=
'Yellow'
,
border_outline
=
'No'
):
"""Constructor.
Parameters
----------
scale : integer, float, default = 100.0
Free parameter. Higher means larger clusters.
sigma : float, optional, default = 1.0
Width of Gaussian kernel used in preprocessing.
min_size : integer, optional, default = 20
Minimum component size. Enforced using postprocessing.
border_color : string
X11Color name of segment border color.
border_outline : string
If 'yes' double the size of segment border.
"""
super
(
self
.
__class__
,
self
).
__init__
(
border_color
,
border_outline
)
self
.
scale
=
Config
(
"Scale"
,
scale
,
float
)
...
...
@@ -29,6 +45,13 @@ class Felzenszwalb(Segmenter, SkimageSegmenter):
def
get_config
(
self
):
"""Return configuration of segmenter.
Returns
-------
config : OrderedDict
Current configs of segmenter.
"""
felzenszwalb_config
=
OrderedDict
()
felzenszwalb_config
[
"scale"
]
=
self
.
scale
...
...
@@ -40,6 +63,13 @@ class Felzenszwalb(Segmenter, SkimageSegmenter):
return
felzenszwalb_config
def
set_config
(
self
,
configs
):
"""Update configuration of segmenter.
Parameters
----------
configs : OrderedDict
New configs of segmenter.
"""
self
.
scale
=
Config
.
nvl_config
(
configs
[
"scale"
],
self
.
scale
)
self
.
sigma
=
Config
.
nvl_config
(
configs
[
"sigma"
],
self
.
sigma
)
self
.
min_size
=
Config
.
nvl_config
(
configs
[
"min_size"
],
self
.
min_size
)
...
...
@@ -49,6 +79,13 @@ class Felzenszwalb(Segmenter, SkimageSegmenter):
self
.
border_outline
.
value
=
self
.
border_outline
.
value
if
self
.
border_outline
.
value
==
'Yes'
else
'No'
def
get_summary_config
(
self
):
"""Return fomatted summary of configuration.
Returns
-------
summary : string
Formatted string with summary of configuration.
"""
felzenszwalb_config
=
OrderedDict
()
felzenszwalb_config
[
self
.
scale
.
label
]
=
self
.
scale
.
value
...
...
@@ -65,17 +102,85 @@ class Felzenszwalb(Segmenter, SkimageSegmenter):
def
get_list_segments
(
self
):
"""Return a list with segments after apply segmentation.
Returns
-------
segments : list
List of segments of segmented image.
"""
return
self
.
get_list_segments_skimage
()
def
get_segment
(
self
,
px
=
0
,
py
=
0
,
idx_segment
=
None
):
"""Return a specified segment using a index or position in image.
Parameters
----------
px : integer, optional, default = 0
Segment point inside the image in x-axis.
py : integer, optional, default = 0
Segment point inside the image in y-axis.
idx_segment : integer, optional, default = None
Index of segment returned by previous call of this method.
Returns
-------
segment : opencv 3-channel color image.
Rectangle encompassing the segment image.
size_segment : integer
Number of pixels of segment.
idx_segment : integer
Index of segment if found, -1 otherwise.
run_time : integer
Running time spent in milliseconds.
"""
return
self
.
get_segment_skimage
(
px
,
py
,
idx_segment
)
def
paint_segment
(
self
,
image
,
color
,
px
=
0
,
py
=
0
,
idx_segment
=
[],
border
=
True
,
clear
=
False
):
"""Paint a list of segments using a index or position in image.
Parameters
----------
image : opencv 3-channel color image.
Segmented image.
color : string
X11Color name.
px : integer, optional, default = 0
Segment point inside the image in x-axis.
py : integer, optional, default = 0
Segment point inside the image in y-axis.
idx_segment : list, optional, default = []
List of segments.
border : boolean, optional, default = True
If true paint the border of segments with default color.
clear : boolean, optional, default = False
If true clear previous painting in the image.
Returns
-------
new_image : opencv 3-channel color image.
Painted image.
run_time : integer
Running time spent in milliseconds.
"""
return
self
.
paint_segment_skimage
(
image
,
color
,
px
,
py
,
idx_segment
,
border
,
clear
)
def
run
(
self
,
image
):
"""Perform the segmentation
Parameters
----------
image : opencv 3-channel color image.
Original image.
Returns
-------
new_image : opencv 3-channel color image.
Segmented image.
run_time : integer
Running time spent in milliseconds.
"""
args
=
{
"scale"
:
self
.
scale
.
get_cast_val
(),
"sigma"
:
self
.
sigma
.
get_cast_val
(),
"min_size"
:
self
.
min_size
.
get_cast_val
()
...
...
@@ -85,4 +190,6 @@ class Felzenszwalb(Segmenter, SkimageSegmenter):
def
reset
(
self
):
"""Clean all data of segmentation.
"""
return
self
.
reset_skimage
()
src/segmentation/quickshift.py
View file @
40c35591
...
...
@@ -19,8 +19,24 @@ from segmenter import Segmenter
from
skimage_segmenter
import
SkimageSegmenter
class
Quickshift
(
Segmenter
,
SkimageSegmenter
):
"""Run Quickshift segmentation."""
def
__init__
(
self
,
ratio
=
0.5
,
kernel_size
=
2.0
,
max_dist
=
10.0
,
border_color
=
'Yellow'
,
border_outline
=
'No'
):
"""Constructor.
Parameters
----------
ratio : float, optional, between 0 and 1, default = 0.5
Balances color-space proximity and image-space proximity. Higher values give more weight to color-space.
kernel_size : float, optional, default = 2.0
Width of Gaussian kernel used in smoothing the sample density. Higher means fewer clusters.
max_dist : float, optional, default = 10.0
Cut-off point for data distances. Higher means fewer clusters.
border_color : string
X11Color name of segment border color.
border_outline : string
If 'yes' double the size of segment border.
"""
super
(
self
.
__class__
,
self
).
__init__
(
border_color
,
border_outline
)
self
.
ratio
=
Config
(
"Ratio [0-1]"
,
ratio
,
float
)
...
...
@@ -30,6 +46,13 @@ class Quickshift(Segmenter, SkimageSegmenter):
def
get_config
(
self
):
"""Return configuration of segmenter.
Returns
-------
config : OrderedDict
Current configs of segmenter.
"""
quickshift_config
=
OrderedDict
()
quickshift_config
[
"ratio"
]
=
self
.
ratio
...
...
@@ -42,6 +65,13 @@ class Quickshift(Segmenter, SkimageSegmenter):
return
quickshift_config
def
set_config
(
self
,
configs
):
"""Update configuration of segmenter.
Parameters
----------
configs : OrderedDict
New configs of segmenter.
"""
self
.
ratio
=
Config
.
nvl_config
(
configs
[
"ratio"
],
self
.
ratio
)
self
.
kernel_size
=
Config
.
nvl_config
(
configs
[
"kernel_size"
],
self
.
kernel_size
)
#self.sigma = Config.nvl_config(configs["sigma"], self.sigma)
...
...
@@ -53,6 +83,13 @@ class Quickshift(Segmenter, SkimageSegmenter):
self
.
border_outline
.
value
=
self
.
border_outline
.
value
if
self
.
border_outline
.
value
==
'Yes'
else
'No'
def
get_summary_config
(
self
):
"""Return fomatted summary of configuration.
Returns
-------
summary : string
Formatted string with summary of configuration.
"""
quickshift_config
=
OrderedDict
()
quickshift_config
[
self
.
ratio
.
label
]
=
self
.
ratio
.
value
...
...
@@ -70,17 +107,85 @@ class Quickshift(Segmenter, SkimageSegmenter):
def
get_list_segments
(
self
):
"""Return a list with segments after apply segmentation.
Returns
-------
segments : list
List of segments of segmented image.
"""
return
self
.
get_list_segments_skimage
()
def
get_segment
(
self
,
px
=
0
,
py
=
0
,
idx_segment
=
None
):
"""Return a specified segment using a index or position in image.
Parameters
----------
px : integer, optional, default = 0
Segment point inside the image in x-axis.
py : integer, optional, default = 0
Segment point inside the image in y-axis.
idx_segment : integer, optional, default = None
Index of segment returned by previous call of this method.
Returns
-------
segment : opencv 3-channel color image.
Rectangle encompassing the segment image.
size_segment : integer
Number of pixels of segment.
idx_segment : integer
Index of segment if found, -1 otherwise.
run_time : integer
Running time spent in milliseconds.
"""
return
self
.
get_segment_skimage
(
px
,
py
,
idx_segment
)
def
paint_segment
(
self
,
image
,
color
,
px
=
0
,
py
=
0
,
idx_segment
=
[],
border
=
True
,
clear
=
False
):
"""Paint a list of segments using a index or position in image.
Parameters
----------
image : opencv 3-channel color image.
Segmented image.
color : string
X11Color name.
px : integer, optional, default = 0
Segment point inside the image in x-axis.
py : integer, optional, default = 0
Segment point inside the image in y-axis.
idx_segment : list, optional, default = []
List of segments.
border : boolean, optional, default = True
If true paint the border of segments with default color.
clear : boolean, optional, default = False
If true clear previous painting in the image.
Returns
-------
new_image : opencv 3-channel color image.
Painted image.
run_time : integer
Running time spent in milliseconds.
"""
return
self
.
paint_segment_skimage
(
image
,
color
,
px
,
py
,
idx_segment
,
border
,
clear
)
def
run
(
self
,
image
):
"""Perform the segmentation
Parameters
----------
image : opencv 3-channel color image.
Original image.
Returns
-------
new_image : opencv 3-channel color image.
Segmented image.
run_time : integer
Running time spent in milliseconds.
"""
args
=
{
"ratio"
:
self
.
ratio
.
get_cast_val
(),
"kernel_size"
:
self
.
kernel_size
.
get_cast_val
(),
#"sigma": self.sigma.get_cast_val(),
...
...
@@ -91,4 +196,6 @@ class Quickshift(Segmenter, SkimageSegmenter):
def
reset
(
self
):
"""Clean all data of segmentation.
"""
return
self
.
reset_skimage
()
src/segmentation/segmenter.py
View file @
40c35591
...
...
@@ -11,40 +11,72 @@
from
abc
import
ABCMeta
,
abstractmethod
class
Segmenter
(
object
):
"""Abstract class for segmenter algorithms."""
__metaclass__
=
ABCMeta
def
get_name
(
self
):
"""Return the name of class.
Returns
-------
name : string
Returns the name of instantiated class.
"""
return
self
.
__class__
.
__name__
@
abstractmethod
def
get_config
(
self
):
"""Return configuration of segmenter.
Implement this method to extend this class with a new segmenter algorithm.
"""
pass
@
abstractmethod
def
set_config
(
self
,
configs
):
"""Update configuration of segmenter.
Implement this method to extend this class with a new segmenter algorithm.
"""
pass
@
abstractmethod
def
get_summary_config
(
self
):
"""Return fomatted summary of configuration.
Implement this method to extend this class with a new segmenter algorithm.
"""
pass
@
abstractmethod
def
get_list_segments
(
self
):
"""Return a list with segments after apply segmentation.
Implement this method to extend this class with a new segmenter algorithm.
"""
pass
@
abstractmethod
def
get_segment
(
self
,
px
,
py
,
idx_segment
):
"""Return a specified segment using a index or position in image.
Implement this method to extend this class with a new segmenter algorithm.
"""
pass
@
abstractmethod
def
paint_segment
(
self
,
image
,
color
,
px
,
py
,
idx_segment
,
border
,
clear
):
"""Paint a list of segments using a index or position in image.
Implement this method to extend this class with a new segmenter algorithm.
"""
pass
@
abstractmethod
def
run
(
self
,
image
):
"""Perform the segmentation
Implement this method to extend this class with a new segmenter algorithm.
"""
pass
@
abstractmethod
def
reset
(
self
):
pass
\ No newline at end of file
"""Clean all data of segmentation.
Implement this method to extend this class with a new classifier algorithm.
"""
pass
src/segmentation/skimage_segmenter.py
View file @
40c35591
...
...
@@ -20,6 +20,7 @@ from util.x11_colors import X11Colors
from
abc
import
ABCMeta
,
abstractmethod
class
SkimageSegmenter
(
object
):
"""Abstract class for segmenters implemented in skimage.segmentation."""
__metaclass__
=
ABCMeta
...
...
@@ -27,6 +28,15 @@ class SkimageSegmenter(object):
FORCE_OPT
=
False
def
__init__
(
self
,
border_color
=
'Yellow'
,
border_outline
=
'No'
):
"""Constructor.
Parameters
----------
border_color : string
X11Color name of segment border color.
border_outline : string
If 'yes' double the size of segment border.
"""
self
.
border_color
=
Config
(
"Border Color"
,
border_color
,
'color'
)
self
.
border_outline
=
Config
(
"Border Outline"
,
border_outline
,
str
)
...
...
@@ -35,6 +45,13 @@ class SkimageSegmenter(object):
def
get_list_segments_skimage
(
self
):
"""Return a list with segments after apply segmentation.
Returns
-------
segments : list
List of segments of segmented image.
"""
if
self
.
_segments
is
None
:
return
[]
...
...
@@ -42,14 +59,39 @@ class SkimageSegmenter(object):
def
get_segment_skimage
(
self
,
px
=
0
,
py
=
0
,
idx_segment
=
None
):
"""Return a specified segment using a index or position in image.
Parameters
----------
px : integer, optional, default = 0
Segment point inside the image in x-axis.
py : integer, optional, default = 0
Segment point inside the image in y-axis.
idx_segment : integer, optional, default = None
Index of segment returned by previous call of this method.
Returns
-------
segment : opencv 3-channel color image.
Rectangle encompassing the segment image.
size_segment : integer
Number of pixels of segment.
idx_segment : integer
Index of segment if found, -1 otherwise.
run_time : integer
Running time spent in milliseconds.
"""
# Check if segmentation was already performed
if
self
.
_segments
is
None
:
return
None
,
0
,
-
1
,
0
start_time
=
TimeUtils
.
get_time
()
# If idx_segment not passed, get the segment index using the points (px, py)
if
idx_segment
is
None
:
idx_segment
=
self
.
_segments
[
py
,
px
]
# Creating a mask, painting black all pixels outside of segment and white the pixels inside.
mask_segment
=
np
.
zeros
(
self
.
_original_image
.
shape
[:
2
],
dtype
=
"uint8"
)
mask_segment
[
self
.
_segments
==
idx_segment
]
=
255
size_segment
=
mask_segment
[
self
.
_segments
==
idx_segment
].
size
...
...
@@ -57,6 +99,7 @@ class SkimageSegmenter(object):
segment
=
self
.
_original_image
.
copy
()
segment
=
cv2
.
bitwise_and
(
segment
,
segment
,
mask
=
mask_segment
)
# Get the countours around the segment
contours
,
_
=
cv2
.
findContours
(
mask_segment
,
cv2
.
RETR_LIST
,
cv2
.
CHAIN_APPROX_SIMPLE
)[
-
2
:]
m
=
-
1
...
...
@@ -66,28 +109,61 @@ class SkimageSegmenter(object):
m
=
len
(
cnt
)
max_contour
=
cnt
# Get the rectangle that encompasses the countour
x
,
y
,
w
,
h
=
cv2
.
boundingRect
(
max_contour
)
segment
=
segment
[
y
:
y
+
h
,
x
:
x
+
w
]
end_time
=
TimeUtils
.
get_time
()
# Return the rectangle that encompasses the countour
return
segment
,
size_segment
,
idx_segment
,
(
end_time
-
start_time
)
def
paint_segment_skimage
(
self
,
image
,
color
,
px
=
0
,
py
=
0
,
idx_segment
=
[],
border
=
True
,
clear
=
False
):
"""Paint a list of segments using a index or position in image.
Parameters
----------
image : opencv 3-channel color image.
Segmented image.
color : string
X11Color name.
px : integer, optional, default = 0
Segment point inside the image in x-axis.
py : integer, optional, default = 0
Segment point inside the image in y-axis.
idx_segment : list, optional, default = []
List of segments.
border : boolean, optional, default = True
If true paint the border of segments with default color.
clear : boolean, optional, default = False
If true clear previous painting in the image.
Returns
-------
new_image : opencv 3-channel color image.
Painted image.
run_time : integer
Running time spent in milliseconds.
"""
# Check if segmentation was already performed
if
self
.
_segments
is
None
:
return
image
,
0
start_time
=
TimeUtils
.
get_time
()
# If idx_segment not passed, get the segment index using the points (px, py)
if
len
(
idx_segment
)
==
0
:
idx_segment
=
[
self
.
_segments
[
py
,
px
]]
height
,
width
,
channels
=
self
.
_original_image
.
shape
# Creating a mask, painting black all pixels outside of segment and white the pixels inside
mask_segment
=
np
.
zeros
(
self
.
_original_image
.
shape
[:
2
],
dtype
=
"uint8"
)
for
idx
in
idx_segment
:
mask_segment
[
self
.
_segments
==
idx
]
=
255
mask_inv
=
cv2
.
bitwise_not
(
mask_segment
)
# Paint all pixels in original image with color choosed
class_color
=
np
.
zeros
((
height
,
width
,
3
),
np
.
uint8
)
class_color
[:,
:]
=
X11Colors
.
get_color
(
color
)
if
SkimageSegmenter
.
FORCE_OPT
==
False
:
...
...
@@ -96,11 +172,13 @@ class SkimageSegmenter(object):
colored_image
=
cv2
.
addWeighted
(
image
,
0.7
,
class_color
,
0.3
,
0
)
colored_image
=
cv2
.
bitwise_and
(
colored_image
,
colored_image
,
mask
=
mask_segment
)
# Create a new image keeping the painting only in pixels inside of segment
new_image
=
image
if
clear
==
False
else
self
.
_original_image
new_image
=
cv2
.
bitwise_and
(
new_image
,
new_image
,
mask
=
mask_inv
)
mask_segment
[:]
=
255
new_image
=
cv2
.
bitwise_or
(
new_image
,
colored_image
,
mask
=
mask_segment
)
# If border is true, mark the boundary of images
if
border
==
True
and
SkimageSegmenter
.
FORCE_OPT
==
False
:
color
=
X11Colors
.
get_color_zero_one
(
self
.
border_color
.
get_cast_val
())
outline_color
=
color
if
self
.
border_outline
.
value
==
'Yes'
else
None
...
...
@@ -109,12 +187,32 @@ class SkimageSegmenter(object):
end_time
=
TimeUtils
.
get_time
()
# Return painted image
return
new_image
,
(
end_time
-
start_time
)
def
run_skimage
(
self
,
image
,
method
,
**
kwargs
):
"""Perform the segmentation
Parameters
----------
image : opencv 3-channel color image.
Original image.
method : function
Method from skyimage that performs the image segmentation.
kwargs : keyword arguments
Dict of the keyword args passed to the function.
Returns
-------
new_image : opencv 3-channel color image.
Segmented image.
run_time : integer
Running time spent in milliseconds.
"""
self
.
_original_image
=
image
# Run the segmentation using the method passed
start_time
=
TimeUtils
.
get_time
()
self
.
_segments
=
method
(
img_as_float
(
image
),
**
kwargs
)
end_time
=
TimeUtils
.
get_time
()
...
...
@@ -129,5 +227,7 @@ class SkimageSegmenter(object):
def
reset_skimage
(
self
):
"""Clean all data of segmentation.
"""
self
.
_segments
=
None
self
.
_original_image
=
None
src/segmentation/slic.py
View file @
40c35591
...
...
@@ -21,8 +21,24 @@ from segmenter import Segmenter
from
skimage_segmenter
import
SkimageSegmenter
class
Slic
(
Segmenter
,
SkimageSegmenter
):
"""Run SLIC (Simple Linear Iterative Clustering) segmentation."""
def
__init__
(
self
,
n_segments
=
250
,
sigma
=
5.0
,
compactness
=
10.0
,
border_color
=
'Yellow'
,
border_outline
=
'No'
):
"""Constructor.
Parameters
----------
n_segments : integer, optional, default = 250
The (approximate) number of labels in the segmented output image.
sigma : float, optional, default = 5.0
Width of Gaussian smoothing kernel for pre-processing.
compactness : float, optional, default = 10.0
Higher values give more weight to space proximity, making superpixel shapes more square/cubic.
border_color : string
X11Color name of segment border color.
border_outline : string
If 'yes' double the size of segment border.
"""
super
(
self
.
__class__
,
self
).
__init__
(
border_color
,
border_outline
)
self
.
n_segments
=
Config
(
"Segments"
,
n_segments
,
int
)
...
...
@@ -31,6 +47,13 @@ class Slic(Segmenter, SkimageSegmenter):
def
get_config
(
self
):
"""Return configuration of segmenter.
Returns
-------
config : OrderedDict
Current configs of segmenter.