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
9b5aa2a5
Commit
9b5aa2a5
authored
May 17, 2017
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1147 from lhelontra:edgenms
parents
74e439f4
da280ac5
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
211 additions
and
9 deletions
+211
-9
structured_edge_detection.hpp
...oc/include/opencv2/ximgproc/structured_edge_detection.hpp
+23
-3
structured_edge_detection.cpp
modules/ximgproc/samples/structured_edge_detection.cpp
+10
-0
structured_edge_detection.cpp
modules/ximgproc/src/structured_edge_detection.cpp
+178
-6
No files found.
modules/ximgproc/include/opencv2/ximgproc/structured_edge_detection.hpp
View file @
9b5aa2a5
...
...
@@ -102,11 +102,31 @@ public:
The algorithm underlies this function is much more robust to texture presence, than common
approaches, e.g. Sobel
@param src source image (RGB, float, in [0;1]) to detect edges
@param dst destination image (grayscale, float, in [0;1]) where edges are drawn
@param
_
src source image (RGB, float, in [0;1]) to detect edges
@param
_
dst destination image (grayscale, float, in [0;1]) where edges are drawn
@sa Sobel, Canny
*/
CV_WRAP
virtual
void
detectEdges
(
const
Mat
&
src
,
CV_OUT
Mat
&
dst
)
const
=
0
;
CV_WRAP
virtual
void
detectEdges
(
cv
::
InputArray
_src
,
cv
::
OutputArray
_dst
)
const
=
0
;
/** @brief The function computes orientation from edge image.
@param _src edge image.
@param _dst orientation image.
*/
CV_WRAP
virtual
void
computeOrientation
(
cv
::
InputArray
_src
,
cv
::
OutputArray
_dst
)
const
=
0
;
/** @brief The function edgenms in edge image and suppress edges where edge is stronger in orthogonal direction.
@param edge_image edge image from detectEdges function.
@param orientation_image orientation image from computeOrientation function.
@param _dst suppressed image (grayscale, float, in [0;1])
@param r radius for NMS suppression.
@param s radius for boundary suppression.
@param m multiplier for conservative suppression.
@param isParallel enables/disables parallel computing.
*/
CV_WRAP
virtual
void
edgesNms
(
cv
::
InputArray
edge_image
,
cv
::
InputArray
orientation_image
,
cv
::
OutputArray
_dst
,
int
r
=
2
,
int
s
=
0
,
float
m
=
1
,
bool
isParallel
=
true
)
const
=
0
;
};
/*!
...
...
modules/ximgproc/samples/structured_edge_detection.cpp
View file @
9b5aa2a5
...
...
@@ -59,10 +59,20 @@ int main( int argc, const char** argv )
createStructuredEdgeDetection
(
modelFilename
);
pDollar
->
detectEdges
(
image
,
edges
);
// computes orientation from edge map
Mat
orientation_map
;
pDollar
->
computeOrientation
(
edges
,
orientation_map
);
// suppress edges
Mat
edge_nms
;
pDollar
->
edgesNms
(
edges
,
orientation_map
,
edge_nms
,
2
,
0
,
1
,
true
);
if
(
outFilename
.
size
()
==
0
)
{
namedWindow
(
"edges"
,
1
);
imshow
(
"edges"
,
edges
);
namedWindow
(
"edges nms"
,
1
);
imshow
(
"edges nms"
,
edge_nms
);
waitKey
(
0
);
}
else
...
...
modules/ximgproc/src/structured_edge_detection.cpp
View file @
9b5aa2a5
...
...
@@ -255,6 +255,81 @@ static void gradientHist(const cv::Mat &src, cv::Mat &magnitude, cv::Mat &histog
}
}
/*!
* The class parallelizing the edgenms algorithm.
*
* \param E : edge image
* \param O : orientation image
* \param dst : destination image
* \param r : radius for NMS suppression
* \param s : radius for boundary suppression
* \param m : multiplier for conservative suppression
*/
class
NmsInvoker
:
public
cv
::
ParallelLoopBody
{
private
:
const
cv
::
Mat
&
E
;
const
cv
::
Mat
&
O
;
cv
::
Mat
&
dst
;
const
int
r
;
const
float
m
;
public
:
NmsInvoker
(
const
cv
::
Mat
&
_E
,
const
cv
::
Mat
&
_O
,
cv
::
Mat
&
_dst
,
const
int
_r
,
const
float
_m
)
:
E
(
_E
),
O
(
_O
),
dst
(
_dst
),
r
(
_r
),
m
(
_m
)
{
}
void
operator
()(
const
cv
::
Range
&
range
)
const
{
for
(
int
x
=
range
.
start
;
x
<
range
.
end
;
x
++
)
{
const
float
*
e_ptr
=
E
.
ptr
<
float
>
(
x
);
const
float
*
o_ptr
=
O
.
ptr
<
float
>
(
x
);
float
*
dst_ptr
=
dst
.
ptr
<
float
>
(
x
);
for
(
int
y
=
0
;
y
<
E
.
cols
;
y
++
)
{
float
e
=
e_ptr
[
y
];
dst_ptr
[
y
]
=
e
;
if
(
!
e
)
continue
;
e
*=
m
;
float
coso
=
cos
(
o_ptr
[
y
]);
float
sino
=
sin
(
o_ptr
[
y
]);
for
(
int
d
=-
r
;
d
<=
r
;
d
++
)
{
if
(
d
)
{
float
xdcos
=
x
+
d
*
coso
;
float
ydsin
=
y
+
d
*
sino
;
xdcos
=
xdcos
<
0
?
0
:
(
xdcos
>
E
.
rows
-
1.001
f
?
E
.
rows
-
1.001
f
:
xdcos
);
ydsin
=
ydsin
<
0
?
0
:
(
ydsin
>
E
.
cols
-
1.001
f
?
E
.
cols
-
1.001
f
:
ydsin
);
int
x0
=
(
int
)
xdcos
;
int
y0
=
(
int
)
ydsin
;
int
x1
=
x0
+
1
;
int
y1
=
y0
+
1
;
float
dx0
=
xdcos
-
x0
;
float
dy0
=
ydsin
-
y0
;
float
dx1
=
1
-
dx0
;
float
dy1
=
1
-
dy0
;
float
e0
=
E
.
at
<
float
>
(
x0
,
y0
)
*
dx1
*
dy1
+
E
.
at
<
float
>
(
x1
,
y0
)
*
dx0
*
dy1
+
E
.
at
<
float
>
(
x0
,
y1
)
*
dx1
*
dy0
+
E
.
at
<
float
>
(
x1
,
y1
)
*
dx0
*
dy0
;
if
(
e
<
e0
)
{
dst_ptr
[
y
]
=
0
;
break
;
}
}
}
}
}
}
};
/********************* RFFeatureGetter class *********************/
namespace
cv
...
...
@@ -445,21 +520,23 @@ public:
/*!
* The function detects edges in src and draw them to dst
*
* \param src : source image (RGB, float, in [0;1]) to detect edges
* \param dst : destination image (grayscale, float, in [0;1])
* \param
_
src : source image (RGB, float, in [0;1]) to detect edges
* \param
_
dst : destination image (grayscale, float, in [0;1])
* where edges are drawn
*/
void
detectEdges
(
c
onst
cv
::
Mat
&
src
,
cv
::
Mat
&
dst
)
const
void
detectEdges
(
c
v
::
InputArray
_src
,
cv
::
OutputArray
_
dst
)
const
{
CV_Assert
(
src
.
type
()
==
CV_32FC3
);
CV_Assert
(
_
src
.
type
()
==
CV_32FC3
);
dst
.
create
(
src
.
size
(),
cv
::
DataType
<
float
>::
type
);
_dst
.
createSameSize
(
_src
,
cv
::
DataType
<
float
>::
type
);
_dst
.
setTo
(
0
);
Mat
dst
=
_dst
.
getMat
();
int
padding
=
(
__rf
.
options
.
patchSize
-
__rf
.
options
.
patchInnerSize
)
/
2
;
cv
::
Mat
nSrc
;
copyMakeBorder
(
src
,
nSrc
,
padding
,
padding
,
copyMakeBorder
(
_
src
,
nSrc
,
padding
,
padding
,
padding
,
padding
,
BORDER_REFLECT
);
NChannelsMat
features
;
...
...
@@ -472,6 +549,101 @@ public:
predictEdges
(
features
,
dst
);
}
/*!
* The function computes orientation from edge image.
*
* \param src : edge image.
* \param dst : orientation image.
* \param r : filter radius.
*/
void
computeOrientation
(
cv
::
InputArray
_src
,
cv
::
OutputArray
_dst
)
const
{
CV_Assert
(
_src
.
type
()
==
CV_32FC1
);
cv
::
Mat
Oxx
,
Oxy
,
Oyy
;
_dst
.
createSameSize
(
_src
,
_src
.
type
()
);
_dst
.
setTo
(
0
);
Mat
src
=
_src
.
getMat
();
cv
::
Mat
E_conv
=
imsmooth
(
src
,
__rf
.
options
.
gradientNormalizationRadius
);
Sobel
(
E_conv
,
Oxx
,
-
1
,
2
,
0
);
Sobel
(
E_conv
,
Oxy
,
-
1
,
1
,
1
);
Sobel
(
E_conv
,
Oyy
,
-
1
,
0
,
2
);
Mat
dst
=
_dst
.
getMat
();
float
*
o
=
dst
.
ptr
<
float
>
();
float
*
oxx
=
Oxx
.
ptr
<
float
>
();
float
*
oxy
=
Oxy
.
ptr
<
float
>
();
float
*
oyy
=
Oyy
.
ptr
<
float
>
();
for
(
int
i
=
0
;
i
<
dst
.
rows
*
dst
.
cols
;
i
++
)
{
int
xysign
=
-
((
oxy
[
i
]
>
0
)
-
(
oxy
[
i
]
<
0
));
o
[
i
]
=
(
atan
((
oyy
[
i
]
*
xysign
/
(
oxx
[
i
]
+
1e-5
)))
>
0
)
?
(
float
)
fmod
(
atan
((
oyy
[
i
]
*
xysign
/
(
oxx
[
i
]
+
1e-5
))),
M_PI
)
:
(
float
)
fmod
(
atan
((
oyy
[
i
]
*
xysign
/
(
oxx
[
i
]
+
1e-5
)))
+
M_PI
,
M_PI
);
}
}
/*!
* The function suppress edges where edge is stronger in orthogonal direction
* \param edge_image : edge image from detectEdges function.
* \param orientation_image : orientation image from computeOrientation function.
* \param _dst : suppressed image (grayscale, float, in [0;1])
* \param r : radius for NMS suppression.
* \param s : radius for boundary suppression.
* \param m : multiplier for conservative suppression.
* \param isParallel: enables/disables parallel computing.
*/
void
edgesNms
(
cv
::
InputArray
edge_image
,
cv
::
InputArray
orientation_image
,
cv
::
OutputArray
_dst
,
int
r
,
int
s
,
float
m
,
bool
isParallel
)
const
{
CV_Assert
(
edge_image
.
type
()
==
CV_32FC1
);
CV_Assert
(
orientation_image
.
type
()
==
CV_32FC1
);
cv
::
Mat
E
=
edge_image
.
getMat
();
cv
::
Mat
O
=
orientation_image
.
getMat
();
cv
::
Mat
E_t
=
E
.
t
();
cv
::
Mat
O_t
=
O
.
t
();
cv
::
Mat
dst
=
_dst
.
getMat
();
dst
.
create
(
E
.
cols
,
E
.
rows
,
E
.
type
());
dst
.
setTo
(
0
);
cv
::
Range
sizeRange
=
cv
::
Range
(
0
,
E_t
.
rows
);
NmsInvoker
body
=
NmsInvoker
(
E_t
,
O_t
,
dst
,
r
,
m
);
if
(
isParallel
)
{
cv
::
parallel_for_
(
sizeRange
,
body
);
}
else
{
body
(
sizeRange
);
}
s
=
s
>
E_t
.
rows
/
2
?
E_t
.
rows
/
2
:
s
;
s
=
s
>
E_t
.
cols
/
2
?
E_t
.
cols
/
2
:
s
;
for
(
int
x
=
0
;
x
<
s
;
x
++
)
{
for
(
int
y
=
0
;
y
<
E_t
.
cols
;
y
++
)
{
dst
.
at
<
float
>
(
x
,
y
)
*=
x
/
(
float
)
s
;
dst
.
at
<
float
>
(
E_t
.
rows
-
1
-
x
,
y
)
*=
x
/
(
float
)
s
;
}
}
for
(
int
x
=
0
;
x
<
E_t
.
rows
;
x
++
)
{
for
(
int
y
=
0
;
y
<
s
;
y
++
)
{
dst
.
at
<
float
>
(
x
,
y
)
*=
y
/
(
float
)
s
;
dst
.
at
<
float
>
(
x
,
E_t
.
cols
-
1
-
y
)
*=
y
/
(
float
)
s
;
}
}
transpose
(
dst
,
dst
);
dst
.
copyTo
(
_dst
);
}
protected
:
/*!
* Private method used by process method. The function
...
...
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