Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
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
Commits
a455858d
Commit
a455858d
authored
Jul 20, 2016
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6878 from alalek:canny_custom_gradient
parents
848c66ba
e20a93f7
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
190 additions
and
49 deletions
+190
-49
imgproc.hpp
modules/imgproc/include/opencv2/imgproc.hpp
+13
-0
canny.cpp
modules/imgproc/src/canny.cpp
+121
-37
test_canny.cpp
modules/imgproc/test/ocl/test_canny.cpp
+30
-7
test_canny.cpp
modules/imgproc/test/test_canny.cpp
+24
-3
ocl_test.hpp
modules/ts/include/opencv2/ts/ocl_test.hpp
+2
-2
No files found.
modules/imgproc/include/opencv2/imgproc.hpp
View file @
a455858d
...
@@ -1664,6 +1664,19 @@ CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
...
@@ -1664,6 +1664,19 @@ CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
double
threshold1
,
double
threshold2
,
double
threshold1
,
double
threshold2
,
int
apertureSize
=
3
,
bool
L2gradient
=
false
);
int
apertureSize
=
3
,
bool
L2gradient
=
false
);
/** \overload
Finds edges in an image using the Canny algorithm with custom image gradient.
@param dx 16-bit x derivative of input image (CV_16SC1 or CV_16SC3).
@param dy 16-bit y derivative of input image (same type as dx).
@param edges,threshold1,threshold2,L2gradient See cv::Canny
*/
CV_EXPORTS_W
void
Canny
(
InputArray
dx
,
InputArray
dy
,
OutputArray
edges
,
double
threshold1
,
double
threshold2
,
bool
L2gradient
=
false
);
/** @brief Calculates the minimal eigenvalue of gradient matrices for corner detection.
/** @brief Calculates the minimal eigenvalue of gradient matrices for corner detection.
The function is similar to cornerEigenValsAndVecs but it calculates and stores only the minimal
The function is similar to cornerEigenValsAndVecs but it calculates and stores only the minimal
...
...
modules/imgproc/src/canny.cpp
View file @
a455858d
...
@@ -43,6 +43,10 @@
...
@@ -43,6 +43,10 @@
#include "precomp.hpp"
#include "precomp.hpp"
#include "opencl_kernels_imgproc.hpp"
#include "opencl_kernels_imgproc.hpp"
#ifdef _MSC_VER
#pragma warning( disable: 4127 ) // conditional expression is constant
#endif
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
#define USE_IPP_CANNY 1
#define USE_IPP_CANNY 1
...
@@ -53,34 +57,45 @@
...
@@ -53,34 +57,45 @@
namespace
cv
namespace
cv
{
{
static
void
CannyImpl
(
Mat
&
dx_
,
Mat
&
dy_
,
Mat
&
_dst
,
double
low_thresh
,
double
high_thresh
,
bool
L2gradient
);
#ifdef HAVE_IPP
#ifdef HAVE_IPP
static
bool
ippCanny
(
const
Mat
&
_src
,
Mat
&
_dst
,
float
low
,
float
high
)
template
<
bool
useCustomDeriv
>
static
bool
ippCanny
(
const
Mat
&
_src
,
const
Mat
&
dx_
,
const
Mat
&
dy_
,
Mat
&
_dst
,
float
low
,
float
high
)
{
{
#if USE_IPP_CANNY
#if USE_IPP_CANNY
int
size
=
0
,
size1
=
0
;
int
size
=
0
,
size1
=
0
;
IppiSize
roi
=
{
_src
.
cols
,
_src
.
rows
};
IppiSize
roi
=
{
_src
.
cols
,
_src
.
rows
};
if
(
ippiCannyGetSize
(
roi
,
&
size
)
<
0
)
return
false
;
if
(
!
useCustomDeriv
)
{
#if IPP_VERSION_X100 < 900
#if IPP_VERSION_X100 < 900
if
(
ippiFilterSobelNegVertGetBufferSize_8u16s_C1R
(
roi
,
ippMskSize3x3
,
&
size
)
<
0
)
if
(
ippiFilterSobelNegVertGetBufferSize_8u16s_C1R
(
roi
,
ippMskSize3x3
,
&
size1
)
<
0
)
return
false
;
return
false
;
size
=
std
::
max
(
size
,
size1
);
if
(
ippiFilterSobelHorizGetBufferSize_8u16s_C1R
(
roi
,
ippMskSize3x3
,
&
size1
)
<
0
)
if
(
ippiFilterSobelHorizGetBufferSize_8u16s_C1R
(
roi
,
ippMskSize3x3
,
&
size1
)
<
0
)
return
false
;
return
false
;
#else
#else
if
(
ippiFilterSobelNegVertBorderGetBufferSize
(
roi
,
ippMskSize3x3
,
ipp8u
,
ipp16s
,
1
,
&
size
)
<
0
)
if
(
ippiFilterSobelNegVertBorderGetBufferSize
(
roi
,
ippMskSize3x3
,
ipp8u
,
ipp16s
,
1
,
&
size1
)
<
0
)
return
false
;
return
false
;
size
=
std
::
max
(
size
,
size1
);
if
(
ippiFilterSobelHorizBorderGetBufferSize
(
roi
,
ippMskSize3x3
,
ipp8u
,
ipp16s
,
1
,
&
size1
)
<
0
)
if
(
ippiFilterSobelHorizBorderGetBufferSize
(
roi
,
ippMskSize3x3
,
ipp8u
,
ipp16s
,
1
,
&
size1
)
<
0
)
return
false
;
return
false
;
#endif
#endif
size
=
std
::
max
(
size
,
size1
);
if
(
ippiCannyGetSize
(
roi
,
&
size1
)
<
0
)
return
false
;
size
=
std
::
max
(
size
,
size1
);
size
=
std
::
max
(
size
,
size1
);
}
AutoBuffer
<
uchar
>
buf
(
size
+
64
);
AutoBuffer
<
uchar
>
buf
(
size
+
64
);
uchar
*
buffer
=
alignPtr
((
uchar
*
)
buf
,
32
);
uchar
*
buffer
=
alignPtr
((
uchar
*
)
buf
,
32
);
Mat
dx
,
dy
;
if
(
!
useCustomDeriv
)
{
Mat
_dx
(
_src
.
rows
,
_src
.
cols
,
CV_16S
);
Mat
_dx
(
_src
.
rows
,
_src
.
cols
,
CV_16S
);
if
(
ippiFilterSobelNegVertBorder_8u16s_C1R
(
_src
.
ptr
(),
(
int
)
_src
.
step
,
if
(
ippiFilterSobelNegVertBorder_8u16s_C1R
(
_src
.
ptr
(),
(
int
)
_src
.
step
,
_dx
.
ptr
<
short
>
(),
(
int
)
_dx
.
step
,
roi
,
_dx
.
ptr
<
short
>
(),
(
int
)
_dx
.
step
,
roi
,
...
@@ -93,13 +108,22 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
...
@@ -93,13 +108,22 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
ippMskSize3x3
,
ippBorderRepl
,
0
,
buffer
)
<
0
)
ippMskSize3x3
,
ippBorderRepl
,
0
,
buffer
)
<
0
)
return
false
;
return
false
;
if
(
ippiCanny_16s8u_C1R
(
_dx
.
ptr
<
short
>
(),
(
int
)
_dx
.
step
,
swap
(
dx
,
_dx
);
_dy
.
ptr
<
short
>
(),
(
int
)
_dy
.
step
,
swap
(
dy
,
_dy
);
}
else
{
dx
=
dx_
;
dy
=
dy_
;
}
if
(
ippiCanny_16s8u_C1R
(
dx
.
ptr
<
short
>
(),
(
int
)
dx
.
step
,
dy
.
ptr
<
short
>
(),
(
int
)
dy
.
step
,
_dst
.
ptr
(),
(
int
)
_dst
.
step
,
roi
,
low
,
high
,
buffer
)
<
0
)
_dst
.
ptr
(),
(
int
)
_dst
.
step
,
roi
,
low
,
high
,
buffer
)
<
0
)
return
false
;
return
false
;
return
true
;
return
true
;
#else
#else
CV_UNUSED
(
_src
);
CV_UNUSED
(
_dst
);
CV_UNUSED
(
low
);
CV_UNUSED
(
high
);
CV_UNUSED
(
_src
);
CV_UNUSED
(
dx_
);
CV_UNUSED
(
dy_
);
CV_UNUSED
(
_dst
);
CV_UNUSED
(
low
);
CV_UNUSED
(
high
);
return
false
;
return
false
;
#endif
#endif
}
}
...
@@ -107,7 +131,8 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
...
@@ -107,7 +131,8 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high)
#ifdef HAVE_OPENCL
#ifdef HAVE_OPENCL
static
bool
ocl_Canny
(
InputArray
_src
,
OutputArray
_dst
,
float
low_thresh
,
float
high_thresh
,
template
<
bool
useCustomDeriv
>
static
bool
ocl_Canny
(
InputArray
_src
,
const
UMat
&
dx_
,
const
UMat
&
dy_
,
OutputArray
_dst
,
float
low_thresh
,
float
high_thresh
,
int
aperture_size
,
bool
L2gradient
,
int
cn
,
const
Size
&
size
)
int
aperture_size
,
bool
L2gradient
,
int
cn
,
const
Size
&
size
)
{
{
UMat
map
;
UMat
map
;
...
@@ -140,7 +165,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float
...
@@ -140,7 +165,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float
}
}
int
low
=
cvFloor
(
low_thresh
),
high
=
cvFloor
(
high_thresh
);
int
low
=
cvFloor
(
low_thresh
),
high
=
cvFloor
(
high_thresh
);
if
(
aperture_size
==
3
&&
!
_src
.
isSubmatrix
())
if
(
!
useCustomDeriv
&&
aperture_size
==
3
&&
!
_src
.
isSubmatrix
())
{
{
/*
/*
stage1_with_sobel:
stage1_with_sobel:
...
@@ -181,8 +207,16 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float
...
@@ -181,8 +207,16 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float
Double thresholding
Double thresholding
*/
*/
UMat
dx
,
dy
;
UMat
dx
,
dy
;
if
(
!
useCustomDeriv
)
{
Sobel
(
_src
,
dx
,
CV_16S
,
1
,
0
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
Sobel
(
_src
,
dx
,
CV_16S
,
1
,
0
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
Sobel
(
_src
,
dy
,
CV_16S
,
0
,
1
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
Sobel
(
_src
,
dy
,
CV_16S
,
0
,
1
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
}
else
{
dx
=
dx_
;
dy
=
dy_
;
}
ocl
::
Kernel
without_sobel
(
"stage1_without_sobel"
,
ocl
::
imgproc
::
canny_oclsrc
,
ocl
::
Kernel
without_sobel
(
"stage1_without_sobel"
,
ocl
::
imgproc
::
canny_oclsrc
,
format
(
"-D WITHOUT_SOBEL -D cn=%d -D GRP_SIZEX=%d -D GRP_SIZEY=%d%s"
,
format
(
"-D WITHOUT_SOBEL -D cn=%d -D GRP_SIZEX=%d -D GRP_SIZEY=%d%s"
,
...
@@ -585,9 +619,7 @@ private:
...
@@ -585,9 +619,7 @@ private:
#endif
#endif
}
// namespace cv
void
Canny
(
InputArray
_src
,
OutputArray
_dst
,
void
cv
::
Canny
(
InputArray
_src
,
OutputArray
_dst
,
double
low_thresh
,
double
high_thresh
,
double
low_thresh
,
double
high_thresh
,
int
aperture_size
,
bool
L2gradient
)
int
aperture_size
,
bool
L2gradient
)
{
{
...
@@ -611,7 +643,7 @@ void cv::Canny( InputArray _src, OutputArray _dst,
...
@@ -611,7 +643,7 @@ void cv::Canny( InputArray _src, OutputArray _dst,
std
::
swap
(
low_thresh
,
high_thresh
);
std
::
swap
(
low_thresh
,
high_thresh
);
CV_OCL_RUN
(
_dst
.
isUMat
()
&&
(
cn
==
1
||
cn
==
3
),
CV_OCL_RUN
(
_dst
.
isUMat
()
&&
(
cn
==
1
||
cn
==
3
),
ocl_Canny
(
_src
,
_dst
,
(
float
)
low_thresh
,
(
float
)
high_thresh
,
aperture_size
,
L2gradient
,
cn
,
size
))
ocl_Canny
<
false
>
(
_src
,
UMat
(),
UMat
()
,
_dst
,
(
float
)
low_thresh
,
(
float
)
high_thresh
,
aperture_size
,
L2gradient
,
cn
,
size
))
Mat
src
=
_src
.
getMat
(),
dst
=
_dst
.
getMat
();
Mat
src
=
_src
.
getMat
(),
dst
=
_dst
.
getMat
();
...
@@ -620,7 +652,7 @@ void cv::Canny( InputArray _src, OutputArray _dst,
...
@@ -620,7 +652,7 @@ void cv::Canny( InputArray _src, OutputArray _dst,
return
;
return
;
#endif
#endif
CV_IPP_RUN
(
USE_IPP_CANNY
&&
(
aperture_size
==
3
&&
!
L2gradient
&&
1
==
cn
),
ippCanny
(
src
,
dst
,
(
float
)
low_thresh
,
(
float
)
high_thresh
))
CV_IPP_RUN
(
USE_IPP_CANNY
&&
(
aperture_size
==
3
&&
!
L2gradient
&&
1
==
cn
),
ippCanny
<
false
>
(
src
,
Mat
(),
Mat
()
,
dst
,
(
float
)
low_thresh
,
(
float
)
high_thresh
))
#ifdef HAVE_TBB
#ifdef HAVE_TBB
...
@@ -683,14 +715,66 @@ while (borderPeaks.try_pop(m))
...
@@ -683,14 +715,66 @@ while (borderPeaks.try_pop(m))
if
(
!
m
[
mapstep
+
1
])
CANNY_PUSH_SERIAL
(
m
+
mapstep
+
1
);
if
(
!
m
[
mapstep
+
1
])
CANNY_PUSH_SERIAL
(
m
+
mapstep
+
1
);
}
}
#else
// the final pass, form the final image
const
uchar
*
pmap
=
map
+
mapstep
+
1
;
uchar
*
pdst
=
dst
.
ptr
();
for
(
int
i
=
0
;
i
<
src
.
rows
;
i
++
,
pmap
+=
mapstep
,
pdst
+=
dst
.
step
)
{
for
(
int
j
=
0
;
j
<
src
.
cols
;
j
++
)
pdst
[
j
]
=
(
uchar
)
-
(
pmap
[
j
]
>>
1
);
}
#else
Mat
dx
(
src
.
rows
,
src
.
cols
,
CV_16SC
(
cn
));
Mat
dx
(
src
.
rows
,
src
.
cols
,
CV_16SC
(
cn
));
Mat
dy
(
src
.
rows
,
src
.
cols
,
CV_16SC
(
cn
));
Mat
dy
(
src
.
rows
,
src
.
cols
,
CV_16SC
(
cn
));
Sobel
(
src
,
dx
,
CV_16S
,
1
,
0
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
Sobel
(
src
,
dx
,
CV_16S
,
1
,
0
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
Sobel
(
src
,
dy
,
CV_16S
,
0
,
1
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
Sobel
(
src
,
dy
,
CV_16S
,
0
,
1
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
CannyImpl
(
dx
,
dy
,
dst
,
low_thresh
,
high_thresh
,
L2gradient
);
#endif
}
void
Canny
(
InputArray
_dx
,
InputArray
_dy
,
OutputArray
_dst
,
double
low_thresh
,
double
high_thresh
,
bool
L2gradient
)
{
CV_Assert
(
_dx
.
dims
()
==
2
);
CV_Assert
(
_dx
.
type
()
==
CV_16SC1
||
_dx
.
type
()
==
CV_16SC3
);
CV_Assert
(
_dy
.
type
()
==
_dx
.
type
());
CV_Assert
(
_dx
.
sameSize
(
_dy
));
if
(
low_thresh
>
high_thresh
)
std
::
swap
(
low_thresh
,
high_thresh
);
const
int
cn
=
_dx
.
channels
();
const
Size
size
=
_dx
.
size
();
CV_OCL_RUN
(
_dst
.
isUMat
(),
ocl_Canny
<
true
>
(
UMat
(),
_dx
.
getUMat
(),
_dy
.
getUMat
(),
_dst
,
(
float
)
low_thresh
,
(
float
)
high_thresh
,
0
,
L2gradient
,
cn
,
size
))
_dst
.
create
(
size
,
CV_8U
);
Mat
dst
=
_dst
.
getMat
();
Mat
dx
=
_dx
.
getMat
();
Mat
dy
=
_dy
.
getMat
();
CV_IPP_RUN
(
USE_IPP_CANNY
&&
(
!
L2gradient
&&
1
==
cn
),
ippCanny
<
true
>
(
Mat
(),
dx
,
dy
,
dst
,
(
float
)
low_thresh
,
(
float
)
high_thresh
))
if
(
cn
>
1
)
{
dx
=
dx
.
clone
();
dy
=
dy
.
clone
();
}
CannyImpl
(
dx
,
dy
,
dst
,
low_thresh
,
high_thresh
,
L2gradient
);
}
static
void
CannyImpl
(
Mat
&
dx
,
Mat
&
dy
,
Mat
&
dst
,
double
low_thresh
,
double
high_thresh
,
bool
L2gradient
)
{
const
int
cn
=
dx
.
channels
();
const
int
cols
=
dx
.
cols
,
rows
=
dx
.
rows
;
if
(
L2gradient
)
if
(
L2gradient
)
{
{
low_thresh
=
std
::
min
(
32767.0
,
low_thresh
);
low_thresh
=
std
::
min
(
32767.0
,
low_thresh
);
...
@@ -702,8 +786,8 @@ while (borderPeaks.try_pop(m))
...
@@ -702,8 +786,8 @@ while (borderPeaks.try_pop(m))
int
low
=
cvFloor
(
low_thresh
);
int
low
=
cvFloor
(
low_thresh
);
int
high
=
cvFloor
(
high_thresh
);
int
high
=
cvFloor
(
high_thresh
);
ptrdiff_t
mapstep
=
src
.
cols
+
2
;
ptrdiff_t
mapstep
=
cols
+
2
;
AutoBuffer
<
uchar
>
buffer
((
src
.
cols
+
2
)
*
(
src
.
rows
+
2
)
+
cn
*
mapstep
*
3
*
sizeof
(
int
));
AutoBuffer
<
uchar
>
buffer
((
cols
+
2
)
*
(
rows
+
2
)
+
cn
*
mapstep
*
3
*
sizeof
(
int
));
int
*
mag_buf
[
3
];
int
*
mag_buf
[
3
];
mag_buf
[
0
]
=
(
int
*
)(
uchar
*
)
buffer
;
mag_buf
[
0
]
=
(
int
*
)(
uchar
*
)
buffer
;
...
@@ -713,9 +797,9 @@ while (borderPeaks.try_pop(m))
...
@@ -713,9 +797,9 @@ while (borderPeaks.try_pop(m))
uchar
*
map
=
(
uchar
*
)(
mag_buf
[
2
]
+
mapstep
*
cn
);
uchar
*
map
=
(
uchar
*
)(
mag_buf
[
2
]
+
mapstep
*
cn
);
memset
(
map
,
1
,
mapstep
);
memset
(
map
,
1
,
mapstep
);
memset
(
map
+
mapstep
*
(
src
.
rows
+
1
),
1
,
mapstep
);
memset
(
map
+
mapstep
*
(
rows
+
1
),
1
,
mapstep
);
int
maxsize
=
std
::
max
(
1
<<
10
,
src
.
cols
*
src
.
rows
/
10
);
int
maxsize
=
std
::
max
(
1
<<
10
,
cols
*
rows
/
10
);
std
::
vector
<
uchar
*>
stack
(
maxsize
);
std
::
vector
<
uchar
*>
stack
(
maxsize
);
uchar
**
stack_top
=
&
stack
[
0
];
uchar
**
stack_top
=
&
stack
[
0
];
uchar
**
stack_bottom
=
&
stack
[
0
];
uchar
**
stack_bottom
=
&
stack
[
0
];
...
@@ -744,17 +828,17 @@ while (borderPeaks.try_pop(m))
...
@@ -744,17 +828,17 @@ while (borderPeaks.try_pop(m))
// 0 - the pixel might belong to an edge
// 0 - the pixel might belong to an edge
// 1 - the pixel can not belong to an edge
// 1 - the pixel can not belong to an edge
// 2 - the pixel does belong to an edge
// 2 - the pixel does belong to an edge
for
(
int
i
=
0
;
i
<=
src
.
rows
;
i
++
)
for
(
int
i
=
0
;
i
<=
rows
;
i
++
)
{
{
int
*
_norm
=
mag_buf
[(
i
>
0
)
+
1
]
+
1
;
int
*
_norm
=
mag_buf
[(
i
>
0
)
+
1
]
+
1
;
if
(
i
<
src
.
rows
)
if
(
i
<
rows
)
{
{
short
*
_dx
=
dx
.
ptr
<
short
>
(
i
);
short
*
_dx
=
dx
.
ptr
<
short
>
(
i
);
short
*
_dy
=
dy
.
ptr
<
short
>
(
i
);
short
*
_dy
=
dy
.
ptr
<
short
>
(
i
);
if
(
!
L2gradient
)
if
(
!
L2gradient
)
{
{
int
j
=
0
,
width
=
src
.
cols
*
cn
;
int
j
=
0
,
width
=
cols
*
cn
;
#if CV_SSE2
#if CV_SSE2
if
(
haveSSE2
)
if
(
haveSSE2
)
{
{
...
@@ -788,7 +872,7 @@ while (borderPeaks.try_pop(m))
...
@@ -788,7 +872,7 @@ while (borderPeaks.try_pop(m))
}
}
else
else
{
{
int
j
=
0
,
width
=
src
.
cols
*
cn
;
int
j
=
0
,
width
=
cols
*
cn
;
#if CV_SSE2
#if CV_SSE2
if
(
haveSSE2
)
if
(
haveSSE2
)
{
{
...
@@ -824,7 +908,7 @@ while (borderPeaks.try_pop(m))
...
@@ -824,7 +908,7 @@ while (borderPeaks.try_pop(m))
if
(
cn
>
1
)
if
(
cn
>
1
)
{
{
for
(
int
j
=
0
,
jn
=
0
;
j
<
src
.
cols
;
++
j
,
jn
+=
cn
)
for
(
int
j
=
0
,
jn
=
0
;
j
<
cols
;
++
j
,
jn
+=
cn
)
{
{
int
maxIdx
=
jn
;
int
maxIdx
=
jn
;
for
(
int
k
=
1
;
k
<
cn
;
++
k
)
for
(
int
k
=
1
;
k
<
cn
;
++
k
)
...
@@ -834,7 +918,7 @@ while (borderPeaks.try_pop(m))
...
@@ -834,7 +918,7 @@ while (borderPeaks.try_pop(m))
_dy
[
j
]
=
_dy
[
maxIdx
];
_dy
[
j
]
=
_dy
[
maxIdx
];
}
}
}
}
_norm
[
-
1
]
=
_norm
[
src
.
cols
]
=
0
;
_norm
[
-
1
]
=
_norm
[
cols
]
=
0
;
}
}
else
else
memset
(
_norm
-
1
,
0
,
/* cn* */
mapstep
*
sizeof
(
int
));
memset
(
_norm
-
1
,
0
,
/* cn* */
mapstep
*
sizeof
(
int
));
...
@@ -845,7 +929,7 @@ while (borderPeaks.try_pop(m))
...
@@ -845,7 +929,7 @@ while (borderPeaks.try_pop(m))
continue
;
continue
;
uchar
*
_map
=
map
+
mapstep
*
i
+
1
;
uchar
*
_map
=
map
+
mapstep
*
i
+
1
;
_map
[
-
1
]
=
_map
[
src
.
cols
]
=
1
;
_map
[
-
1
]
=
_map
[
cols
]
=
1
;
int
*
_mag
=
mag_buf
[
1
]
+
1
;
// take the central row
int
*
_mag
=
mag_buf
[
1
]
+
1
;
// take the central row
ptrdiff_t
magstep1
=
mag_buf
[
2
]
-
mag_buf
[
1
];
ptrdiff_t
magstep1
=
mag_buf
[
2
]
-
mag_buf
[
1
];
...
@@ -854,17 +938,17 @@ while (borderPeaks.try_pop(m))
...
@@ -854,17 +938,17 @@ while (borderPeaks.try_pop(m))
const
short
*
_x
=
dx
.
ptr
<
short
>
(
i
-
1
);
const
short
*
_x
=
dx
.
ptr
<
short
>
(
i
-
1
);
const
short
*
_y
=
dy
.
ptr
<
short
>
(
i
-
1
);
const
short
*
_y
=
dy
.
ptr
<
short
>
(
i
-
1
);
if
((
stack_top
-
stack_bottom
)
+
src
.
cols
>
maxsize
)
if
((
stack_top
-
stack_bottom
)
+
cols
>
maxsize
)
{
{
int
sz
=
(
int
)(
stack_top
-
stack_bottom
);
int
sz
=
(
int
)(
stack_top
-
stack_bottom
);
maxsize
=
std
::
max
(
maxsize
*
3
/
2
,
sz
+
src
.
cols
);
maxsize
=
std
::
max
(
maxsize
*
3
/
2
,
sz
+
cols
);
stack
.
resize
(
maxsize
);
stack
.
resize
(
maxsize
);
stack_bottom
=
&
stack
[
0
];
stack_bottom
=
&
stack
[
0
];
stack_top
=
stack_bottom
+
sz
;
stack_top
=
stack_bottom
+
sz
;
}
}
int
prev_flag
=
0
;
int
prev_flag
=
0
;
for
(
int
j
=
0
;
j
<
src
.
cols
;
j
++
)
for
(
int
j
=
0
;
j
<
cols
;
j
++
)
{
{
#define CANNY_SHIFT 15
#define CANNY_SHIFT 15
const
int
TG22
=
(
int
)(
0.4142135623730950488016887242097
*
(
1
<<
CANNY_SHIFT
)
+
0.5
);
const
int
TG22
=
(
int
)(
0.4142135623730950488016887242097
*
(
1
<<
CANNY_SHIFT
)
+
0.5
);
...
@@ -943,18 +1027,18 @@ __ocv_canny_push:
...
@@ -943,18 +1027,18 @@ __ocv_canny_push:
if
(
!
m
[
mapstep
+
1
])
CANNY_PUSH
(
m
+
mapstep
+
1
);
if
(
!
m
[
mapstep
+
1
])
CANNY_PUSH
(
m
+
mapstep
+
1
);
}
}
#endif
// the final pass, form the final image
// the final pass, form the final image
const
uchar
*
pmap
=
map
+
mapstep
+
1
;
const
uchar
*
pmap
=
map
+
mapstep
+
1
;
uchar
*
pdst
=
dst
.
ptr
();
uchar
*
pdst
=
dst
.
ptr
();
for
(
int
i
=
0
;
i
<
src
.
rows
;
i
++
,
pmap
+=
mapstep
,
pdst
+=
dst
.
step
)
for
(
int
i
=
0
;
i
<
rows
;
i
++
,
pmap
+=
mapstep
,
pdst
+=
dst
.
step
)
{
{
for
(
int
j
=
0
;
j
<
src
.
cols
;
j
++
)
for
(
int
j
=
0
;
j
<
cols
;
j
++
)
pdst
[
j
]
=
(
uchar
)
-
(
pmap
[
j
]
>>
1
);
pdst
[
j
]
=
(
uchar
)
-
(
pmap
[
j
]
>>
1
);
}
}
}
}
}
// namespace cv
void
cvCanny
(
const
CvArr
*
image
,
CvArr
*
edges
,
double
threshold1
,
void
cvCanny
(
const
CvArr
*
image
,
CvArr
*
edges
,
double
threshold1
,
double
threshold2
,
int
aperture_size
)
double
threshold2
,
int
aperture_size
)
{
{
...
...
modules/imgproc/test/ocl/test_canny.cpp
View file @
a455858d
...
@@ -54,13 +54,13 @@ namespace ocl {
...
@@ -54,13 +54,13 @@ namespace ocl {
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// Canny
// Canny
IMPLEMENT_PARAM_CLASS
(
Ap
p
ertureSize
,
int
)
IMPLEMENT_PARAM_CLASS
(
ApertureSize
,
int
)
IMPLEMENT_PARAM_CLASS
(
L2gradient
,
bool
)
IMPLEMENT_PARAM_CLASS
(
L2gradient
,
bool
)
IMPLEMENT_PARAM_CLASS
(
UseRoi
,
bool
)
IMPLEMENT_PARAM_CLASS
(
UseRoi
,
bool
)
PARAM_TEST_CASE
(
Canny
,
Channels
,
Ap
p
ertureSize
,
L2gradient
,
UseRoi
)
PARAM_TEST_CASE
(
Canny
,
Channels
,
ApertureSize
,
L2gradient
,
UseRoi
)
{
{
int
cn
,
ap
p
erture_size
;
int
cn
,
aperture_size
;
bool
useL2gradient
,
use_roi
;
bool
useL2gradient
,
use_roi
;
TEST_DECLARE_INPUT_PARAMETER
(
src
);
TEST_DECLARE_INPUT_PARAMETER
(
src
);
...
@@ -69,7 +69,7 @@ PARAM_TEST_CASE(Canny, Channels, AppertureSize, L2gradient, UseRoi)
...
@@ -69,7 +69,7 @@ PARAM_TEST_CASE(Canny, Channels, AppertureSize, L2gradient, UseRoi)
virtual
void
SetUp
()
virtual
void
SetUp
()
{
{
cn
=
GET_PARAM
(
0
);
cn
=
GET_PARAM
(
0
);
ap
p
erture_size
=
GET_PARAM
(
1
);
aperture_size
=
GET_PARAM
(
1
);
useL2gradient
=
GET_PARAM
(
2
);
useL2gradient
=
GET_PARAM
(
2
);
use_roi
=
GET_PARAM
(
3
);
use_roi
=
GET_PARAM
(
3
);
}
}
...
@@ -105,8 +105,31 @@ OCL_TEST_P(Canny, Accuracy)
...
@@ -105,8 +105,31 @@ OCL_TEST_P(Canny, Accuracy)
eps
=
12e-3
;
eps
=
12e-3
;
#endif
#endif
OCL_OFF
(
cv
::
Canny
(
src_roi
,
dst_roi
,
low_thresh
,
high_thresh
,
apperture_size
,
useL2gradient
));
OCL_OFF
(
cv
::
Canny
(
src_roi
,
dst_roi
,
low_thresh
,
high_thresh
,
aperture_size
,
useL2gradient
));
OCL_ON
(
cv
::
Canny
(
usrc_roi
,
udst_roi
,
low_thresh
,
high_thresh
,
apperture_size
,
useL2gradient
));
OCL_ON
(
cv
::
Canny
(
usrc_roi
,
udst_roi
,
low_thresh
,
high_thresh
,
aperture_size
,
useL2gradient
));
EXPECT_MAT_SIMILAR
(
dst_roi
,
udst_roi
,
eps
);
EXPECT_MAT_SIMILAR
(
dst
,
udst
,
eps
);
}
OCL_TEST_P
(
Canny
,
AccuracyCustomGradient
)
{
generateTestData
();
const
double
low_thresh
=
50.0
,
high_thresh
=
100.0
;
double
eps
=
1e-2
;
#ifdef ANDROID
if
(
cv
::
ocl
::
Device
::
getDefault
().
isNVidia
())
eps
=
12e-3
;
#endif
OCL_OFF
(
cv
::
Canny
(
src_roi
,
dst_roi
,
low_thresh
,
high_thresh
,
aperture_size
,
useL2gradient
));
OCL_ON
(
UMat
dx
,
dy
;
Sobel
(
usrc_roi
,
dx
,
CV_16S
,
1
,
0
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
Sobel
(
usrc_roi
,
dy
,
CV_16S
,
0
,
1
,
aperture_size
,
1
,
0
,
BORDER_REPLICATE
);
cv
::
Canny
(
dx
,
dy
,
udst_roi
,
low_thresh
,
high_thresh
,
useL2gradient
);
);
EXPECT_MAT_SIMILAR
(
dst_roi
,
udst_roi
,
eps
);
EXPECT_MAT_SIMILAR
(
dst_roi
,
udst_roi
,
eps
);
EXPECT_MAT_SIMILAR
(
dst
,
udst
,
eps
);
EXPECT_MAT_SIMILAR
(
dst
,
udst
,
eps
);
...
@@ -114,7 +137,7 @@ OCL_TEST_P(Canny, Accuracy)
...
@@ -114,7 +137,7 @@ OCL_TEST_P(Canny, Accuracy)
OCL_INSTANTIATE_TEST_CASE_P
(
ImgProc
,
Canny
,
testing
::
Combine
(
OCL_INSTANTIATE_TEST_CASE_P
(
ImgProc
,
Canny
,
testing
::
Combine
(
testing
::
Values
(
1
,
3
),
testing
::
Values
(
1
,
3
),
testing
::
Values
(
Ap
pertureSize
(
3
),
Ap
pertureSize
(
5
)),
testing
::
Values
(
Ap
ertureSize
(
3
),
A
pertureSize
(
5
)),
testing
::
Values
(
L2gradient
(
false
),
L2gradient
(
true
)),
testing
::
Values
(
L2gradient
(
false
),
L2gradient
(
true
)),
testing
::
Values
(
UseRoi
(
false
),
UseRoi
(
true
))));
testing
::
Values
(
UseRoi
(
false
),
UseRoi
(
true
))));
...
...
modules/imgproc/test/test_canny.cpp
View file @
a455858d
...
@@ -47,7 +47,7 @@ using namespace std;
...
@@ -47,7 +47,7 @@ using namespace std;
class
CV_CannyTest
:
public
cvtest
::
ArrayTest
class
CV_CannyTest
:
public
cvtest
::
ArrayTest
{
{
public
:
public
:
CV_CannyTest
();
CV_CannyTest
(
bool
custom_deriv
=
false
);
protected
:
protected
:
void
get_test_array_types_and_sizes
(
int
test_case_idx
,
vector
<
vector
<
Size
>
>&
sizes
,
vector
<
vector
<
int
>
>&
types
);
void
get_test_array_types_and_sizes
(
int
test_case_idx
,
vector
<
vector
<
Size
>
>&
sizes
,
vector
<
vector
<
int
>
>&
types
);
...
@@ -61,10 +61,11 @@ protected:
...
@@ -61,10 +61,11 @@ protected:
bool
use_true_gradient
;
bool
use_true_gradient
;
double
threshold1
,
threshold2
;
double
threshold1
,
threshold2
;
bool
test_cpp
;
bool
test_cpp
;
bool
test_custom_deriv
;
};
};
CV_CannyTest
::
CV_CannyTest
()
CV_CannyTest
::
CV_CannyTest
(
bool
custom_deriv
)
{
{
test_array
[
INPUT
].
push_back
(
NULL
);
test_array
[
INPUT
].
push_back
(
NULL
);
test_array
[
OUTPUT
].
push_back
(
NULL
);
test_array
[
OUTPUT
].
push_back
(
NULL
);
...
@@ -75,6 +76,7 @@ CV_CannyTest::CV_CannyTest()
...
@@ -75,6 +76,7 @@ CV_CannyTest::CV_CannyTest()
threshold1
=
threshold2
=
0
;
threshold1
=
threshold2
=
0
;
test_cpp
=
false
;
test_cpp
=
false
;
test_custom_deriv
=
custom_deriv
;
}
}
...
@@ -99,6 +101,9 @@ void CV_CannyTest::get_test_array_types_and_sizes( int test_case_idx,
...
@@ -99,6 +101,9 @@ void CV_CannyTest::get_test_array_types_and_sizes( int test_case_idx,
use_true_gradient
=
cvtest
::
randInt
(
rng
)
%
2
!=
0
;
use_true_gradient
=
cvtest
::
randInt
(
rng
)
%
2
!=
0
;
test_cpp
=
(
cvtest
::
randInt
(
rng
)
&
256
)
==
0
;
test_cpp
=
(
cvtest
::
randInt
(
rng
)
&
256
)
==
0
;
ts
->
printf
(
cvtest
::
TS
::
LOG
,
"Canny(size = %d x %d, aperture_size = %d, threshold1 = %g, threshold2 = %g, L2 = %s) test_cpp = %s (test case #%d)
\n
"
,
sizes
[
0
][
0
].
width
,
sizes
[
0
][
0
].
height
,
aperture_size
,
threshold1
,
threshold2
,
use_true_gradient
?
"TRUE"
:
"FALSE"
,
test_cpp
?
"TRUE"
:
"FALSE"
,
test_case_idx
);
}
}
...
@@ -123,9 +128,24 @@ double CV_CannyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/,
...
@@ -123,9 +128,24 @@ double CV_CannyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/,
void
CV_CannyTest
::
run_func
()
void
CV_CannyTest
::
run_func
()
{
{
if
(
!
test_cpp
)
if
(
test_custom_deriv
)
{
cv
::
Mat
_out
=
cv
::
cvarrToMat
(
test_array
[
OUTPUT
][
0
]);
cv
::
Mat
src
=
cv
::
cvarrToMat
(
test_array
[
INPUT
][
0
]);
cv
::
Mat
dx
,
dy
;
int
m
=
aperture_size
;
Point
anchor
(
m
/
2
,
m
/
2
);
Mat
dxkernel
=
cvtest
::
calcSobelKernel2D
(
1
,
0
,
m
,
0
);
Mat
dykernel
=
cvtest
::
calcSobelKernel2D
(
0
,
1
,
m
,
0
);
cvtest
::
filter2D
(
src
,
dx
,
CV_16S
,
dxkernel
,
anchor
,
0
,
BORDER_REPLICATE
);
cvtest
::
filter2D
(
src
,
dy
,
CV_16S
,
dykernel
,
anchor
,
0
,
BORDER_REPLICATE
);
cv
::
Canny
(
dx
,
dy
,
_out
,
threshold1
,
threshold2
,
use_true_gradient
);
}
else
if
(
!
test_cpp
)
{
cvCanny
(
test_array
[
INPUT
][
0
],
test_array
[
OUTPUT
][
0
],
threshold1
,
threshold2
,
cvCanny
(
test_array
[
INPUT
][
0
],
test_array
[
OUTPUT
][
0
],
threshold1
,
threshold2
,
aperture_size
+
(
use_true_gradient
?
CV_CANNY_L2_GRADIENT
:
0
));
aperture_size
+
(
use_true_gradient
?
CV_CANNY_L2_GRADIENT
:
0
));
}
else
else
{
{
cv
::
Mat
_out
=
cv
::
cvarrToMat
(
test_array
[
OUTPUT
][
0
]);
cv
::
Mat
_out
=
cv
::
cvarrToMat
(
test_array
[
OUTPUT
][
0
]);
...
@@ -283,5 +303,6 @@ int CV_CannyTest::validate_test_results( int test_case_idx )
...
@@ -283,5 +303,6 @@ int CV_CannyTest::validate_test_results( int test_case_idx )
}
}
TEST
(
Imgproc_Canny
,
accuracy
)
{
CV_CannyTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_Canny
,
accuracy
)
{
CV_CannyTest
test
;
test
.
safe_run
();
}
TEST
(
Imgproc_Canny
,
accuracy_deriv
)
{
CV_CannyTest
test
(
true
);
test
.
safe_run
();
}
/* End of file. */
/* End of file. */
modules/ts/include/opencv2/ts/ocl_test.hpp
View file @
a455858d
...
@@ -349,8 +349,8 @@ IMPLEMENT_PARAM_CLASS(Channels, int)
...
@@ -349,8 +349,8 @@ IMPLEMENT_PARAM_CLASS(Channels, int)
#define OCL_TEST_F(name, ...) typedef name OCL_##name; TEST_F(OCL_##name, __VA_ARGS__)
#define OCL_TEST_F(name, ...) typedef name OCL_##name; TEST_F(OCL_##name, __VA_ARGS__)
#define OCL_TEST(name, ...) TEST(OCL_##name, __VA_ARGS__)
#define OCL_TEST(name, ...) TEST(OCL_##name, __VA_ARGS__)
#define OCL_OFF(
fn) cv::ocl::setUseOpenCL(false); fn
#define OCL_OFF(
...) cv::ocl::setUseOpenCL(false); __VA_ARGS__ ;
#define OCL_ON(
fn) cv::ocl::setUseOpenCL(true); fn
#define OCL_ON(
...) cv::ocl::setUseOpenCL(true); __VA_ARGS__ ;
#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F)
#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F)
#define OCL_ALL_CHANNELS Values(1, 2, 3, 4)
#define OCL_ALL_CHANNELS Values(1, 2, 3, 4)
...
...
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