Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
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_contrib
Commits
6891d778
Commit
6891d778
authored
Jan 11, 2017
by
Alexander Alekhin
Committed by
GitHub
Jan 11, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #923 from cbalint13:mslic
Add MSLIC (Manifold SLIC)
parents
04ad07c0
ce2fd8e3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
599 additions
and
26 deletions
+599
-26
superpixels_slic.png
modules/ximgproc/doc/pics/superpixels_slic.png
+0
-0
ximgproc.bib
modules/ximgproc/doc/ximgproc.bib
+8
-0
slic.hpp
modules/ximgproc/include/opencv2/ximgproc/slic.hpp
+11
-8
slic.cpp
modules/ximgproc/samples/slic.cpp
+2
-2
slic.cpp
modules/ximgproc/src/slic.cpp
+578
-16
No files found.
modules/ximgproc/doc/pics/superpixels_slic.png
View replaced file @
04ad07c0
View file @
6891d778
757 KB
|
W:
|
H:
966 KB
|
W:
|
H:
2-up
Swipe
Onion skin
modules/ximgproc/doc/ximgproc.bib
View file @
6891d778
...
...
@@ -160,6 +160,14 @@
keywords = {Superpixels, segmentation, clustering, k-means}
}
@InProceedings{Liu_2016_CVPR,
author = {Liu, Yong-Jin and Yu, Cheng-Chi and Yu, Min-Jing and He, Ying},
title = {Manifold SLIC: A Fast Method to Compute Content-Sensitive Superpixels},
booktitle = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR)},
month = {June},
year = {2016}
}
@InProceedings{LiCVPR2015LSC,
author = {Li, Zhengqin and Chen, Jiansheng},
title = {Superpixel Segmentation Using Linear Spectral Clustering},
...
...
modules/ximgproc/include/opencv2/ximgproc/slic.hpp
View file @
6891d778
...
...
@@ -61,6 +61,8 @@ namespace ximgproc
//! @addtogroup ximgproc_superpixel
//! @{
enum
SLIC
{
SLIC
=
100
,
SLICO
=
101
,
MSLIC
=
102
};
/** @brief Class implementing the SLIC (Simple Linear Iterative Clustering) superpixels
algorithm described in @cite Achanta2012.
...
...
@@ -68,7 +70,9 @@ SLIC (Simple Linear Iterative Clustering) clusters pixels using pixel channels a
to efficiently generate compact, nearly uniform superpixels. The simplicity of approach makes it
extremely easy to use a lone parameter specifies the number of superpixels and the efficiency of
the algorithm makes it very practical.
Several optimizations are available for SLIC class:
SLICO stands for "Zero parameter SLIC" and it is an optimization of baseline SLIC descibed in @cite Achanta2012.
MSLIC stands for "Manifold SLIC" and it is an optimization of baseline SLIC described in @cite Liu_2016_CVPR.
*/
class
CV_EXPORTS_W
SuperpixelSLIC
:
public
Algorithm
...
...
@@ -134,26 +138,25 @@ public:
};
/** @brief
Class implementing the SLIC (Simple Linear Iterative Clustering) superpixels
/** @brief
Initialize a SuperpixelSLIC object
@param image Image to segment
@param algorithm Chooses the algorithm variant to use:
SLIC segments image using a desired region_size, and in addition
SLICO will choose an adaptive compactness factor
.
SLIC segments image using a desired region_size, and in addition
SLICO will optimize using adaptive compactness factor,
while MSLIC will optimize using manifold methods resulting in more content-sensitive superpixels
.
@param region_size Chooses an average superpixel size measured in pixels
@param ruler Chooses the enforcement of superpixel smoothness factor of superpixel
The function initializes a SuperpixelSLIC object for the input image. It sets the parameters of choosed
superpixel algorithm, which are: region_size and ruler. It preallocate some buffers for future
computing iterations over the given image. An example of SLIC versus SLICO is ilustrated in the
following picture.
computing iterations over the given image. For enanched results it is recommended for color images to
preprocess image with little gaussian blur using a small 3 x 3 kernel and additional conversion into
CieLAB color space. An example of SLIC versus SLICO and MSLIC is ilustrated in the following picture.
![image](pics/superpixels_slic.png)
*/
enum
SLIC
{
SLIC
=
100
,
SLICO
=
101
};
CV_EXPORTS_W
Ptr
<
SuperpixelSLIC
>
createSuperpixelSLIC
(
InputArray
image
,
int
algorithm
=
SLICO
,
int
region_size
=
10
,
float
ruler
=
10.0
f
);
...
...
modules/ximgproc/samples/slic.cpp
View file @
6891d778
...
...
@@ -19,7 +19,7 @@ static const char* keys =
"{h help | | help menu}"
"{c camera |0| camera id}"
"{i image | | image file}"
"{a algorithm |1| SLIC(0),SLICO(1)}"
"{a algorithm |1| SLIC(0),SLICO(1)
,MSLIC(2)
}"
;
int
main
(
int
argc
,
char
**
argv
)
...
...
@@ -63,7 +63,7 @@ int main(int argc, char** argv)
}
namedWindow
(
window_name
,
0
);
createTrackbar
(
"Algorithm"
,
window_name
,
&
algorithm
,
1
,
0
);
createTrackbar
(
"Algorithm"
,
window_name
,
&
algorithm
,
2
,
0
);
createTrackbar
(
"Region size"
,
window_name
,
&
region_size
,
200
,
0
);
createTrackbar
(
"Ruler"
,
window_name
,
&
ruler
,
100
,
0
);
createTrackbar
(
"Connectivity"
,
window_name
,
&
min_element_size
,
100
,
0
);
...
...
modules/ximgproc/src/slic.cpp
View file @
6891d778
/*********************************************************************
* Software License Agreement (BSD License)
*
* Copyright (c) 2013
*
SLIC, SLICO
Copyright (c) 2013
* Radhakrishna Achanta
* email : Radhakrishna [dot] Achanta [at] epfl [dot] ch
* web : http://ivrl.epfl.ch/people/achanta
*
* MSLIC Copyright (c) 2016
* Yong-Jin Liu
* email : liuyongjin [at] tsinghua [dot] edu [dot] cn
* web : http://cg.cs.tsinghua.edu.cn/people/~Yongjin/yongjin.htm
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
...
...
@@ -44,6 +49,11 @@
Aurelien Lucchi, Pascal Fua, and Sabine Süsstrunk, EPFL Technical
Report no. 149300, June 2010.
"Manifold SLIC: A Fast Method to Compute Content-Sensitive Superpixels"
Yong-Jin Liu, Cheng-Chi Yu, Min-Jing Yu, Ying He,
The IEEE Conference on Computer Vision and Pattern Recognition (CVPR),
2016, pp. 651-659.
OpenCV port by: Cristian Balint <cristian dot balint at gmail dot com>
*/
...
...
@@ -99,6 +109,19 @@ protected:
// compactness
float
m_ruler
;
// ratio (MSLIC)
float
m_ratio
;
// split (MSLIC)
float
m_split
;
// current iter
int
m_cur_iter
;
// current iter
int
m_iterations
;
private
:
// labels no
...
...
@@ -120,6 +143,12 @@ private:
// seeds storage
vector
<
vector
<
float
>
>
m_kseeds
;
// adaptive k (MSLIC)
vector
<
float
>
m_adaptk
;
// merge threshold (MSLIC)
float
m_merge
;
// initialization
inline
void
initialize
();
...
...
@@ -140,6 +169,13 @@ private:
// SLICO
inline
void
PerformSLICO
(
const
int
&
num_iterations
);
// MSLIC
inline
void
PerformMSLIC
(
const
int
&
num_iterations
);
// MSLIC
inline
void
SuperpixelSplit
();
};
CV_EXPORTS
Ptr
<
SuperpixelSLIC
>
createSuperpixelSLIC
(
InputArray
image
,
int
algorithm
,
int
region_size
,
float
ruler
)
...
...
@@ -221,7 +257,8 @@ void SuperpixelSLICImpl::initialize()
if
(
m_algorithm
==
SLICO
)
GetChSeedsK
();
else
if
(
m_algorithm
==
SLIC
)
else
if
(
(
m_algorithm
==
SLIC
)
||
(
m_algorithm
==
MSLIC
)
)
GetChSeedsS
();
else
CV_Error
(
Error
::
StsInternal
,
"No such algorithm"
);
...
...
@@ -232,6 +269,11 @@ void SuperpixelSLICImpl::initialize()
// perturb seeds given edges
if
(
perturbseeds
)
PerturbSeeds
(
edgemag
);
if
(
m_algorithm
==
MSLIC
)
{
m_merge
=
4.0
f
;
m_adaptk
.
resize
(
m_numlabels
,
1.0
f
);
}
}
void
SuperpixelSLICImpl
::
iterate
(
int
num_iterations
)
...
...
@@ -240,6 +282,8 @@ void SuperpixelSLICImpl::iterate( int num_iterations )
PerformSLICO
(
num_iterations
);
else
if
(
m_algorithm
==
SLIC
)
PerformSLIC
(
num_iterations
);
else
if
(
m_algorithm
==
MSLIC
)
PerformMSLIC
(
num_iterations
);
else
CV_Error
(
Error
::
StsInternal
,
"No such algorithm"
);
...
...
@@ -316,6 +360,13 @@ void SuperpixelSLICImpl::enforceLabelConnectivity( int min_element_size )
if
(
min_element_size
==
0
)
return
;
CV_Assert
(
min_element_size
>=
0
&&
min_element_size
<=
100
);
vector
<
float
>
adaptk
(
m_numlabels
,
1.0
f
);
if
(
m_algorithm
==
MSLIC
)
{
adaptk
.
clear
();
}
const
int
dx4
[
4
]
=
{
-
1
,
0
,
1
,
0
};
const
int
dy4
[
4
]
=
{
0
,
-
1
,
0
,
1
};
...
...
@@ -331,6 +382,20 @@ void SuperpixelSLICImpl::enforceLabelConnectivity( int min_element_size )
vector
<
int
>
xvec
(
sz
);
vector
<
int
>
yvec
(
sz
);
// MSLIC
int
currentlabel
;
float
diffch
=
0.0
f
;
vector
<
float
>
adjch
;
vector
<
float
>
curch
;
map
<
int
,
int
>
hashtable
;
if
(
m_algorithm
==
MSLIC
)
{
hashtable
[
-
1
]
=
0
;
adjch
.
resize
(
m_nr_channels
,
0
);
curch
.
resize
(
m_nr_channels
,
0
);
}
//adjacent label
int
adjlabel
=
0
;
...
...
@@ -346,6 +411,7 @@ void SuperpixelSLICImpl::enforceLabelConnectivity( int min_element_size )
//--------------------
xvec
[
0
]
=
k
;
yvec
[
0
]
=
j
;
currentlabel
=
m_klabels
.
at
<
int
>
(
j
,
k
);
//-------------------------------------------------------
// Quickly find an adjacent label for use later if needed
//-------------------------------------------------------
...
...
@@ -355,11 +421,35 @@ void SuperpixelSLICImpl::enforceLabelConnectivity( int min_element_size )
int
y
=
yvec
[
0
]
+
dy4
[
n
];
if
(
(
x
>=
0
&&
x
<
m_width
)
&&
(
y
>=
0
&&
y
<
m_height
)
)
{
if
(
nlabels
.
at
<
int
>
(
y
,
x
)
!=
INT_MAX
)
adjlabel
=
nlabels
.
at
<
int
>
(
y
,
x
);
if
(
nlabels
.
at
<
int
>
(
y
,
x
)
!=
INT_MAX
)
{
adjlabel
=
nlabels
.
at
<
int
>
(
y
,
x
);
if
(
m_algorithm
==
MSLIC
)
{
for
(
int
b
=
0
;
b
<
m_nr_channels
;
b
++
)
{
adjch
[
b
]
=
m_kseeds
[
b
][
m_klabels
.
at
<
int
>
(
y
,
x
)];
}
}
}
}
}
if
(
m_algorithm
==
MSLIC
)
{
float
ssumch
=
0.0
f
;
for
(
int
b
=
0
;
b
<
m_nr_channels
;
b
++
)
{
curch
[
b
]
=
m_kseeds
[
b
][
m_klabels
.
at
<
int
>
(
j
,
k
)];
// squared distance
float
diff
=
curch
[
b
]
-
adjch
[
b
];
ssumch
+=
diff
*
diff
;
}
// L2 distance with adj
diffch
=
sqrt
(
ssumch
);
adaptk
.
push_back
(
m_adaptk
[
currentlabel
]
);
}
int
count
(
1
);
for
(
int
c
=
0
;
c
<
count
;
c
++
)
{
...
...
@@ -379,20 +469,74 @@ void SuperpixelSLICImpl::enforceLabelConnectivity( int min_element_size )
count
++
;
}
}
}
}
//-------------------------------------------------------
// If segment size is less then a limit, assign an
// adjacent label found before, and decrement label count.
//-------------------------------------------------------
if
(
count
<=
min_sp_sz
)
// MSLIC only
if
(
m_algorithm
==
MSLIC
)
{
for
(
int
c
=
0
;
c
<
count
;
c
++
)
{
nlabels
.
at
<
int
>
(
yvec
[
c
],
xvec
[
c
])
=
adjlabel
;
}
label
--
;
if
(
m_cur_iter
<
m_iterations
-
1
)
{
hashtable
[
label
]
=
count
;
//-------------------------------------------------------
// If segment size is less then a limit, or is very similar
// to it's neighbour assign adjacent label found before,
// and decrement label count.
//-------------------------------------------------------
if
(
(
count
<=
min_sp_sz
)
||
(
(
diffch
<
m_merge
)
&&
(
hashtable
[
adjlabel
]
+
hashtable
[(
int
)
adaptk
.
size
()
-
1
]
<=
3
*
m_region_size
*
m_region_size
)
)
)
{
if
(
(
diffch
<
m_merge
)
&&
(
hashtable
[
adjlabel
]
+
hashtable
[(
int
)
adaptk
.
size
()
-
1
]
<=
3
*
m_region_size
*
m_region_size
)
)
{
adaptk
[
adjlabel
]
=
min
(
2.0
f
,
float
(
adaptk
[
adjlabel
]
+
adaptk
[(
int
)
adaptk
.
size
()
-
1
])
);
hashtable
[
adjlabel
]
+=
hashtable
[(
int
)
adaptk
.
size
()
-
1
];
}
for
(
int
c
=
0
;
c
<
count
;
c
++
)
{
nlabels
.
at
<
int
>
(
yvec
[
c
],
xvec
[
c
])
=
adjlabel
;
}
label
--
;
adaptk
.
pop_back
();
}
}
else
{
//-------------------------------------------------------
// If segment size is less then a limit, assign an
// adjacent label found before, and decrement label count.
//-------------------------------------------------------
if
(
count
<=
min_sp_sz
)
{
for
(
int
c
=
0
;
c
<
count
;
c
++
)
{
nlabels
.
at
<
int
>
(
yvec
[
c
],
xvec
[
c
])
=
adjlabel
;
}
label
--
;
}
}
// SLIC or SLICO
}
else
{
//-------------------------------------------------------
// If segment size is less then a limit, assign an
// adjacent label found before, and decrement label count.
//-------------------------------------------------------
if
(
count
<=
min_sp_sz
)
{
for
(
int
c
=
0
;
c
<
count
;
c
++
)
{
nlabels
.
at
<
int
>
(
yvec
[
c
],
xvec
[
c
])
=
adjlabel
;
}
label
--
;
}
}
label
++
;
}
...
...
@@ -401,6 +545,9 @@ void SuperpixelSLICImpl::enforceLabelConnectivity( int min_element_size )
// replace old
m_klabels
=
nlabels
;
m_numlabels
=
label
;
m_adaptk
.
clear
();
m_adaptk
=
adaptk
;
}
/*
...
...
@@ -696,7 +843,7 @@ struct SeedNormInvoker : ParallelLoopBody
if
(
clustersize
->
at
(
k
)
<=
0
)
clustersize
->
at
(
k
)
=
1
;
for
(
int
b
=
0
;
b
<
nr_channels
;
b
++
)
kseeds
->
at
(
b
)[
k
]
=
sigma
->
at
(
b
)[
k
]
/
float
(
clustersize
->
at
(
k
));
;
kseeds
->
at
(
b
)[
k
]
=
sigma
->
at
(
b
)[
k
]
/
float
(
clustersize
->
at
(
k
));
kseedsx
->
at
(
k
)
=
sigmax
->
at
(
k
)
/
float
(
clustersize
->
at
(
k
));
kseedsy
->
at
(
k
)
=
sigmay
->
at
(
k
)
/
float
(
clustersize
->
at
(
k
));
...
...
@@ -1214,5 +1361,420 @@ inline void SuperpixelSLICImpl::PerformSLIC( const int& itrnum )
}
}
/*
* PerformSuperpixelMSLIC
*
*
*/
inline
void
SuperpixelSLICImpl
::
PerformMSLIC
(
const
int
&
itrnum
)
{
vector
<
vector
<
float
>
>
sigma
(
m_nr_channels
);
for
(
int
b
=
0
;
b
<
m_nr_channels
;
b
++
)
sigma
[
b
].
resize
(
m_numlabels
,
0
);
vector
<
float
>
sigmax
(
m_numlabels
,
0
);
vector
<
float
>
sigmay
(
m_numlabels
,
0
);
vector
<
int
>
clustersize
(
m_numlabels
,
0
);
Mat
distvec
(
m_height
,
m_width
,
CV_32F
);
const
float
xywt
=
(
m_region_size
/
m_ruler
)
*
(
m_region_size
/
m_ruler
);
int
offset
=
m_region_size
;
// from paper
m_split
=
4.0
f
;
m_ratio
=
5.0
f
;
for
(
int
itr
=
0
;
itr
<
itrnum
;
itr
++
)
{
m_cur_iter
=
itr
;
distvec
.
setTo
(
FLT_MAX
);
for
(
int
n
=
0
;
n
<
m_numlabels
;
n
++
)
{
if
(
m_adaptk
[
n
]
<
1.0
f
)
offset
=
int
(
m_region_size
*
m_adaptk
[
n
]);
else
offset
=
int
(
m_region_size
*
m_adaptk
[
n
]);
int
y1
=
max
(
0
,
(
int
)
m_kseedsy
[
n
]
-
offset
);
int
y2
=
min
(
m_height
,
(
int
)
m_kseedsy
[
n
]
+
offset
);
int
x1
=
max
(
0
,
(
int
)
m_kseedsx
[
n
]
-
offset
);
int
x2
=
min
(
m_width
,
(
int
)
m_kseedsx
[
n
]
+
offset
);
parallel_for_
(
Range
(
y1
,
y2
),
SLICGrowInvoker
(
&
m_chvec
,
&
distvec
,
&
m_klabels
,
m_kseedsx
[
n
],
m_kseedsy
[
n
],
xywt
,
&
m_kseeds
,
x1
,
x2
,
m_nr_channels
,
n
)
);
}
//-----------------------------------------------------------------
// Recalculate the centroid and store in the seed values
//-----------------------------------------------------------------
// instead of reassigning memory on each iteration, just reset.
// parallel reduce structure
SeedsCenters
sc
(
m_chvec
,
m_klabels
,
m_numlabels
,
m_nr_channels
);
// accumulate center distances
parallel_reduce
(
BlockedRange
(
0
,
m_width
),
sc
);
// normalize centers
parallel_for_
(
Range
(
0
,
m_numlabels
),
SeedNormInvoker
(
&
m_kseeds
,
&
sc
.
sigma
,
&
sc
.
clustersize
,
&
sc
.
sigmax
,
&
sc
.
sigmay
,
&
m_kseedsx
,
&
m_kseedsy
,
m_nr_channels
)
);
// 13% as in original paper
enforceLabelConnectivity
(
13
);
SuperpixelSplit
();
}
}
inline
void
SuperpixelSLICImpl
::
SuperpixelSplit
()
{
Mat
klabels
=
m_klabels
.
clone
();
// parallel reduce structure
SeedsCenters
msc
(
m_chvec
,
m_klabels
,
m_numlabels
,
m_nr_channels
);
// accumulate center distances
parallel_reduce
(
BlockedRange
(
0
,
m_width
),
msc
);
const
float
invwt
=
1.0
f
/
(
(
m_region_size
/
m_ruler
)
*
(
m_region_size
/
m_ruler
)
);
const
float
sqrt_invwt
=
sqrt
(
invwt
);
if
(
m_cur_iter
<
m_iterations
-
2
)
{
vector
<
float
>
avglabs
(
m_numlabels
,
0
);
for
(
int
y
=
0
;
y
<
m_height
-
1
;
y
++
)
{
for
(
int
x
=
0
;
x
<
m_width
-
1
;
x
++
)
{
if
(
klabels
.
at
<
int
>
(
y
,
x
)
==
klabels
.
at
<
int
>
(
y
+
1
,
x
)
&&
klabels
.
at
<
int
>
(
y
,
x
)
==
klabels
.
at
<
int
>
(
y
,
x
+
1
)
)
{
float
x1
=
1
,
y1
=
0
;
float
x2
=
0
,
y2
=
1
;
vector
<
float
>
ch1
(
m_nr_channels
);
vector
<
float
>
ch2
(
m_nr_channels
);
switch
(
m_chvec
.
at
(
0
).
depth
()
)
{
case
CV_8U
:
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch1
[
c
]
=
float
(
m_chvec
[
c
].
at
<
uchar
>
(
y
+
1
,
x
)
-
m_chvec
[
c
].
at
<
uchar
>
(
y
,
x
)
);
ch2
[
c
]
=
float
(
m_chvec
[
c
].
at
<
uchar
>
(
y
,
x
+
1
)
-
m_chvec
[
c
].
at
<
uchar
>
(
y
,
x
)
);
ch1
[
c
]
/=
sqrt_invwt
;
ch2
[
c
]
/=
sqrt_invwt
;
}
break
;
case
CV_8S
:
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch1
[
c
]
=
float
(
m_chvec
[
c
].
at
<
char
>
(
y
+
1
,
x
)
-
m_chvec
[
c
].
at
<
char
>
(
y
,
x
)
);
ch2
[
c
]
=
float
(
m_chvec
[
c
].
at
<
char
>
(
y
,
x
+
1
)
-
m_chvec
[
c
].
at
<
char
>
(
y
,
x
)
);
ch1
[
c
]
/=
sqrt_invwt
;
ch2
[
c
]
/=
sqrt_invwt
;
}
break
;
case
CV_16U
:
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch1
[
c
]
=
float
(
m_chvec
[
c
].
at
<
ushort
>
(
y
+
1
,
x
)
-
m_chvec
[
c
].
at
<
ushort
>
(
y
,
x
)
);
ch2
[
c
]
=
float
(
m_chvec
[
c
].
at
<
ushort
>
(
y
,
x
+
1
)
-
m_chvec
[
c
].
at
<
ushort
>
(
y
,
x
)
);
ch1
[
c
]
/=
sqrt_invwt
;
ch2
[
c
]
/=
sqrt_invwt
;
}
break
;
case
CV_16S
:
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch1
[
c
]
=
float
(
m_chvec
[
c
].
at
<
short
>
(
y
+
1
,
x
)
-
m_chvec
[
c
].
at
<
short
>
(
y
,
x
)
);
ch2
[
c
]
=
float
(
m_chvec
[
c
].
at
<
short
>
(
y
,
x
+
1
)
-
m_chvec
[
c
].
at
<
short
>
(
y
,
x
)
);
ch1
[
c
]
/=
sqrt_invwt
;
ch2
[
c
]
/=
sqrt_invwt
;
}
break
;
case
CV_32S
:
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch1
[
c
]
=
float
(
m_chvec
[
c
].
at
<
int
>
(
y
+
1
,
x
)
-
m_chvec
[
c
].
at
<
int
>
(
y
,
x
)
);
ch2
[
c
]
=
float
(
m_chvec
[
c
].
at
<
int
>
(
y
,
x
+
1
)
-
m_chvec
[
c
].
at
<
int
>
(
y
,
x
)
);
ch1
[
c
]
/=
sqrt_invwt
;
ch2
[
c
]
/=
sqrt_invwt
;
}
break
;
case
CV_32F
:
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch1
[
c
]
=
m_chvec
[
c
].
at
<
float
>
(
y
+
1
,
x
)
-
m_chvec
[
c
].
at
<
float
>
(
y
,
x
);
ch2
[
c
]
=
m_chvec
[
c
].
at
<
float
>
(
y
,
x
+
1
)
-
m_chvec
[
c
].
at
<
float
>
(
y
,
x
);
ch1
[
c
]
/=
sqrt_invwt
;
ch2
[
c
]
/=
sqrt_invwt
;
}
break
;
case
CV_64F
:
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch1
[
c
]
=
float
(
m_chvec
[
c
].
at
<
double
>
(
y
+
1
,
x
)
-
m_chvec
[
c
].
at
<
double
>
(
y
,
x
)
);
ch2
[
c
]
=
float
(
m_chvec
[
c
].
at
<
double
>
(
y
,
x
+
1
)
-
m_chvec
[
c
].
at
<
double
>
(
y
,
x
)
);
ch1
[
c
]
/=
sqrt_invwt
;
ch2
[
c
]
/=
sqrt_invwt
;
}
break
;
default
:
CV_Error
(
Error
::
StsInternal
,
"Invalid matrix depth"
);
break
;
}
float
ch11sqsum
=
0.0
f
;
float
ch12sqsum
=
0.0
f
;
float
ch22sqsum
=
0.0
f
;
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
ch11sqsum
+=
ch1
[
c
]
*
ch1
[
c
];
ch12sqsum
+=
ch1
[
c
]
*
ch2
[
c
];
ch22sqsum
+=
ch2
[
c
]
*
ch2
[
c
];
}
// adjacent metric for N channels
avglabs
[
klabels
.
at
<
int
>
(
y
,
x
)
]
+=
sqrt
(
(
x1
*
x1
+
y1
*
y1
+
ch11sqsum
)
*
(
x2
*
x2
+
y2
*
y2
+
ch22sqsum
)
-
(
x1
*
x2
+
y1
*
y2
+
ch12sqsum
)
*
(
x1
*
x2
+
y1
*
y2
+
ch12sqsum
)
);
}
}
}
for
(
int
i
=
0
;
i
<
m_numlabels
;
i
++
)
{
avglabs
[
i
]
/=
m_region_size
*
m_region_size
;
}
m_kseedsx
.
clear
();
m_kseedsy
.
clear
();
m_kseedsx
.
resize
(
m_numlabels
,
0
);
m_kseedsy
.
resize
(
m_numlabels
,
0
);
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
m_kseeds
[
c
].
clear
();
m_kseeds
[
c
].
resize
(
m_numlabels
,
0
);
}
for
(
int
k
=
0
;
k
<
m_numlabels
;
k
++
)
{
m_kseedsx
[
k
]
=
msc
.
sigmax
[
k
]
/
msc
.
clustersize
[
k
];
m_kseedsy
[
k
]
=
msc
.
sigmay
[
k
]
/
msc
.
clustersize
[
k
];
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
m_kseeds
[
c
][
k
]
=
msc
.
sigma
[
c
][
k
]
/
msc
.
clustersize
[
k
];
}
for
(
int
k
=
0
;
k
<
m_numlabels
;
k
++
)
{
int
xindex
=
0
,
yindex
=
0
;
if
(
(
m_adaptk
[
k
]
<=
0.5
f
)
||
(
avglabs
[
k
]
<
(
m_split
*
m_ratio
)
)
)
{
m_kseedsx
[
k
]
=
msc
.
sigmax
[
k
]
/
msc
.
clustersize
[
k
];
m_kseedsy
[
k
]
=
msc
.
sigmay
[
k
]
/
msc
.
clustersize
[
k
];
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
m_kseeds
[
c
][
k
]
=
msc
.
sigma
[
c
][
k
]
/
msc
.
clustersize
[
k
];
m_adaptk
[
k
]
=
sqrt
(
m_ratio
/
avglabs
[
k
]
);
m_adaptk
[
k
]
=
max
(
0.5
f
,
m_adaptk
[
k
]
);
m_adaptk
[
k
]
=
min
(
2.0
f
,
m_adaptk
[
k
]
);
}
// if segment size is too large
// split it and calculate four new seeds
else
{
xindex
=
(
int
)(
msc
.
sigmax
[
k
]
/
msc
.
clustersize
[
k
]
);
yindex
=
(
int
)(
msc
.
sigmay
[
k
]
/
msc
.
clustersize
[
k
]
);
m_adaptk
[
k
]
=
max
(
0.5
f
,
m_adaptk
[
k
]
/
2
);
const
float
minadaptk
=
min
(
1.0
f
,
m_adaptk
[
k
]
)
*
m_region_size
/
2
;
int
x1
=
(
int
)(
xindex
-
minadaptk
);
int
x2
=
(
int
)(
xindex
+
minadaptk
);
int
x3
=
(
int
)(
xindex
-
minadaptk
);
int
x4
=
(
int
)(
xindex
+
minadaptk
);
int
y1
=
(
int
)(
yindex
+
minadaptk
);
int
y2
=
(
int
)(
yindex
+
minadaptk
);
int
y3
=
(
int
)(
yindex
-
minadaptk
);
int
y4
=
(
int
)(
yindex
-
minadaptk
);
if
(
x1
<
0
)
x1
=
0
;
if
(
x2
>=
m_width
)
x2
=
m_width
-
1
;
if
(
x3
<
0
)
x3
=
0
;
if
(
x4
>=
m_width
)
x4
=
m_width
-
1
;
if
(
y1
>=
m_height
)
y1
=
m_height
-
1
;
if
(
y2
>=
m_height
)
y2
=
m_height
-
1
;
if
(
y3
<
0
)
y3
=
0
;
if
(
y4
<
0
)
y4
=
0
;
m_kseedsx
[
k
]
=
(
float
)
x1
;
m_kseedsy
[
k
]
=
(
float
)
y1
;
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
switch
(
m_chvec
[
c
].
depth
()
)
{
case
CV_8U
:
m_kseeds
[
c
][
k
]
=
m_chvec
[
c
].
at
<
uchar
>
(
y1
,
x1
);
break
;
case
CV_8S
:
m_kseeds
[
c
][
k
]
=
m_chvec
[
c
].
at
<
char
>
(
y1
,
x1
);
break
;
case
CV_16U
:
m_kseeds
[
c
][
k
]
=
m_chvec
[
c
].
at
<
ushort
>
(
y1
,
x1
);
break
;
case
CV_16S
:
m_kseeds
[
c
][
k
]
=
m_chvec
[
c
].
at
<
short
>
(
y1
,
x1
);
break
;
case
CV_32S
:
m_kseeds
[
c
][
k
]
=
float
(
m_chvec
[
c
].
at
<
int
>
(
y1
,
x1
));
break
;
case
CV_32F
:
m_kseeds
[
c
][
k
]
=
m_chvec
[
c
].
at
<
float
>
(
y1
,
x1
);
break
;
case
CV_64F
:
m_kseeds
[
c
][
k
]
=
float
(
m_chvec
[
c
].
at
<
double
>
(
y1
,
x1
));
break
;
default
:
CV_Error
(
Error
::
StsInternal
,
"Invalid matrix depth"
);
break
;
}
}
m_kseedsx
.
push_back
(
(
float
)
x2
);
m_kseedsx
.
push_back
(
(
float
)
x3
);
m_kseedsx
.
push_back
(
(
float
)
x4
);
m_kseedsy
.
push_back
(
(
float
)
y2
);
m_kseedsy
.
push_back
(
(
float
)
y3
);
m_kseedsy
.
push_back
(
(
float
)
y4
);
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
switch
(
m_chvec
[
c
].
depth
()
)
{
case
CV_8U
:
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
uchar
>
(
y2
,
x2
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
uchar
>
(
y3
,
x3
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
uchar
>
(
y4
,
x4
)
);
break
;
case
CV_8S
:
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
char
>
(
y2
,
x2
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
char
>
(
y3
,
x3
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
char
>
(
y4
,
x4
)
);
break
;
case
CV_16U
:
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
ushort
>
(
y2
,
x2
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
ushort
>
(
y3
,
x3
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
ushort
>
(
y4
,
x4
)
);
break
;
case
CV_16S
:
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
short
>
(
y2
,
x2
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
short
>
(
y3
,
x3
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
short
>
(
y4
,
x4
)
);
break
;
case
CV_32S
:
m_kseeds
[
c
].
push_back
(
float
(
m_chvec
[
c
].
at
<
int
>
(
y2
,
x2
))
);
m_kseeds
[
c
].
push_back
(
float
(
m_chvec
[
c
].
at
<
int
>
(
y3
,
x3
))
);
m_kseeds
[
c
].
push_back
(
float
(
m_chvec
[
c
].
at
<
int
>
(
y4
,
x4
))
);
break
;
case
CV_32F
:
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
float
>
(
y2
,
x2
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
float
>
(
y3
,
x3
)
);
m_kseeds
[
c
].
push_back
(
m_chvec
[
c
].
at
<
float
>
(
y4
,
x4
)
);
break
;
case
CV_64F
:
m_kseeds
[
c
].
push_back
(
float
(
m_chvec
[
c
].
at
<
double
>
(
y2
,
x2
))
);
m_kseeds
[
c
].
push_back
(
float
(
m_chvec
[
c
].
at
<
double
>
(
y3
,
x3
))
);
m_kseeds
[
c
].
push_back
(
float
(
m_chvec
[
c
].
at
<
double
>
(
y4
,
x4
))
);
break
;
default
:
CV_Error
(
Error
::
StsInternal
,
"Invalid matrix depth"
);
break
;
}
}
m_adaptk
.
push_back
(
m_adaptk
[
k
]
);
m_adaptk
.
push_back
(
m_adaptk
[
k
]
);
m_adaptk
.
push_back
(
m_adaptk
[
k
]
);
msc
.
clustersize
.
push_back
(
1
);
msc
.
clustersize
.
push_back
(
1
);
msc
.
clustersize
.
push_back
(
1
);
}
}
}
else
{
m_kseedsx
.
clear
();
m_kseedsy
.
clear
();
m_kseedsx
.
resize
(
m_numlabels
,
0
);
m_kseedsy
.
resize
(
m_numlabels
,
0
);
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
{
m_kseeds
[
c
].
clear
();
m_kseeds
[
c
].
resize
(
m_numlabels
,
0
);
}
for
(
int
k
=
0
;
k
<
m_numlabels
;
k
++
)
{
m_kseedsx
[
k
]
=
msc
.
sigmax
[
k
]
/
msc
.
clustersize
[
k
];
m_kseedsy
[
k
]
=
msc
.
sigmay
[
k
]
/
msc
.
clustersize
[
k
];
for
(
int
c
=
0
;
c
<
m_nr_channels
;
c
++
)
m_kseeds
[
c
][
k
]
=
msc
.
sigma
[
c
][
k
]
/
msc
.
clustersize
[
k
];
}
}
m_klabels
.
release
();
m_klabels
=
klabels
.
clone
();
// re-update amount of labels
m_numlabels
=
(
int
)
m_kseeds
[
0
].
size
();
}
}
// namespace ximgproc
}
// namespace cv
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