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:
...
@@ -102,11 +102,31 @@ public:
The algorithm underlies this function is much more robust to texture presence, than common
The algorithm underlies this function is much more robust to texture presence, than common
approaches, e.g. Sobel
approaches, e.g. Sobel
@param src source image (RGB, float, in [0;1]) to detect edges
@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
_
dst destination image (grayscale, float, in [0;1]) where edges are drawn
@sa Sobel, Canny
@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 )
...
@@ -59,10 +59,20 @@ int main( int argc, const char** argv )
createStructuredEdgeDetection
(
modelFilename
);
createStructuredEdgeDetection
(
modelFilename
);
pDollar
->
detectEdges
(
image
,
edges
);
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
)
if
(
outFilename
.
size
()
==
0
)
{
{
namedWindow
(
"edges"
,
1
);
namedWindow
(
"edges"
,
1
);
imshow
(
"edges"
,
edges
);
imshow
(
"edges"
,
edges
);
namedWindow
(
"edges nms"
,
1
);
imshow
(
"edges nms"
,
edge_nms
);
waitKey
(
0
);
waitKey
(
0
);
}
}
else
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
...
@@ -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 *********************/
/********************* RFFeatureGetter class *********************/
namespace
cv
namespace
cv
...
@@ -445,21 +520,23 @@ public:
...
@@ -445,21 +520,23 @@ public:
/*!
/*!
* The function detects edges in src and draw them to dst
* The function detects edges in src and draw them to dst
*
*
* \param src : source image (RGB, float, in [0;1]) to detect edges
* \param
_
src : source image (RGB, float, in [0;1]) to detect edges
* \param dst : destination image (grayscale, float, in [0;1])
* \param
_
dst : destination image (grayscale, float, in [0;1])
* where edges are drawn
* 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
int
padding
=
(
__rf
.
options
.
patchSize
-
__rf
.
options
.
patchInnerSize
)
/
2
;
-
__rf
.
options
.
patchInnerSize
)
/
2
;
cv
::
Mat
nSrc
;
cv
::
Mat
nSrc
;
copyMakeBorder
(
src
,
nSrc
,
padding
,
padding
,
copyMakeBorder
(
_
src
,
nSrc
,
padding
,
padding
,
padding
,
padding
,
BORDER_REFLECT
);
padding
,
padding
,
BORDER_REFLECT
);
NChannelsMat
features
;
NChannelsMat
features
;
...
@@ -472,6 +549,101 @@ public:
...
@@ -472,6 +549,101 @@ public:
predictEdges
(
features
,
dst
);
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
:
protected
:
/*!
/*!
* Private method used by process method. The function
* 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