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
9a8dbfd5
Commit
9a8dbfd5
authored
Mar 09, 2019
by
Alexander Alekhin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
imgproc: dispatch filter.cpp
parent
756a98a3
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
187 additions
and
1369 deletions
+187
-1369
CMakeLists.txt
modules/imgproc/CMakeLists.txt
+1
-0
filter.dispatch.cpp
modules/imgproc/src/filter.dispatch.cpp
+0
-0
filter.hpp
modules/imgproc/src/filter.hpp
+2
-0
filter.simd.hpp
modules/imgproc/src/filter.simd.hpp
+184
-1369
No files found.
modules/imgproc/CMakeLists.txt
View file @
9a8dbfd5
set
(
the_description
"Image Processing"
)
ocv_add_dispatched_file
(
accum SSE4_1 AVX AVX2
)
ocv_add_dispatched_file
(
filter SSE2 SSE4_1 AVX2
)
ocv_add_dispatched_file
(
color_hsv SSE2 SSE4_1 AVX2
)
ocv_add_dispatched_file
(
color_rgb SSE2 SSE4_1 AVX2
)
ocv_add_dispatched_file
(
color_yuv SSE2 SSE4_1 AVX2
)
...
...
modules/imgproc/src/filter.dispatch.cpp
View file @
9a8dbfd5
This source diff could not be displayed because it is too large. You can
view the blob
instead.
modules/imgproc/src/filter.hpp
View file @
9a8dbfd5
...
...
@@ -56,6 +56,8 @@ namespace cv
InputArray
_kernelX
,
InputArray
_kernelY
,
Point
anchor
,
double
delta
,
int
borderType
);
#endif
void
preprocess2DKernel
(
const
Mat
&
kernel
,
std
::
vector
<
Point
>&
coords
,
std
::
vector
<
uchar
>&
coeffs
);
}
#endif
...
...
modules/imgproc/src/filter.simd.hpp
View file @
9a8dbfd5
...
...
@@ -41,160 +41,85 @@
//M*/
#include "precomp.hpp"
#include "opencv2/core/opencl/ocl_defs.hpp"
#include "opencl_kernels_imgproc.hpp"
#include "hal_replacement.hpp"
#include "opencv2/core/hal/intrin.hpp"
#include "filter.hpp"
/****************************************************************************************\
Base Image Filter
\****************************************************************************************/
#if defined(CV_CPU_BASELINE_MODE)
#if IPP_VERSION_X100 >= 710
#define USE_IPP_SEP_FILTERS 1
#else
#undef USE_IPP_SEP_FILTERS
#endif
#endif
namespace
cv
{
BaseRowFilter
::
BaseRowFilter
()
{
ksize
=
anchor
=
-
1
;
}
BaseRowFilter
::~
BaseRowFilter
()
{}
BaseColumnFilter
::
BaseColumnFilter
()
{
ksize
=
anchor
=
-
1
;
}
BaseColumnFilter
::~
BaseColumnFilter
()
{}
void
BaseColumnFilter
::
reset
()
{}
BaseFilter
::
BaseFilter
()
{
ksize
=
Size
(
-
1
,
-
1
);
anchor
=
Point
(
-
1
,
-
1
);
}
BaseFilter
::~
BaseFilter
()
{}
void
BaseFilter
::
reset
()
{}
FilterEngine
::
FilterEngine
()
:
srcType
(
-
1
),
dstType
(
-
1
),
bufType
(
-
1
),
maxWidth
(
0
),
wholeSize
(
-
1
,
-
1
),
dx1
(
0
),
dx2
(
0
),
rowBorderType
(
BORDER_REPLICATE
),
columnBorderType
(
BORDER_REPLICATE
),
borderElemSize
(
0
),
bufStep
(
0
),
startY
(
0
),
startY0
(
0
),
endY
(
0
),
rowCount
(
0
),
dstY
(
0
)
{
}
FilterEngine
::
FilterEngine
(
const
Ptr
<
BaseFilter
>&
_filter2D
,
const
Ptr
<
BaseRowFilter
>&
_rowFilter
,
const
Ptr
<
BaseColumnFilter
>&
_columnFilter
,
int
_srcType
,
int
_dstType
,
int
_bufType
,
int
_rowBorderType
,
int
_columnBorderType
,
const
Scalar
&
_borderValue
)
:
srcType
(
-
1
),
dstType
(
-
1
),
bufType
(
-
1
),
maxWidth
(
0
),
wholeSize
(
-
1
,
-
1
),
dx1
(
0
),
dx2
(
0
),
rowBorderType
(
BORDER_REPLICATE
),
columnBorderType
(
BORDER_REPLICATE
),
borderElemSize
(
0
),
bufStep
(
0
),
startY
(
0
),
startY0
(
0
),
endY
(
0
),
rowCount
(
0
),
dstY
(
0
)
{
init
(
_filter2D
,
_rowFilter
,
_columnFilter
,
_srcType
,
_dstType
,
_bufType
,
_rowBorderType
,
_columnBorderType
,
_borderValue
);
}
FilterEngine
::~
FilterEngine
()
{
}
void
FilterEngine
::
init
(
const
Ptr
<
BaseFilter
>&
_filter2D
,
const
Ptr
<
BaseRowFilter
>&
_rowFilter
,
const
Ptr
<
BaseColumnFilter
>&
_columnFilter
,
int
_srcType
,
int
_dstType
,
int
_bufType
,
int
_rowBorderType
,
int
_columnBorderType
,
const
Scalar
&
_borderValue
)
{
_srcType
=
CV_MAT_TYPE
(
_srcType
);
_bufType
=
CV_MAT_TYPE
(
_bufType
);
_dstType
=
CV_MAT_TYPE
(
_dstType
);
srcType
=
_srcType
;
int
srcElemSize
=
(
int
)
getElemSize
(
srcType
);
dstType
=
_dstType
;
bufType
=
_bufType
;
filter2D
=
_filter2D
;
rowFilter
=
_rowFilter
;
columnFilter
=
_columnFilter
;
if
(
_columnBorderType
<
0
)
_columnBorderType
=
_rowBorderType
;
rowBorderType
=
_rowBorderType
;
columnBorderType
=
_columnBorderType
;
CV_Assert
(
columnBorderType
!=
BORDER_WRAP
);
/****************************************************************************************\
Base Image Filter
\****************************************************************************************/
if
(
isSeparable
()
)
{
CV_Assert
(
rowFilter
&&
columnFilter
);
ksize
=
Size
(
rowFilter
->
ksize
,
columnFilter
->
ksize
);
anchor
=
Point
(
rowFilter
->
anchor
,
columnFilter
->
anchor
);
}
else
{
CV_Assert
(
bufType
==
srcType
);
ksize
=
filter2D
->
ksize
;
anchor
=
filter2D
->
anchor
;
}
namespace
cv
{
CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
// forward declarations
int
FilterEngine__start
(
FilterEngine
&
this_
,
const
Size
&
_wholeSize
,
const
Size
&
sz
,
const
Point
&
ofs
);
int
FilterEngine__proceed
(
FilterEngine
&
this_
,
const
uchar
*
src
,
int
srcstep
,
int
count
,
uchar
*
dst
,
int
dststep
);
void
FilterEngine__apply
(
FilterEngine
&
this_
,
const
Mat
&
src
,
Mat
&
dst
,
const
Size
&
wsz
,
const
Point
&
ofs
);
CV_Assert
(
0
<=
anchor
.
x
&&
anchor
.
x
<
ksize
.
width
&&
0
<=
anchor
.
y
&&
anchor
.
y
<
ksize
.
height
);
Ptr
<
BaseRowFilter
>
getLinearRowFilter
(
int
srcType
,
int
bufType
,
const
Mat
&
kernel
,
int
anchor
,
int
symmetryType
);
borderElemSize
=
srcElemSize
/
(
CV_MAT_DEPTH
(
srcType
)
>=
CV_32S
?
sizeof
(
int
)
:
1
);
int
borderLength
=
std
::
max
(
ksize
.
width
-
1
,
1
);
borderTab
.
resize
(
borderLength
*
borderElemSize
);
Ptr
<
BaseColumnFilter
>
getLinearColumnFilter
(
int
bufType
,
int
dstType
,
const
Mat
&
kernel
,
int
anchor
,
int
symmetryType
,
double
delta
,
int
bits
);
maxWidth
=
bufStep
=
0
;
constBorderRow
.
clear
();
Ptr
<
BaseFilter
>
getLinearFilter
(
int
srcType
,
int
dstType
,
const
Mat
&
filter_kernel
,
Point
anchor
,
double
delta
,
int
bits
);
if
(
rowBorderType
==
BORDER_CONSTANT
||
columnBorderType
==
BORDER_CONSTANT
)
{
constBorderValue
.
resize
(
srcElemSize
*
borderLength
);
int
srcType1
=
CV_MAKETYPE
(
CV_MAT_DEPTH
(
srcType
),
MIN
(
CV_MAT_CN
(
srcType
),
4
));
scalarToRawData
(
_borderValue
,
&
constBorderValue
[
0
],
srcType1
,
borderLength
*
CV_MAT_CN
(
srcType
));
}
wholeSize
=
Size
(
-
1
,
-
1
);
}
#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
#define VEC_ALIGN CV_MALLOC_ALIGN
int
FilterEngine
::
start
(
const
Size
&
_wholeSize
,
const
Size
&
sz
,
const
Point
&
ofs
)
int
FilterEngine
__start
(
FilterEngine
&
this_
,
const
Size
&
_wholeSize
,
const
Size
&
sz
,
const
Point
&
ofs
)
{
CV_INSTRUMENT_REGION
();
int
i
,
j
;
wholeSize
=
_wholeSize
;
roi
=
Rect
(
ofs
,
sz
);
CV_Assert
(
roi
.
x
>=
0
&&
roi
.
y
>=
0
&&
roi
.
width
>=
0
&&
roi
.
height
>=
0
&&
roi
.
x
+
roi
.
width
<=
wholeSize
.
width
&&
roi
.
y
+
roi
.
height
<=
wholeSize
.
height
);
this_
.
wholeSize
=
_wholeSize
;
this_
.
roi
=
Rect
(
ofs
,
sz
);
CV_Assert
(
this_
.
roi
.
x
>=
0
&&
this_
.
roi
.
y
>=
0
&&
this_
.
roi
.
width
>=
0
&&
this_
.
roi
.
height
>=
0
&&
this_
.
roi
.
x
+
this_
.
roi
.
width
<=
this_
.
wholeSize
.
width
&&
this_
.
roi
.
y
+
this_
.
roi
.
height
<=
this_
.
wholeSize
.
height
);
int
esz
=
(
int
)
getElemSize
(
srcType
);
int
bufElemSize
=
(
int
)
getElemSize
(
bufType
);
const
uchar
*
constVal
=
!
constBorderValue
.
empty
()
?
&
constBorderValue
[
0
]
:
0
;
int
esz
=
(
int
)
getElemSize
(
this_
.
srcType
);
int
bufElemSize
=
(
int
)
getElemSize
(
this_
.
bufType
);
const
uchar
*
constVal
=
!
this_
.
constBorderValue
.
empty
()
?
&
this_
.
constBorderValue
[
0
]
:
0
;
int
_maxBufRows
=
std
::
max
(
ksize
.
height
+
3
,
std
::
max
(
anchor
.
y
,
ksize
.
height
-
anchor
.
y
-
1
)
*
2
+
1
);
int
_maxBufRows
=
std
::
max
(
this_
.
ksize
.
height
+
3
,
std
::
max
(
this_
.
anchor
.
y
,
this_
.
ksize
.
height
-
this_
.
anchor
.
y
-
1
)
*
2
+
1
);
if
(
maxWidth
<
roi
.
width
||
_maxBufRows
!=
(
int
)
rows
.
size
()
)
if
(
this_
.
maxWidth
<
this_
.
roi
.
width
||
_maxBufRows
!=
(
int
)
this_
.
rows
.
size
()
)
{
rows
.
resize
(
_maxBufRows
);
maxWidth
=
std
::
max
(
maxWidth
,
roi
.
width
);
int
cn
=
CV_MAT_CN
(
srcType
);
srcRow
.
resize
(
esz
*
(
maxWidth
+
ksize
.
width
-
1
));
if
(
columnBorderType
==
BORDER_CONSTANT
)
this_
.
rows
.
resize
(
_maxBufRows
);
this_
.
maxWidth
=
std
::
max
(
this_
.
maxWidth
,
this_
.
roi
.
width
);
int
cn
=
CV_MAT_CN
(
this_
.
srcType
);
this_
.
srcRow
.
resize
(
esz
*
(
this_
.
maxWidth
+
this_
.
ksize
.
width
-
1
));
if
(
this_
.
columnBorderType
==
BORDER_CONSTANT
)
{
CV_Assert
(
constVal
!=
NULL
);
constBorderRow
.
resize
(
getElemSize
(
bufType
)
*
(
maxWidth
+
ksize
.
width
-
1
+
VEC_ALIGN
));
uchar
*
dst
=
alignPtr
(
&
constBorderRow
[
0
],
VEC_ALIGN
),
*
tdst
;
int
n
=
(
int
)
constBorderValue
.
size
(),
N
;
N
=
(
maxWidth
+
ksize
.
width
-
1
)
*
esz
;
tdst
=
isSeparable
()
?
&
srcRow
[
0
]
:
dst
;
this_
.
constBorderRow
.
resize
(
getElemSize
(
this_
.
bufType
)
*
(
this_
.
maxWidth
+
this_
.
ksize
.
width
-
1
+
VEC_ALIGN
));
uchar
*
dst
=
alignPtr
(
&
this_
.
constBorderRow
[
0
],
VEC_ALIGN
)
;
int
n
=
(
int
)
this_
.
constBorderValue
.
size
()
;
int
N
=
(
this_
.
maxWidth
+
this_
.
ksize
.
width
-
1
)
*
esz
;
uchar
*
tdst
=
this_
.
isSeparable
()
?
&
this_
.
srcRow
[
0
]
:
dst
;
for
(
i
=
0
;
i
<
N
;
i
+=
n
)
{
...
...
@@ -203,126 +128,113 @@ int FilterEngine::start(const Size &_wholeSize, const Size &sz, const Point &ofs
tdst
[
i
+
j
]
=
constVal
[
j
];
}
if
(
isSeparable
()
)
(
*
rowFilter
)(
&
srcRow
[
0
],
dst
,
maxWidth
,
cn
);
if
(
this_
.
isSeparable
()
)
(
*
this_
.
rowFilter
)(
&
this_
.
srcRow
[
0
],
dst
,
this_
.
maxWidth
,
cn
);
}
int
maxBufStep
=
bufElemSize
*
(
int
)
alignSize
(
maxWidth
+
(
!
isSeparable
()
?
ksize
.
width
-
1
:
0
),
VEC_ALIGN
);
ringBuf
.
resize
(
maxBufStep
*
rows
.
size
()
+
VEC_ALIGN
);
int
maxBufStep
=
bufElemSize
*
(
int
)
alignSize
(
this_
.
maxWidth
+
(
!
this_
.
isSeparable
()
?
this_
.
ksize
.
width
-
1
:
0
),
VEC_ALIGN
);
this_
.
ringBuf
.
resize
(
maxBufStep
*
this_
.
rows
.
size
()
+
VEC_ALIGN
);
}
// adjust bufstep so that the used part of the ring buffer stays compact in memory
bufStep
=
bufElemSize
*
(
int
)
alignSize
(
roi
.
width
+
(
!
isSeparable
()
?
ksize
.
width
-
1
:
0
),
VEC_ALIGN
);
this_
.
bufStep
=
bufElemSize
*
(
int
)
alignSize
(
this_
.
roi
.
width
+
(
!
this_
.
isSeparable
()
?
this_
.
ksize
.
width
-
1
:
0
),
VEC_ALIGN
);
dx1
=
std
::
max
(
anchor
.
x
-
roi
.
x
,
0
);
dx2
=
std
::
max
(
ksize
.
width
-
anchor
.
x
-
1
+
roi
.
x
+
roi
.
width
-
wholeSize
.
width
,
0
);
this_
.
dx1
=
std
::
max
(
this_
.
anchor
.
x
-
this_
.
roi
.
x
,
0
);
this_
.
dx2
=
std
::
max
(
this_
.
ksize
.
width
-
this_
.
anchor
.
x
-
1
+
this_
.
roi
.
x
+
this_
.
roi
.
width
-
this_
.
wholeSize
.
width
,
0
);
// recompute border tables
if
(
dx1
>
0
||
dx2
>
0
)
if
(
this_
.
dx1
>
0
||
this_
.
dx2
>
0
)
{
if
(
rowBorderType
==
BORDER_CONSTANT
)
if
(
this_
.
rowBorderType
==
BORDER_CONSTANT
)
{
CV_Assert
(
constVal
!=
NULL
);
int
nr
=
isSeparable
()
?
1
:
(
int
)
rows
.
size
();
int
nr
=
this_
.
isSeparable
()
?
1
:
(
int
)
this_
.
rows
.
size
();
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
uchar
*
dst
=
isSeparable
()
?
&
srcRow
[
0
]
:
alignPtr
(
&
ringBuf
[
0
],
VEC_ALIGN
)
+
bufStep
*
i
;
memcpy
(
dst
,
constVal
,
dx1
*
esz
);
memcpy
(
dst
+
(
roi
.
width
+
ksize
.
width
-
1
-
dx2
)
*
esz
,
constVal
,
dx2
*
esz
);
uchar
*
dst
=
this_
.
isSeparable
()
?
&
this_
.
srcRow
[
0
]
:
alignPtr
(
&
this_
.
ringBuf
[
0
],
VEC_ALIGN
)
+
this_
.
bufStep
*
i
;
memcpy
(
dst
,
constVal
,
this_
.
dx1
*
esz
);
memcpy
(
dst
+
(
this_
.
roi
.
width
+
this_
.
ksize
.
width
-
1
-
this_
.
dx2
)
*
esz
,
constVal
,
this_
.
dx2
*
esz
);
}
}
else
{
int
xofs1
=
std
::
min
(
roi
.
x
,
anchor
.
x
)
-
roi
.
x
;
int
xofs1
=
std
::
min
(
this_
.
roi
.
x
,
this_
.
anchor
.
x
)
-
this_
.
roi
.
x
;
int
btab_esz
=
borderElemSize
,
wholeWidth
=
wholeSize
.
width
;
int
*
btab
=
(
int
*
)
&
borderTab
[
0
];
int
btab_esz
=
this_
.
borderElemSize
,
wholeWidth
=
this_
.
wholeSize
.
width
;
int
*
btab
=
(
int
*
)
&
this_
.
borderTab
[
0
];
for
(
i
=
0
;
i
<
dx1
;
i
++
)
for
(
i
=
0
;
i
<
this_
.
dx1
;
i
++
)
{
int
p0
=
(
borderInterpolate
(
i
-
dx1
,
wholeWidth
,
rowBorderType
)
+
xofs1
)
*
btab_esz
;
int
p0
=
(
borderInterpolate
(
i
-
this_
.
dx1
,
wholeWidth
,
this_
.
rowBorderType
)
+
xofs1
)
*
btab_esz
;
for
(
j
=
0
;
j
<
btab_esz
;
j
++
)
btab
[
i
*
btab_esz
+
j
]
=
p0
+
j
;
}
for
(
i
=
0
;
i
<
dx2
;
i
++
)
for
(
i
=
0
;
i
<
this_
.
dx2
;
i
++
)
{
int
p0
=
(
borderInterpolate
(
wholeWidth
+
i
,
wholeWidth
,
rowBorderType
)
+
xofs1
)
*
btab_esz
;
int
p0
=
(
borderInterpolate
(
wholeWidth
+
i
,
wholeWidth
,
this_
.
rowBorderType
)
+
xofs1
)
*
btab_esz
;
for
(
j
=
0
;
j
<
btab_esz
;
j
++
)
btab
[(
i
+
dx1
)
*
btab_esz
+
j
]
=
p0
+
j
;
btab
[(
i
+
this_
.
dx1
)
*
btab_esz
+
j
]
=
p0
+
j
;
}
}
}
rowCount
=
dstY
=
0
;
startY
=
startY0
=
std
::
max
(
roi
.
y
-
anchor
.
y
,
0
);
endY
=
std
::
min
(
roi
.
y
+
roi
.
height
+
ksize
.
height
-
anchor
.
y
-
1
,
wholeSize
.
height
);
if
(
columnFilter
)
columnFilter
->
reset
();
if
(
filter2D
)
filter2D
->
reset
();
return
startY
;
}
this_
.
rowCount
=
this_
.
dstY
=
0
;
this_
.
startY
=
this_
.
startY0
=
std
::
max
(
this_
.
roi
.
y
-
this_
.
anchor
.
y
,
0
);
this_
.
endY
=
std
::
min
(
this_
.
roi
.
y
+
this_
.
roi
.
height
+
this_
.
ksize
.
height
-
this_
.
anchor
.
y
-
1
,
this_
.
wholeSize
.
height
);
if
(
this_
.
columnFilter
)
this_
.
columnFilter
->
reset
();
if
(
this_
.
filter2D
)
this_
.
filter2D
->
reset
();
int
FilterEngine
::
start
(
const
Mat
&
src
,
const
Size
&
wsz
,
const
Point
&
ofs
)
{
start
(
wsz
,
src
.
size
(),
ofs
);
return
startY
-
ofs
.
y
;
return
this_
.
startY
;
}
int
FilterEngine
::
remainingInputRows
()
const
{
return
endY
-
startY
-
rowCount
;
}
int
FilterEngine
::
remainingOutputRows
()
const
int
FilterEngine__proceed
(
FilterEngine
&
this_
,
const
uchar
*
src
,
int
srcstep
,
int
count
,
uchar
*
dst
,
int
dststep
)
{
return
roi
.
height
-
dstY
;
}
CV_INSTRUMENT_REGION
();
int
FilterEngine
::
proceed
(
const
uchar
*
src
,
int
srcstep
,
int
count
,
uchar
*
dst
,
int
dststep
)
{
CV_Assert
(
wholeSize
.
width
>
0
&&
wholeSize
.
height
>
0
);
const
int
*
btab
=
&
borderTab
[
0
];
int
esz
=
(
int
)
getElemSize
(
srcType
),
btab_esz
=
borderElemSize
;
uchar
**
brows
=
&
rows
[
0
];
int
bufRows
=
(
int
)
rows
.
size
();
int
cn
=
CV_MAT_CN
(
bufType
);
int
width
=
roi
.
width
,
kwidth
=
ksize
.
width
;
int
kheight
=
ksize
.
height
,
ay
=
anchor
.
y
;
int
_dx1
=
dx1
,
_dx2
=
dx2
;
int
width1
=
roi
.
width
+
kwidth
-
1
;
int
xofs1
=
std
::
min
(
roi
.
x
,
anchor
.
x
);
bool
isSep
=
isSeparable
();
bool
makeBorder
=
(
_dx1
>
0
||
_dx2
>
0
)
&&
rowBorderType
!=
BORDER_CONSTANT
;
CV_DbgAssert
(
this_
.
wholeSize
.
width
>
0
&&
this_
.
wholeSize
.
height
>
0
);
const
int
*
btab
=
&
this_
.
borderTab
[
0
];
int
esz
=
(
int
)
getElemSize
(
this_
.
srcType
),
btab_esz
=
this_
.
borderElemSize
;
uchar
**
brows
=
&
this_
.
rows
[
0
];
int
bufRows
=
(
int
)
this_
.
rows
.
size
();
int
cn
=
CV_MAT_CN
(
this_
.
bufType
);
int
width
=
this_
.
roi
.
width
,
kwidth
=
this_
.
ksize
.
width
;
int
kheight
=
this_
.
ksize
.
height
,
ay
=
this_
.
anchor
.
y
;
int
_dx1
=
this_
.
dx1
,
_dx2
=
this_
.
dx2
;
int
width1
=
this_
.
roi
.
width
+
kwidth
-
1
;
int
xofs1
=
std
::
min
(
this_
.
roi
.
x
,
this_
.
anchor
.
x
);
bool
isSep
=
this_
.
isSeparable
();
bool
makeBorder
=
(
_dx1
>
0
||
_dx2
>
0
)
&&
this_
.
rowBorderType
!=
BORDER_CONSTANT
;
int
dy
=
0
,
i
=
0
;
src
-=
xofs1
*
esz
;
count
=
std
::
min
(
count
,
remainingInputRows
());
count
=
std
::
min
(
count
,
this_
.
remainingInputRows
());
CV_Assert
(
src
&&
dst
&&
count
>
0
);
CV_Assert
(
src
&&
dst
&&
count
>
0
);
for
(;;
dst
+=
dststep
*
i
,
dy
+=
i
)
{
int
dcount
=
bufRows
-
ay
-
startY
-
rowCount
+
roi
.
y
;
int
dcount
=
bufRows
-
ay
-
this_
.
startY
-
this_
.
rowCount
+
this_
.
roi
.
y
;
dcount
=
dcount
>
0
?
dcount
:
bufRows
-
kheight
+
1
;
dcount
=
std
::
min
(
dcount
,
count
);
count
-=
dcount
;
for
(
;
dcount
--
>
0
;
src
+=
srcstep
)
{
int
bi
=
(
startY
-
startY0
+
rowCount
)
%
bufRows
;
uchar
*
brow
=
alignPtr
(
&
ringBuf
[
0
],
VEC_ALIGN
)
+
bi
*
bufStep
;
uchar
*
row
=
isSep
?
&
srcRow
[
0
]
:
brow
;
int
bi
=
(
this_
.
startY
-
this_
.
startY0
+
this_
.
rowCount
)
%
bufRows
;
uchar
*
brow
=
alignPtr
(
&
this_
.
ringBuf
[
0
],
VEC_ALIGN
)
+
bi
*
this_
.
bufStep
;
uchar
*
row
=
isSep
?
&
this_
.
srcRow
[
0
]
:
brow
;
if
(
++
rowCount
>
bufRows
)
if
(
++
this_
.
rowCount
>
bufRows
)
{
--
rowCount
;
++
startY
;
--
this_
.
rowCount
;
++
this_
.
startY
;
}
memcpy
(
row
+
_dx1
*
esz
,
src
,
(
width1
-
_dx2
-
_dx1
)
*
esz
);
...
...
@@ -349,99 +261,55 @@ int FilterEngine::proceed( const uchar* src, int srcstep, int count,
}
if
(
isSep
)
(
*
rowFilter
)(
row
,
brow
,
width
,
CV_MAT_CN
(
srcType
));
(
*
this_
.
rowFilter
)(
row
,
brow
,
width
,
CV_MAT_CN
(
this_
.
srcType
));
}
int
max_i
=
std
::
min
(
bufRows
,
roi
.
height
-
(
dstY
+
dy
)
+
(
kheight
-
1
));
int
max_i
=
std
::
min
(
bufRows
,
this_
.
roi
.
height
-
(
this_
.
dstY
+
dy
)
+
(
kheight
-
1
));
for
(
i
=
0
;
i
<
max_i
;
i
++
)
{
int
srcY
=
borderInterpolate
(
dstY
+
dy
+
i
+
roi
.
y
-
ay
,
wholeSize
.
height
,
columnBorderType
);
int
srcY
=
borderInterpolate
(
this_
.
dstY
+
dy
+
i
+
this_
.
roi
.
y
-
ay
,
this_
.
wholeSize
.
height
,
this_
.
columnBorderType
);
if
(
srcY
<
0
)
// can happen only with constant border type
brows
[
i
]
=
alignPtr
(
&
constBorderRow
[
0
],
VEC_ALIGN
);
brows
[
i
]
=
alignPtr
(
&
this_
.
constBorderRow
[
0
],
VEC_ALIGN
);
else
{
CV_Assert
(
srcY
>=
startY
);
if
(
srcY
>=
startY
+
rowCount
)
CV_Assert
(
srcY
>=
this_
.
startY
);
if
(
srcY
>=
this_
.
startY
+
this_
.
rowCount
)
break
;
int
bi
=
(
srcY
-
startY0
)
%
bufRows
;
brows
[
i
]
=
alignPtr
(
&
ringBuf
[
0
],
VEC_ALIGN
)
+
bi
*
bufStep
;
int
bi
=
(
srcY
-
this_
.
startY0
)
%
bufRows
;
brows
[
i
]
=
alignPtr
(
&
this_
.
ringBuf
[
0
],
VEC_ALIGN
)
+
bi
*
this_
.
bufStep
;
}
}
if
(
i
<
kheight
)
break
;
i
-=
kheight
-
1
;
if
(
isSeparable
()
)
(
*
columnFilter
)((
const
uchar
**
)
brows
,
dst
,
dststep
,
i
,
roi
.
width
*
cn
);
if
(
isSep
)
(
*
this_
.
columnFilter
)((
const
uchar
**
)
brows
,
dst
,
dststep
,
i
,
this_
.
roi
.
width
*
cn
);
else
(
*
filter2D
)((
const
uchar
**
)
brows
,
dst
,
dststep
,
i
,
roi
.
width
,
cn
);
(
*
this_
.
filter2D
)((
const
uchar
**
)
brows
,
dst
,
dststep
,
i
,
this_
.
roi
.
width
,
cn
);
}
dstY
+=
dy
;
CV_Assert
(
dstY
<=
roi
.
height
);
this_
.
dstY
+=
dy
;
CV_Assert
(
this_
.
dstY
<=
this_
.
roi
.
height
);
return
dy
;
}
void
FilterEngine
::
apply
(
const
Mat
&
src
,
Mat
&
dst
,
const
Size
&
wsz
,
const
Point
&
ofs
)
void
FilterEngine
__apply
(
FilterEngine
&
this_
,
const
Mat
&
src
,
Mat
&
dst
,
const
Size
&
wsz
,
const
Point
&
ofs
)
{
CV_INSTRUMENT_REGION
();
CV_
Assert
(
src
.
type
()
==
srcType
&&
dst
.
type
()
==
dstType
);
CV_
DbgAssert
(
src
.
type
()
==
this_
.
srcType
&&
dst
.
type
()
==
this_
.
dstType
);
int
y
=
start
(
src
,
wsz
,
ofs
);
proceed
(
src
.
ptr
()
+
y
*
src
.
step
,
FilterEngine__start
(
this_
,
wsz
,
src
.
size
(),
ofs
);
int
y
=
this_
.
startY
-
ofs
.
y
;
FilterEngine__proceed
(
this_
,
src
.
ptr
()
+
y
*
src
.
step
,
(
int
)
src
.
step
,
endY
-
startY
,
this_
.
endY
-
this_
.
startY
,
dst
.
ptr
(),
(
int
)
dst
.
step
);
}
}
/****************************************************************************************\
* Separable linear filter *
\****************************************************************************************/
int
cv
::
getKernelType
(
InputArray
filter_kernel
,
Point
anchor
)
{
Mat
_kernel
=
filter_kernel
.
getMat
();
CV_Assert
(
_kernel
.
channels
()
==
1
);
int
i
,
sz
=
_kernel
.
rows
*
_kernel
.
cols
;
Mat
kernel
;
_kernel
.
convertTo
(
kernel
,
CV_64F
);
const
double
*
coeffs
=
kernel
.
ptr
<
double
>
();
double
sum
=
0
;
int
type
=
KERNEL_SMOOTH
+
KERNEL_INTEGER
;
if
(
(
_kernel
.
rows
==
1
||
_kernel
.
cols
==
1
)
&&
anchor
.
x
*
2
+
1
==
_kernel
.
cols
&&
anchor
.
y
*
2
+
1
==
_kernel
.
rows
)
type
|=
(
KERNEL_SYMMETRICAL
+
KERNEL_ASYMMETRICAL
);
for
(
i
=
0
;
i
<
sz
;
i
++
)
{
double
a
=
coeffs
[
i
],
b
=
coeffs
[
sz
-
i
-
1
];
if
(
a
!=
b
)
type
&=
~
KERNEL_SYMMETRICAL
;
if
(
a
!=
-
b
)
type
&=
~
KERNEL_ASYMMETRICAL
;
if
(
a
<
0
)
type
&=
~
KERNEL_SMOOTH
;
if
(
a
!=
saturate_cast
<
int
>
(
a
)
)
type
&=
~
KERNEL_INTEGER
;
sum
+=
a
;
}
if
(
fabs
(
sum
-
1
)
>
FLT_EPSILON
*
(
fabs
(
sum
)
+
1
)
)
type
&=
~
KERNEL_SMOOTH
;
return
type
;
}
namespace
cv
{
struct
RowNoVec
{
RowNoVec
()
{}
...
...
@@ -503,6 +371,8 @@ struct RowVec_8u32s
int
operator
()(
const
uchar
*
_src
,
uchar
*
_dst
,
int
width
,
int
cn
)
const
{
CV_INSTRUMENT_REGION
();
int
i
=
0
,
k
,
_ksize
=
kernel
.
rows
+
kernel
.
cols
-
1
;
int
*
dst
=
(
int
*
)
_dst
;
const
int
*
_kx
=
kernel
.
ptr
<
int
>
();
...
...
@@ -587,7 +457,6 @@ struct RowVec_8u32s
i
+=
v_uint32
::
nlanes
;
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -618,6 +487,8 @@ struct SymmRowSmallVec_8u32s
int
operator
()(
const
uchar
*
src
,
uchar
*
_dst
,
int
width
,
int
cn
)
const
{
CV_INSTRUMENT_REGION
();
int
i
=
0
,
j
,
k
,
_ksize
=
kernel
.
rows
+
kernel
.
cols
-
1
;
int
*
dst
=
(
int
*
)
_dst
;
bool
symmetrical
=
(
symmetryType
&
KERNEL_SYMMETRICAL
)
!=
0
;
...
...
@@ -1083,8 +954,6 @@ struct SymmRowSmallVec_8u32s
}
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -1107,6 +976,8 @@ struct SymmColumnVec_32s8u
int
operator
()(
const
uchar
**
_src
,
uchar
*
dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
int
_ksize
=
kernel
.
rows
+
kernel
.
cols
-
1
;
if
(
_ksize
==
1
)
return
0
;
...
...
@@ -1237,8 +1108,6 @@ struct SymmColumnVec_32s8u
i
+=
v_int32x4
::
nlanes
;
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -1261,6 +1130,8 @@ struct SymmColumnSmallVec_32s16s
int
operator
()(
const
uchar
**
_src
,
uchar
*
_dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
int
ksize2
=
(
kernel
.
rows
+
kernel
.
cols
-
1
)
/
2
;
const
float
*
ky
=
kernel
.
ptr
<
float
>
()
+
ksize2
;
int
i
=
0
;
...
...
@@ -1420,8 +1291,6 @@ struct SymmColumnSmallVec_32s16s
}
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -1443,6 +1312,8 @@ struct RowVec_16s32f
int
operator
()(
const
uchar
*
_src
,
uchar
*
_dst
,
int
width
,
int
cn
)
const
{
CV_INSTRUMENT_REGION
();
int
i
=
0
,
k
,
_ksize
=
kernel
.
rows
+
kernel
.
cols
-
1
;
float
*
dst
=
(
float
*
)
_dst
;
const
float
*
_kx
=
kernel
.
ptr
<
float
>
();
...
...
@@ -1495,7 +1366,6 @@ struct RowVec_16s32f
v_store
(
dst
+
i
,
s0
);
i
+=
v_float32
::
nlanes
;
}
vx_cleanup
();
return
i
;
}
...
...
@@ -1516,6 +1386,8 @@ struct SymmColumnVec_32f16s
int
operator
()(
const
uchar
**
_src
,
uchar
*
_dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
int
_ksize
=
kernel
.
rows
+
kernel
.
cols
-
1
;
if
(
_ksize
==
1
)
return
0
;
...
...
@@ -1620,7 +1492,6 @@ struct SymmColumnVec_32f16s
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -1653,6 +1524,8 @@ struct RowVec_32f
int
operator
()(
const
uchar
*
_src
,
uchar
*
_dst
,
int
width
,
int
cn
)
const
{
CV_INSTRUMENT_REGION
();
#if defined USE_IPP_SEP_FILTERS
CV_IPP_CHECK
()
{
...
...
@@ -1722,7 +1595,6 @@ struct RowVec_32f
v_store
(
dst
+
i
,
s0
);
i
+=
v_float32
::
nlanes
;
}
vx_cleanup
();
return
i
;
}
...
...
@@ -1782,6 +1654,8 @@ struct SymmRowSmallVec_32f
int
operator
()(
const
uchar
*
_src
,
uchar
*
_dst
,
int
width
,
int
cn
)
const
{
CV_INSTRUMENT_REGION
();
int
i
=
0
,
_ksize
=
kernel
.
rows
+
kernel
.
cols
-
1
;
if
(
_ksize
==
1
)
return
0
;
...
...
@@ -1868,8 +1742,6 @@ struct SymmRowSmallVec_32f
v_store
(
dst
+
i
,
v_muladd
(
vx_load
(
src
+
2
*
cn
)
-
vx_load
(
src
-
2
*
cn
),
k2
,
(
vx_load
(
src
+
cn
)
-
vx_load
(
src
-
cn
))
*
k1
));
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -1896,6 +1768,8 @@ struct SymmColumnVec_32f
int
operator
()(
const
uchar
**
_src
,
uchar
*
_dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
int
ksize2
=
(
kernel
.
rows
+
kernel
.
cols
-
1
)
/
2
;
const
float
*
ky
=
kernel
.
ptr
<
float
>
()
+
ksize2
;
int
i
=
0
,
k
;
...
...
@@ -2005,8 +1879,6 @@ struct SymmColumnVec_32f
i
+=
v_float32
::
nlanes
;
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -2030,6 +1902,8 @@ struct SymmColumnSmallVec_32f
int
operator
()(
const
uchar
**
_src
,
uchar
*
_dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
int
ksize2
=
(
kernel
.
rows
+
kernel
.
cols
-
1
)
/
2
;
const
float
*
ky
=
kernel
.
ptr
<
float
>
()
+
ksize2
;
int
i
=
0
;
...
...
@@ -2085,8 +1959,6 @@ struct SymmColumnSmallVec_32f
v_store
(
dst
+
i
,
v_muladd
(
vx_load
(
S2
+
i
)
-
vx_load
(
S0
+
i
),
k1
,
d4
));
}
}
vx_cleanup
();
return
i
;
}
...
...
@@ -2115,6 +1987,8 @@ struct FilterVec_8u
int
operator
()(
const
uchar
**
src
,
uchar
*
dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
CV_DbgAssert
(
_nz
>
0
);
const
float
*
kf
=
(
const
float
*
)
&
coeffs
[
0
];
int
i
=
0
,
k
,
nz
=
_nz
;
...
...
@@ -2175,8 +2049,6 @@ struct FilterVec_8u
*
(
int
*
)(
dst
+
i
)
=
v_reinterpret_as_s32
(
v_pack_u
(
s16
,
s16
)).
get0
();
i
+=
v_int32x4
::
nlanes
;
}
vx_cleanup
();
return
i
;
}
...
...
@@ -2201,6 +2073,8 @@ struct FilterVec_8u16s
int
operator
()(
const
uchar
**
src
,
uchar
*
_dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
CV_DbgAssert
(
_nz
>
0
);
const
float
*
kf
=
(
const
float
*
)
&
coeffs
[
0
];
short
*
dst
=
(
short
*
)
_dst
;
...
...
@@ -2251,8 +2125,6 @@ struct FilterVec_8u16s
v_pack_store
(
dst
+
i
,
v_round
(
s0
));
i
+=
v_int32
::
nlanes
;
}
vx_cleanup
();
return
i
;
}
...
...
@@ -2275,6 +2147,8 @@ struct FilterVec_32f
int
operator
()(
const
uchar
**
_src
,
uchar
*
_dst
,
int
width
)
const
{
CV_INSTRUMENT_REGION
();
const
float
*
kf
=
(
const
float
*
)
&
coeffs
[
0
];
const
float
**
src
=
(
const
float
**
)
_src
;
float
*
dst
=
(
float
*
)
_dst
;
...
...
@@ -2323,8 +2197,6 @@ struct FilterVec_32f
v_store
(
dst
+
i
,
s0
);
i
+=
v_float32
::
nlanes
;
}
vx_cleanup
();
return
i
;
}
...
...
@@ -2369,6 +2241,8 @@ template<typename ST, typename DT, class VecOp> struct RowFilter : public BaseRo
void
operator
()(
const
uchar
*
src
,
uchar
*
dst
,
int
width
,
int
cn
)
CV_OVERRIDE
{
CV_INSTRUMENT_REGION
();
int
_ksize
=
ksize
;
const
DT
*
kx
=
kernel
.
ptr
<
DT
>
();
const
ST
*
S
;
...
...
@@ -2427,6 +2301,8 @@ template<typename ST, typename DT, class VecOp> struct SymmRowSmallFilter :
void
operator
()(
const
uchar
*
src
,
uchar
*
dst
,
int
width
,
int
cn
)
CV_OVERRIDE
{
CV_INSTRUMENT_REGION
();
int
ksize2
=
this
->
ksize
/
2
,
ksize2n
=
ksize2
*
cn
;
const
DT
*
kx
=
this
->
kernel
.
template
ptr
<
DT
>
()
+
ksize2
;
bool
symmetrical
=
(
this
->
symmetryType
&
KERNEL_SYMMETRICAL
)
!=
0
;
...
...
@@ -2566,6 +2442,8 @@ template<class CastOp, class VecOp> struct ColumnFilter : public BaseColumnFilte
void
operator
()(
const
uchar
**
src
,
uchar
*
dst
,
int
dststep
,
int
count
,
int
width
)
CV_OVERRIDE
{
CV_INSTRUMENT_REGION
();
const
ST
*
ky
=
kernel
.
template
ptr
<
ST
>
();
ST
_delta
=
delta
;
int
_ksize
=
ksize
;
...
...
@@ -2629,6 +2507,8 @@ template<class CastOp, class VecOp> struct SymmColumnFilter : public ColumnFilte
void
operator
()(
const
uchar
**
src
,
uchar
*
dst
,
int
dststep
,
int
count
,
int
width
)
CV_OVERRIDE
{
CV_INSTRUMENT_REGION
();
int
ksize2
=
this
->
ksize
/
2
;
const
ST
*
ky
=
this
->
kernel
.
template
ptr
<
ST
>
()
+
ksize2
;
int
i
,
k
;
...
...
@@ -2735,6 +2615,8 @@ struct SymmColumnSmallFilter : public SymmColumnFilter<CastOp, VecOp>
void
operator
()(
const
uchar
**
src
,
uchar
*
dst
,
int
dststep
,
int
count
,
int
width
)
CV_OVERRIDE
{
CV_INSTRUMENT_REGION
();
int
ksize2
=
this
->
ksize
/
2
;
const
ST
*
ky
=
this
->
kernel
.
template
ptr
<
ST
>
()
+
ksize2
;
int
i
;
...
...
@@ -2904,13 +2786,14 @@ template<typename ST, typename DT> struct FixedPtCastEx
int
SHIFT
,
DELTA
;
};
}
cv
::
Ptr
<
cv
::
BaseRowFilter
>
cv
::
getLinearRowFilter
(
int
srcType
,
int
bufType
,
InputArray
_kernel
,
int
anchor
,
int
symmetryType
)
Ptr
<
BaseRowFilter
>
getLinearRowFilter
(
int
srcType
,
int
bufType
,
const
Mat
&
kernel
,
int
anchor
,
int
symmetryType
)
{
Mat
kernel
=
_kernel
.
getMat
();
CV_INSTRUMENT_REGION
();
int
sdepth
=
CV_MAT_DEPTH
(
srcType
),
ddepth
=
CV_MAT_DEPTH
(
bufType
);
int
cn
=
CV_MAT_CN
(
srcType
);
CV_Assert
(
cn
==
CV_MAT_CN
(
bufType
)
&&
...
...
@@ -2958,12 +2841,14 @@ cv::Ptr<cv::BaseRowFilter> cv::getLinearRowFilter( int srcType, int bufType,
}
cv
::
Ptr
<
cv
::
BaseColumnFilter
>
cv
::
getLinearColumnFilter
(
int
bufType
,
int
dstType
,
InputArray
_kernel
,
int
anchor
,
int
symmetryType
,
double
delta
,
int
bits
)
Ptr
<
BaseColumnFilter
>
getLinearColumnFilter
(
int
bufType
,
int
dstType
,
const
Mat
&
kernel
,
int
anchor
,
int
symmetryType
,
double
delta
,
int
bits
)
{
Mat
kernel
=
_kernel
.
getMat
();
CV_INSTRUMENT_REGION
();
int
sdepth
=
CV_MAT_DEPTH
(
bufType
),
ddepth
=
CV_MAT_DEPTH
(
dstType
);
int
cn
=
CV_MAT_CN
(
dstType
);
CV_Assert
(
cn
==
CV_MAT_CN
(
bufType
)
&&
...
...
@@ -3053,131 +2938,6 @@ cv::Ptr<cv::BaseColumnFilter> cv::getLinearColumnFilter( int bufType, int dstTyp
}
cv
::
Ptr
<
cv
::
FilterEngine
>
cv
::
createSeparableLinearFilter
(
int
_srcType
,
int
_dstType
,
InputArray
__rowKernel
,
InputArray
__columnKernel
,
Point
_anchor
,
double
_delta
,
int
_rowBorderType
,
int
_columnBorderType
,
const
Scalar
&
_borderValue
)
{
Mat
_rowKernel
=
__rowKernel
.
getMat
(),
_columnKernel
=
__columnKernel
.
getMat
();
_srcType
=
CV_MAT_TYPE
(
_srcType
);
_dstType
=
CV_MAT_TYPE
(
_dstType
);
int
sdepth
=
CV_MAT_DEPTH
(
_srcType
),
ddepth
=
CV_MAT_DEPTH
(
_dstType
);
int
cn
=
CV_MAT_CN
(
_srcType
);
CV_Assert
(
cn
==
CV_MAT_CN
(
_dstType
)
);
int
rsize
=
_rowKernel
.
rows
+
_rowKernel
.
cols
-
1
;
int
csize
=
_columnKernel
.
rows
+
_columnKernel
.
cols
-
1
;
if
(
_anchor
.
x
<
0
)
_anchor
.
x
=
rsize
/
2
;
if
(
_anchor
.
y
<
0
)
_anchor
.
y
=
csize
/
2
;
int
rtype
=
getKernelType
(
_rowKernel
,
_rowKernel
.
rows
==
1
?
Point
(
_anchor
.
x
,
0
)
:
Point
(
0
,
_anchor
.
x
));
int
ctype
=
getKernelType
(
_columnKernel
,
_columnKernel
.
rows
==
1
?
Point
(
_anchor
.
y
,
0
)
:
Point
(
0
,
_anchor
.
y
));
Mat
rowKernel
,
columnKernel
;
int
bdepth
=
std
::
max
(
CV_32F
,
std
::
max
(
sdepth
,
ddepth
));
int
bits
=
0
;
if
(
sdepth
==
CV_8U
&&
((
rtype
==
KERNEL_SMOOTH
+
KERNEL_SYMMETRICAL
&&
ctype
==
KERNEL_SMOOTH
+
KERNEL_SYMMETRICAL
&&
ddepth
==
CV_8U
)
||
((
rtype
&
(
KERNEL_SYMMETRICAL
+
KERNEL_ASYMMETRICAL
))
&&
(
ctype
&
(
KERNEL_SYMMETRICAL
+
KERNEL_ASYMMETRICAL
))
&&
(
rtype
&
ctype
&
KERNEL_INTEGER
)
&&
ddepth
==
CV_16S
))
)
{
bdepth
=
CV_32S
;
bits
=
ddepth
==
CV_8U
?
8
:
0
;
_rowKernel
.
convertTo
(
rowKernel
,
CV_32S
,
1
<<
bits
);
_columnKernel
.
convertTo
(
columnKernel
,
CV_32S
,
1
<<
bits
);
bits
*=
2
;
_delta
*=
(
1
<<
bits
);
}
else
{
if
(
_rowKernel
.
type
()
!=
bdepth
)
_rowKernel
.
convertTo
(
rowKernel
,
bdepth
);
else
rowKernel
=
_rowKernel
;
if
(
_columnKernel
.
type
()
!=
bdepth
)
_columnKernel
.
convertTo
(
columnKernel
,
bdepth
);
else
columnKernel
=
_columnKernel
;
}
int
_bufType
=
CV_MAKETYPE
(
bdepth
,
cn
);
Ptr
<
BaseRowFilter
>
_rowFilter
=
getLinearRowFilter
(
_srcType
,
_bufType
,
rowKernel
,
_anchor
.
x
,
rtype
);
Ptr
<
BaseColumnFilter
>
_columnFilter
=
getLinearColumnFilter
(
_bufType
,
_dstType
,
columnKernel
,
_anchor
.
y
,
ctype
,
_delta
,
bits
);
return
Ptr
<
FilterEngine
>
(
new
FilterEngine
(
Ptr
<
BaseFilter
>
(),
_rowFilter
,
_columnFilter
,
_srcType
,
_dstType
,
_bufType
,
_rowBorderType
,
_columnBorderType
,
_borderValue
));
}
/****************************************************************************************\
* Non-separable linear filter *
\****************************************************************************************/
namespace
cv
{
void
preprocess2DKernel
(
const
Mat
&
kernel
,
std
::
vector
<
Point
>&
coords
,
std
::
vector
<
uchar
>&
coeffs
)
{
int
i
,
j
,
k
,
nz
=
countNonZero
(
kernel
),
ktype
=
kernel
.
type
();
if
(
nz
==
0
)
nz
=
1
;
CV_Assert
(
ktype
==
CV_8U
||
ktype
==
CV_32S
||
ktype
==
CV_32F
||
ktype
==
CV_64F
);
coords
.
resize
(
nz
);
coeffs
.
resize
(
nz
*
getElemSize
(
ktype
));
uchar
*
_coeffs
=
&
coeffs
[
0
];
for
(
i
=
k
=
0
;
i
<
kernel
.
rows
;
i
++
)
{
const
uchar
*
krow
=
kernel
.
ptr
(
i
);
for
(
j
=
0
;
j
<
kernel
.
cols
;
j
++
)
{
if
(
ktype
==
CV_8U
)
{
uchar
val
=
krow
[
j
];
if
(
val
==
0
)
continue
;
coords
[
k
]
=
Point
(
j
,
i
);
_coeffs
[
k
++
]
=
val
;
}
else
if
(
ktype
==
CV_32S
)
{
int
val
=
((
const
int
*
)
krow
)[
j
];
if
(
val
==
0
)
continue
;
coords
[
k
]
=
Point
(
j
,
i
);
((
int
*
)
_coeffs
)[
k
++
]
=
val
;
}
else
if
(
ktype
==
CV_32F
)
{
float
val
=
((
const
float
*
)
krow
)[
j
];
if
(
val
==
0
)
continue
;
coords
[
k
]
=
Point
(
j
,
i
);
((
float
*
)
_coeffs
)[
k
++
]
=
val
;
}
else
{
double
val
=
((
const
double
*
)
krow
)[
j
];
if
(
val
==
0
)
continue
;
coords
[
k
]
=
Point
(
j
,
i
);
((
double
*
)
_coeffs
)[
k
++
]
=
val
;
}
}
}
}
template
<
typename
ST
,
class
CastOp
,
class
VecOp
>
struct
Filter2D
:
public
BaseFilter
{
...
...
@@ -3253,489 +3013,14 @@ template<typename ST, class CastOp, class VecOp> struct Filter2D : public BaseFi
VecOp
vecOp
;
};
#ifdef HAVE_OPENCL
#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain))
#define ROUNDUP(sz, n) ((sz) + (n) - 1 - (((sz) + (n) - 1) % (n)))
// prepare kernel: transpose and make double rows (+align). Returns size of aligned row
// Samples:
// a b c
// Input: d e f
// g h i
// Output, last two zeros is the alignment:
// a d g a d g 0 0
// b e h b e h 0 0
// c f i c f i 0 0
template
<
typename
T
>
static
int
_prepareKernelFilter2D
(
std
::
vector
<
T
>
&
data
,
const
Mat
&
kernel
)
{
Mat
_kernel
;
kernel
.
convertTo
(
_kernel
,
DataDepth
<
T
>::
value
);
int
size_y_aligned
=
ROUNDUP
(
kernel
.
rows
*
2
,
4
);
data
.
clear
();
data
.
resize
(
size_y_aligned
*
kernel
.
cols
,
0
);
for
(
int
x
=
0
;
x
<
kernel
.
cols
;
x
++
)
{
for
(
int
y
=
0
;
y
<
kernel
.
rows
;
y
++
)
{
data
[
x
*
size_y_aligned
+
y
]
=
_kernel
.
at
<
T
>
(
y
,
x
);
data
[
x
*
size_y_aligned
+
y
+
kernel
.
rows
]
=
_kernel
.
at
<
T
>
(
y
,
x
);
}
}
return
size_y_aligned
;
}
static
bool
ocl_filter2D
(
InputArray
_src
,
OutputArray
_dst
,
int
ddepth
,
InputArray
_kernel
,
Point
anchor
,
double
delta
,
int
borderType
)
{
int
type
=
_src
.
type
(),
sdepth
=
CV_MAT_DEPTH
(
type
),
cn
=
CV_MAT_CN
(
type
);
ddepth
=
ddepth
<
0
?
sdepth
:
ddepth
;
int
dtype
=
CV_MAKE_TYPE
(
ddepth
,
cn
),
wdepth
=
std
::
max
(
std
::
max
(
sdepth
,
ddepth
),
CV_32F
),
wtype
=
CV_MAKE_TYPE
(
wdepth
,
cn
);
if
(
cn
>
4
)
return
false
;
Size
ksize
=
_kernel
.
size
();
if
(
anchor
.
x
<
0
)
anchor
.
x
=
ksize
.
width
/
2
;
if
(
anchor
.
y
<
0
)
anchor
.
y
=
ksize
.
height
/
2
;
bool
isolated
=
(
borderType
&
BORDER_ISOLATED
)
!=
0
;
borderType
&=
~
BORDER_ISOLATED
;
const
cv
::
ocl
::
Device
&
device
=
cv
::
ocl
::
Device
::
getDefault
();
bool
doubleSupport
=
device
.
doubleFPConfig
()
>
0
;
if
(
wdepth
==
CV_64F
&&
!
doubleSupport
)
return
false
;
const
char
*
const
borderMap
[]
=
{
"BORDER_CONSTANT"
,
"BORDER_REPLICATE"
,
"BORDER_REFLECT"
,
"BORDER_WRAP"
,
"BORDER_REFLECT_101"
};
cv
::
Mat
kernelMat
=
_kernel
.
getMat
();
cv
::
Size
sz
=
_src
.
size
(),
wholeSize
;
size_t
globalsize
[
2
]
=
{
(
size_t
)
sz
.
width
,
(
size_t
)
sz
.
height
};
size_t
localsize_general
[
2
]
=
{
0
,
1
};
size_t
*
localsize
=
NULL
;
ocl
::
Kernel
k
;
UMat
src
=
_src
.
getUMat
();
if
(
!
isolated
)
{
Point
ofs
;
src
.
locateROI
(
wholeSize
,
ofs
);
}
size_t
tryWorkItems
=
device
.
maxWorkGroupSize
();
if
(
device
.
isIntel
()
&&
128
<
tryWorkItems
)
tryWorkItems
=
128
;
char
cvt
[
2
][
40
];
// For smaller filter kernels, there is a special kernel that is more
// efficient than the general one.
UMat
kernalDataUMat
;
if
(
device
.
isIntel
()
&&
(
device
.
type
()
&
ocl
::
Device
::
TYPE_GPU
)
&&
((
ksize
.
width
<
5
&&
ksize
.
height
<
5
)
||
(
ksize
.
width
==
5
&&
ksize
.
height
==
5
&&
cn
==
1
)))
{
kernelMat
=
kernelMat
.
reshape
(
0
,
1
);
String
kerStr
=
ocl
::
kernelToStr
(
kernelMat
,
CV_32F
);
int
h
=
isolated
?
sz
.
height
:
wholeSize
.
height
;
int
w
=
isolated
?
sz
.
width
:
wholeSize
.
width
;
if
(
w
<
ksize
.
width
||
h
<
ksize
.
height
)
return
false
;
// Figure out what vector size to use for loading the pixels.
int
pxLoadNumPixels
=
cn
!=
1
||
sz
.
width
%
4
?
1
:
4
;
int
pxLoadVecSize
=
cn
*
pxLoadNumPixels
;
// Figure out how many pixels per work item to compute in X and Y
// directions. Too many and we run out of registers.
int
pxPerWorkItemX
=
1
;
int
pxPerWorkItemY
=
1
;
if
(
cn
<=
2
&&
ksize
.
width
<=
4
&&
ksize
.
height
<=
4
)
{
pxPerWorkItemX
=
sz
.
width
%
8
?
sz
.
width
%
4
?
sz
.
width
%
2
?
1
:
2
:
4
:
8
;
pxPerWorkItemY
=
sz
.
height
%
2
?
1
:
2
;
}
else
if
(
cn
<
4
||
(
ksize
.
width
<=
4
&&
ksize
.
height
<=
4
))
{
pxPerWorkItemX
=
sz
.
width
%
2
?
1
:
2
;
pxPerWorkItemY
=
sz
.
height
%
2
?
1
:
2
;
}
globalsize
[
0
]
=
sz
.
width
/
pxPerWorkItemX
;
globalsize
[
1
]
=
sz
.
height
/
pxPerWorkItemY
;
// Need some padding in the private array for pixels
int
privDataWidth
=
ROUNDUP
(
pxPerWorkItemX
+
ksize
.
width
-
1
,
pxLoadNumPixels
);
// Make the global size a nice round number so the runtime can pick
// from reasonable choices for the workgroup size
const
int
wgRound
=
256
;
globalsize
[
0
]
=
ROUNDUP
(
globalsize
[
0
],
wgRound
);
char
build_options
[
1024
];
sprintf
(
build_options
,
"-D cn=%d "
"-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
"-D PX_LOAD_VEC_SIZE=%d -D PX_LOAD_NUM_PX=%d "
"-D PX_PER_WI_X=%d -D PX_PER_WI_Y=%d -D PRIV_DATA_WIDTH=%d -D %s -D %s "
"-D PX_LOAD_X_ITERATIONS=%d -D PX_LOAD_Y_ITERATIONS=%d "
"-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
"-D convertToWT=%s -D convertToDstT=%s %s"
,
cn
,
anchor
.
x
,
anchor
.
y
,
ksize
.
width
,
ksize
.
height
,
pxLoadVecSize
,
pxLoadNumPixels
,
pxPerWorkItemX
,
pxPerWorkItemY
,
privDataWidth
,
borderMap
[
borderType
],
isolated
?
"BORDER_ISOLATED"
:
"NO_BORDER_ISOLATED"
,
privDataWidth
/
pxLoadNumPixels
,
pxPerWorkItemY
+
ksize
.
height
-
1
,
ocl
::
typeToStr
(
type
),
ocl
::
typeToStr
(
sdepth
),
ocl
::
typeToStr
(
dtype
),
ocl
::
typeToStr
(
ddepth
),
ocl
::
typeToStr
(
wtype
),
ocl
::
typeToStr
(
wdepth
),
ocl
::
convertTypeStr
(
sdepth
,
wdepth
,
cn
,
cvt
[
0
]),
ocl
::
convertTypeStr
(
wdepth
,
ddepth
,
cn
,
cvt
[
1
]),
kerStr
.
c_str
());
if
(
!
k
.
create
(
"filter2DSmall"
,
cv
::
ocl
::
imgproc
::
filter2DSmall_oclsrc
,
build_options
))
return
false
;
}
else
{
localsize
=
localsize_general
;
std
::
vector
<
float
>
kernelMatDataFloat
;
int
kernel_size_y2_aligned
=
_prepareKernelFilter2D
<
float
>
(
kernelMatDataFloat
,
kernelMat
);
String
kerStr
=
ocl
::
kernelToStr
(
kernelMatDataFloat
,
CV_32F
);
for
(
;
;
)
{
size_t
BLOCK_SIZE
=
tryWorkItems
;
while
(
BLOCK_SIZE
>
32
&&
BLOCK_SIZE
>=
(
size_t
)
ksize
.
width
*
2
&&
BLOCK_SIZE
>
(
size_t
)
sz
.
width
*
2
)
BLOCK_SIZE
/=
2
;
if
((
size_t
)
ksize
.
width
>
BLOCK_SIZE
)
return
false
;
int
requiredTop
=
anchor
.
y
;
int
requiredLeft
=
(
int
)
BLOCK_SIZE
;
// not this: anchor.x;
int
requiredBottom
=
ksize
.
height
-
1
-
anchor
.
y
;
int
requiredRight
=
(
int
)
BLOCK_SIZE
;
// not this: ksize.width - 1 - anchor.x;
int
h
=
isolated
?
sz
.
height
:
wholeSize
.
height
;
int
w
=
isolated
?
sz
.
width
:
wholeSize
.
width
;
bool
extra_extrapolation
=
h
<
requiredTop
||
h
<
requiredBottom
||
w
<
requiredLeft
||
w
<
requiredRight
;
if
((
w
<
ksize
.
width
)
||
(
h
<
ksize
.
height
))
return
false
;
String
opts
=
format
(
"-D LOCAL_SIZE=%d -D cn=%d "
"-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d "
"-D KERNEL_SIZE_Y2_ALIGNED=%d -D %s -D %s -D %s%s%s "
"-D srcT=%s -D srcT1=%s -D dstT=%s -D dstT1=%s -D WT=%s -D WT1=%s "
"-D convertToWT=%s -D convertToDstT=%s"
,
(
int
)
BLOCK_SIZE
,
cn
,
anchor
.
x
,
anchor
.
y
,
ksize
.
width
,
ksize
.
height
,
kernel_size_y2_aligned
,
borderMap
[
borderType
],
extra_extrapolation
?
"EXTRA_EXTRAPOLATION"
:
"NO_EXTRA_EXTRAPOLATION"
,
isolated
?
"BORDER_ISOLATED"
:
"NO_BORDER_ISOLATED"
,
doubleSupport
?
" -D DOUBLE_SUPPORT"
:
""
,
kerStr
.
c_str
(),
ocl
::
typeToStr
(
type
),
ocl
::
typeToStr
(
sdepth
),
ocl
::
typeToStr
(
dtype
),
ocl
::
typeToStr
(
ddepth
),
ocl
::
typeToStr
(
wtype
),
ocl
::
typeToStr
(
wdepth
),
ocl
::
convertTypeStr
(
sdepth
,
wdepth
,
cn
,
cvt
[
0
]),
ocl
::
convertTypeStr
(
wdepth
,
ddepth
,
cn
,
cvt
[
1
]));
localsize
[
0
]
=
BLOCK_SIZE
;
globalsize
[
0
]
=
DIVUP
(
sz
.
width
,
BLOCK_SIZE
-
(
ksize
.
width
-
1
))
*
BLOCK_SIZE
;
globalsize
[
1
]
=
sz
.
height
;
if
(
!
k
.
create
(
"filter2D"
,
cv
::
ocl
::
imgproc
::
filter2D_oclsrc
,
opts
))
return
false
;
size_t
kernelWorkGroupSize
=
k
.
workGroupSize
();
if
(
localsize
[
0
]
<=
kernelWorkGroupSize
)
break
;
if
(
BLOCK_SIZE
<
kernelWorkGroupSize
)
return
false
;
tryWorkItems
=
kernelWorkGroupSize
;
}
}
_dst
.
create
(
sz
,
dtype
);
UMat
dst
=
_dst
.
getUMat
();
int
srcOffsetX
=
(
int
)((
src
.
offset
%
src
.
step
)
/
src
.
elemSize
());
int
srcOffsetY
=
(
int
)(
src
.
offset
/
src
.
step
);
int
srcEndX
=
(
isolated
?
(
srcOffsetX
+
sz
.
width
)
:
wholeSize
.
width
);
int
srcEndY
=
(
isolated
?
(
srcOffsetY
+
sz
.
height
)
:
wholeSize
.
height
);
k
.
args
(
ocl
::
KernelArg
::
PtrReadOnly
(
src
),
(
int
)
src
.
step
,
srcOffsetX
,
srcOffsetY
,
srcEndX
,
srcEndY
,
ocl
::
KernelArg
::
WriteOnly
(
dst
),
(
float
)
delta
);
return
k
.
run
(
2
,
globalsize
,
localsize
,
false
);
}
const
int
shift_bits
=
8
;
static
bool
ocl_sepRowFilter2D
(
const
UMat
&
src
,
UMat
&
buf
,
const
Mat
&
kernelX
,
int
anchor
,
int
borderType
,
int
ddepth
,
bool
fast8uc1
,
bool
int_arithm
)
Ptr
<
BaseFilter
>
getLinearFilter
(
int
srcType
,
int
dstType
,
const
Mat
&
_kernel
,
Point
anchor
,
double
delta
,
int
bits
)
{
int
type
=
src
.
type
(),
cn
=
CV_MAT_CN
(
type
),
sdepth
=
CV_MAT_DEPTH
(
type
);
bool
doubleSupport
=
ocl
::
Device
::
getDefault
().
doubleFPConfig
()
>
0
;
Size
bufSize
=
buf
.
size
();
int
buf_type
=
buf
.
type
(),
bdepth
=
CV_MAT_DEPTH
(
buf_type
);
if
(
!
doubleSupport
&&
(
sdepth
==
CV_64F
||
ddepth
==
CV_64F
))
return
false
;
#ifdef __ANDROID__
size_t
localsize
[
2
]
=
{
16
,
10
};
#else
size_t
localsize
[
2
]
=
{
16
,
16
};
#endif
size_t
globalsize
[
2
]
=
{
DIVUP
(
bufSize
.
width
,
localsize
[
0
])
*
localsize
[
0
],
DIVUP
(
bufSize
.
height
,
localsize
[
1
])
*
localsize
[
1
]};
if
(
fast8uc1
)
globalsize
[
0
]
=
DIVUP
((
bufSize
.
width
+
3
)
>>
2
,
localsize
[
0
])
*
localsize
[
0
];
int
radiusX
=
anchor
,
radiusY
=
(
buf
.
rows
-
src
.
rows
)
>>
1
;
bool
isolated
=
(
borderType
&
BORDER_ISOLATED
)
!=
0
;
const
char
*
const
borderMap
[]
=
{
"BORDER_CONSTANT"
,
"BORDER_REPLICATE"
,
"BORDER_REFLECT"
,
"BORDER_WRAP"
,
"BORDER_REFLECT_101"
},
*
const
btype
=
borderMap
[
borderType
&
~
BORDER_ISOLATED
];
bool
extra_extrapolation
=
src
.
rows
<
(
int
)((
-
radiusY
+
globalsize
[
1
])
>>
1
)
+
1
;
extra_extrapolation
|=
src
.
rows
<
radiusY
;
extra_extrapolation
|=
src
.
cols
<
(
int
)((
-
radiusX
+
globalsize
[
0
]
+
8
*
localsize
[
0
]
+
3
)
>>
1
)
+
1
;
extra_extrapolation
|=
src
.
cols
<
radiusX
;
char
cvt
[
40
];
cv
::
String
build_options
=
cv
::
format
(
"-D RADIUSX=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d -D %s -D %s -D %s"
" -D srcT=%s -D dstT=%s -D convertToDstT=%s -D srcT1=%s -D dstT1=%s%s%s"
,
radiusX
,
(
int
)
localsize
[
0
],
(
int
)
localsize
[
1
],
cn
,
btype
,
extra_extrapolation
?
"EXTRA_EXTRAPOLATION"
:
"NO_EXTRA_EXTRAPOLATION"
,
isolated
?
"BORDER_ISOLATED"
:
"NO_BORDER_ISOLATED"
,
ocl
::
typeToStr
(
type
),
ocl
::
typeToStr
(
buf_type
),
ocl
::
convertTypeStr
(
sdepth
,
bdepth
,
cn
,
cvt
),
ocl
::
typeToStr
(
sdepth
),
ocl
::
typeToStr
(
bdepth
),
doubleSupport
?
" -D DOUBLE_SUPPORT"
:
""
,
int_arithm
?
" -D INTEGER_ARITHMETIC"
:
""
);
build_options
+=
ocl
::
kernelToStr
(
kernelX
,
bdepth
);
Size
srcWholeSize
;
Point
srcOffset
;
src
.
locateROI
(
srcWholeSize
,
srcOffset
);
String
kernelName
(
"row_filter"
);
if
(
fast8uc1
)
kernelName
+=
"_C1_D0"
;
ocl
::
Kernel
k
(
kernelName
.
c_str
(),
cv
::
ocl
::
imgproc
::
filterSepRow_oclsrc
,
build_options
);
if
(
k
.
empty
())
return
false
;
if
(
fast8uc1
)
k
.
args
(
ocl
::
KernelArg
::
PtrReadOnly
(
src
),
(
int
)(
src
.
step
/
src
.
elemSize
()),
srcOffset
.
x
,
srcOffset
.
y
,
src
.
cols
,
src
.
rows
,
srcWholeSize
.
width
,
srcWholeSize
.
height
,
ocl
::
KernelArg
::
PtrWriteOnly
(
buf
),
(
int
)(
buf
.
step
/
buf
.
elemSize
()),
buf
.
cols
,
buf
.
rows
,
radiusY
);
else
k
.
args
(
ocl
::
KernelArg
::
PtrReadOnly
(
src
),
(
int
)
src
.
step
,
srcOffset
.
x
,
srcOffset
.
y
,
src
.
cols
,
src
.
rows
,
srcWholeSize
.
width
,
srcWholeSize
.
height
,
ocl
::
KernelArg
::
PtrWriteOnly
(
buf
),
(
int
)
buf
.
step
,
buf
.
cols
,
buf
.
rows
,
radiusY
);
return
k
.
run
(
2
,
globalsize
,
localsize
,
false
);
}
static
bool
ocl_sepColFilter2D
(
const
UMat
&
buf
,
UMat
&
dst
,
const
Mat
&
kernelY
,
double
delta
,
int
anchor
,
bool
int_arithm
)
{
bool
doubleSupport
=
ocl
::
Device
::
getDefault
().
doubleFPConfig
()
>
0
;
if
(
dst
.
depth
()
==
CV_64F
&&
!
doubleSupport
)
return
false
;
#ifdef __ANDROID__
size_t
localsize
[
2
]
=
{
16
,
10
};
#else
size_t
localsize
[
2
]
=
{
16
,
16
};
#endif
size_t
globalsize
[
2
]
=
{
0
,
0
};
int
dtype
=
dst
.
type
(),
cn
=
CV_MAT_CN
(
dtype
),
ddepth
=
CV_MAT_DEPTH
(
dtype
);
Size
sz
=
dst
.
size
();
int
buf_type
=
buf
.
type
(),
bdepth
=
CV_MAT_DEPTH
(
buf_type
);
globalsize
[
1
]
=
DIVUP
(
sz
.
height
,
localsize
[
1
])
*
localsize
[
1
];
globalsize
[
0
]
=
DIVUP
(
sz
.
width
,
localsize
[
0
])
*
localsize
[
0
];
char
cvt
[
40
];
cv
::
String
build_options
=
cv
::
format
(
"-D RADIUSY=%d -D LSIZE0=%d -D LSIZE1=%d -D CN=%d"
" -D srcT=%s -D dstT=%s -D convertToDstT=%s"
" -D srcT1=%s -D dstT1=%s -D SHIFT_BITS=%d%s%s"
,
anchor
,
(
int
)
localsize
[
0
],
(
int
)
localsize
[
1
],
cn
,
ocl
::
typeToStr
(
buf_type
),
ocl
::
typeToStr
(
dtype
),
ocl
::
convertTypeStr
(
bdepth
,
ddepth
,
cn
,
cvt
),
ocl
::
typeToStr
(
bdepth
),
ocl
::
typeToStr
(
ddepth
),
2
*
shift_bits
,
doubleSupport
?
" -D DOUBLE_SUPPORT"
:
""
,
int_arithm
?
" -D INTEGER_ARITHMETIC"
:
""
);
build_options
+=
ocl
::
kernelToStr
(
kernelY
,
bdepth
);
ocl
::
Kernel
k
(
"col_filter"
,
cv
::
ocl
::
imgproc
::
filterSepCol_oclsrc
,
build_options
);
if
(
k
.
empty
())
return
false
;
k
.
args
(
ocl
::
KernelArg
::
ReadOnly
(
buf
),
ocl
::
KernelArg
::
WriteOnly
(
dst
),
static_cast
<
float
>
(
delta
));
return
k
.
run
(
2
,
globalsize
,
localsize
,
false
);
}
const
int
optimizedSepFilterLocalWidth
=
16
;
const
int
optimizedSepFilterLocalHeight
=
8
;
static
bool
ocl_sepFilter2D_SinglePass
(
InputArray
_src
,
OutputArray
_dst
,
Mat
row_kernel
,
Mat
col_kernel
,
double
delta
,
int
borderType
,
int
ddepth
,
int
bdepth
,
bool
int_arithm
)
{
Size
size
=
_src
.
size
(),
wholeSize
;
Point
origin
;
int
stype
=
_src
.
type
(),
sdepth
=
CV_MAT_DEPTH
(
stype
),
cn
=
CV_MAT_CN
(
stype
),
esz
=
CV_ELEM_SIZE
(
stype
),
wdepth
=
std
::
max
(
std
::
max
(
sdepth
,
ddepth
),
bdepth
),
dtype
=
CV_MAKE_TYPE
(
ddepth
,
cn
);
size_t
src_step
=
_src
.
step
(),
src_offset
=
_src
.
offset
();
bool
doubleSupport
=
ocl
::
Device
::
getDefault
().
doubleFPConfig
()
>
0
;
if
(
esz
==
0
||
src_step
==
0
||
(
src_offset
%
src_step
)
%
esz
!=
0
||
(
!
doubleSupport
&&
(
sdepth
==
CV_64F
||
ddepth
==
CV_64F
))
||
!
(
borderType
==
BORDER_CONSTANT
||
borderType
==
BORDER_REPLICATE
||
borderType
==
BORDER_REFLECT
||
borderType
==
BORDER_WRAP
||
borderType
==
BORDER_REFLECT_101
))
return
false
;
size_t
lt2
[
2
]
=
{
optimizedSepFilterLocalWidth
,
optimizedSepFilterLocalHeight
};
size_t
gt2
[
2
]
=
{
lt2
[
0
]
*
(
1
+
(
size
.
width
-
1
)
/
lt2
[
0
]),
lt2
[
1
]};
char
cvt
[
2
][
40
];
const
char
*
const
borderMap
[]
=
{
"BORDER_CONSTANT"
,
"BORDER_REPLICATE"
,
"BORDER_REFLECT"
,
"BORDER_WRAP"
,
"BORDER_REFLECT_101"
};
String
opts
=
cv
::
format
(
"-D BLK_X=%d -D BLK_Y=%d -D RADIUSX=%d -D RADIUSY=%d%s%s"
" -D srcT=%s -D convertToWT=%s -D WT=%s -D dstT=%s -D convertToDstT=%s"
" -D %s -D srcT1=%s -D dstT1=%s -D WT1=%s -D CN=%d -D SHIFT_BITS=%d%s"
,
(
int
)
lt2
[
0
],
(
int
)
lt2
[
1
],
row_kernel
.
cols
/
2
,
col_kernel
.
cols
/
2
,
ocl
::
kernelToStr
(
row_kernel
,
wdepth
,
"KERNEL_MATRIX_X"
).
c_str
(),
ocl
::
kernelToStr
(
col_kernel
,
wdepth
,
"KERNEL_MATRIX_Y"
).
c_str
(),
ocl
::
typeToStr
(
stype
),
ocl
::
convertTypeStr
(
sdepth
,
wdepth
,
cn
,
cvt
[
0
]),
ocl
::
typeToStr
(
CV_MAKE_TYPE
(
wdepth
,
cn
)),
ocl
::
typeToStr
(
dtype
),
ocl
::
convertTypeStr
(
wdepth
,
ddepth
,
cn
,
cvt
[
1
]),
borderMap
[
borderType
],
ocl
::
typeToStr
(
sdepth
),
ocl
::
typeToStr
(
ddepth
),
ocl
::
typeToStr
(
wdepth
),
cn
,
2
*
shift_bits
,
int_arithm
?
" -D INTEGER_ARITHMETIC"
:
""
);
ocl
::
Kernel
k
(
"sep_filter"
,
ocl
::
imgproc
::
filterSep_singlePass_oclsrc
,
opts
);
if
(
k
.
empty
())
return
false
;
UMat
src
=
_src
.
getUMat
();
_dst
.
create
(
size
,
dtype
);
UMat
dst
=
_dst
.
getUMat
();
int
src_offset_x
=
static_cast
<
int
>
((
src_offset
%
src_step
)
/
esz
);
int
src_offset_y
=
static_cast
<
int
>
(
src_offset
/
src_step
);
src
.
locateROI
(
wholeSize
,
origin
);
k
.
args
(
ocl
::
KernelArg
::
PtrReadOnly
(
src
),
(
int
)
src_step
,
src_offset_x
,
src_offset_y
,
wholeSize
.
height
,
wholeSize
.
width
,
ocl
::
KernelArg
::
WriteOnly
(
dst
),
static_cast
<
float
>
(
delta
));
return
k
.
run
(
2
,
gt2
,
lt2
,
false
);
}
bool
ocl_sepFilter2D
(
InputArray
_src
,
OutputArray
_dst
,
int
ddepth
,
InputArray
_kernelX
,
InputArray
_kernelY
,
Point
anchor
,
double
delta
,
int
borderType
)
{
const
ocl
::
Device
&
d
=
ocl
::
Device
::
getDefault
();
Size
imgSize
=
_src
.
size
();
int
type
=
_src
.
type
(),
sdepth
=
CV_MAT_DEPTH
(
type
),
cn
=
CV_MAT_CN
(
type
);
if
(
cn
>
4
)
return
false
;
Mat
kernelX
=
_kernelX
.
getMat
().
reshape
(
1
,
1
);
if
(
kernelX
.
cols
%
2
!=
1
)
return
false
;
Mat
kernelY
=
_kernelY
.
getMat
().
reshape
(
1
,
1
);
if
(
kernelY
.
cols
%
2
!=
1
)
return
false
;
if
(
ddepth
<
0
)
ddepth
=
sdepth
;
if
(
anchor
.
x
<
0
)
anchor
.
x
=
kernelX
.
cols
>>
1
;
if
(
anchor
.
y
<
0
)
anchor
.
y
=
kernelY
.
cols
>>
1
;
int
rtype
=
getKernelType
(
kernelX
,
kernelX
.
rows
==
1
?
Point
(
anchor
.
x
,
0
)
:
Point
(
0
,
anchor
.
x
));
int
ctype
=
getKernelType
(
kernelY
,
kernelY
.
rows
==
1
?
Point
(
anchor
.
y
,
0
)
:
Point
(
0
,
anchor
.
y
));
int
bdepth
=
CV_32F
;
bool
int_arithm
=
false
;
if
(
sdepth
==
CV_8U
&&
ddepth
==
CV_8U
&&
rtype
==
KERNEL_SMOOTH
+
KERNEL_SYMMETRICAL
&&
ctype
==
KERNEL_SMOOTH
+
KERNEL_SYMMETRICAL
)
{
if
(
ocl
::
Device
::
getDefault
().
isIntel
())
{
for
(
int
i
=
0
;
i
<
kernelX
.
cols
;
i
++
)
kernelX
.
at
<
float
>
(
0
,
i
)
=
(
float
)
cvRound
(
kernelX
.
at
<
float
>
(
0
,
i
)
*
(
1
<<
shift_bits
));
if
(
kernelX
.
data
!=
kernelY
.
data
)
for
(
int
i
=
0
;
i
<
kernelX
.
cols
;
i
++
)
kernelY
.
at
<
float
>
(
0
,
i
)
=
(
float
)
cvRound
(
kernelY
.
at
<
float
>
(
0
,
i
)
*
(
1
<<
shift_bits
));
}
else
{
bdepth
=
CV_32S
;
kernelX
.
convertTo
(
kernelX
,
bdepth
,
1
<<
shift_bits
);
kernelY
.
convertTo
(
kernelY
,
bdepth
,
1
<<
shift_bits
);
}
int_arithm
=
true
;
}
CV_OCL_RUN_
(
kernelY
.
cols
<=
21
&&
kernelX
.
cols
<=
21
&&
imgSize
.
width
>
optimizedSepFilterLocalWidth
+
anchor
.
x
&&
imgSize
.
height
>
optimizedSepFilterLocalHeight
+
anchor
.
y
&&
(
!
(
borderType
&
BORDER_ISOLATED
)
||
_src
.
offset
()
==
0
)
&&
anchor
==
Point
(
kernelX
.
cols
>>
1
,
kernelY
.
cols
>>
1
)
&&
OCL_PERFORMANCE_CHECK
(
d
.
isIntel
()),
// TODO FIXIT
ocl_sepFilter2D_SinglePass
(
_src
,
_dst
,
kernelX
,
kernelY
,
delta
,
borderType
&
~
BORDER_ISOLATED
,
ddepth
,
bdepth
,
int_arithm
),
true
)
UMat
src
=
_src
.
getUMat
();
Size
srcWholeSize
;
Point
srcOffset
;
src
.
locateROI
(
srcWholeSize
,
srcOffset
);
bool
fast8uc1
=
type
==
CV_8UC1
&&
srcOffset
.
x
%
4
==
0
&&
src
.
cols
%
4
==
0
&&
src
.
step
%
4
==
0
;
Size
srcSize
=
src
.
size
();
Size
bufSize
(
srcSize
.
width
,
srcSize
.
height
+
kernelY
.
cols
-
1
);
UMat
buf
(
bufSize
,
CV_MAKETYPE
(
bdepth
,
cn
));
if
(
!
ocl_sepRowFilter2D
(
src
,
buf
,
kernelX
,
anchor
.
x
,
borderType
,
ddepth
,
fast8uc1
,
int_arithm
))
return
false
;
_dst
.
create
(
srcSize
,
CV_MAKETYPE
(
ddepth
,
cn
));
UMat
dst
=
_dst
.
getUMat
();
return
ocl_sepColFilter2D
(
buf
,
dst
,
kernelY
,
delta
,
anchor
.
y
,
int_arithm
);
}
#endif
}
CV_INSTRUMENT_REGION
();
cv
::
Ptr
<
cv
::
BaseFilter
>
cv
::
getLinearFilter
(
int
srcType
,
int
dstType
,
InputArray
filter_kernel
,
Point
anchor
,
double
delta
,
int
bits
)
{
Mat
_kernel
=
filter_kernel
.
getMat
();
int
sdepth
=
CV_MAT_DEPTH
(
srcType
),
ddepth
=
CV_MAT_DEPTH
(
dstType
);
int
cn
=
CV_MAT_CN
(
srcType
),
kdepth
=
_kernel
.
depth
();
CV_Assert
(
cn
==
CV_MAT_CN
(
dstType
)
&&
ddepth
>=
sdepth
);
...
...
@@ -3806,476 +3091,6 @@ cv::Ptr<cv::BaseFilter> cv::getLinearFilter(int srcType, int dstType,
srcType
,
dstType
));
}
cv
::
Ptr
<
cv
::
FilterEngine
>
cv
::
createLinearFilter
(
int
_srcType
,
int
_dstType
,
InputArray
filter_kernel
,
Point
_anchor
,
double
_delta
,
int
_rowBorderType
,
int
_columnBorderType
,
const
Scalar
&
_borderValue
)
{
Mat
_kernel
=
filter_kernel
.
getMat
();
_srcType
=
CV_MAT_TYPE
(
_srcType
);
_dstType
=
CV_MAT_TYPE
(
_dstType
);
int
cn
=
CV_MAT_CN
(
_srcType
);
CV_Assert
(
cn
==
CV_MAT_CN
(
_dstType
)
);
Mat
kernel
=
_kernel
;
int
bits
=
0
;
/*int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType);
int ktype = _kernel.depth() == CV_32S ? KERNEL_INTEGER : getKernelType(_kernel, _anchor);
if( sdepth == CV_8U && (ddepth == CV_8U || ddepth == CV_16S) &&
_kernel.rows*_kernel.cols <= (1 << 10) )
{
bits = (ktype & KERNEL_INTEGER) ? 0 : 11;
_kernel.convertTo(kernel, CV_32S, 1 << bits);
}*/
Ptr
<
BaseFilter
>
_filter2D
=
getLinearFilter
(
_srcType
,
_dstType
,
kernel
,
_anchor
,
_delta
,
bits
);
return
makePtr
<
FilterEngine
>
(
_filter2D
,
Ptr
<
BaseRowFilter
>
(),
Ptr
<
BaseColumnFilter
>
(),
_srcType
,
_dstType
,
_srcType
,
_rowBorderType
,
_columnBorderType
,
_borderValue
);
}
//================================================================
// HAL interface
//================================================================
using
namespace
cv
;
static
bool
replacementFilter2D
(
int
stype
,
int
dtype
,
int
kernel_type
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
width
,
int
height
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernel_data
,
size_t
kernel_step
,
int
kernel_width
,
int
kernel_height
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
,
bool
isSubmatrix
)
{
cvhalFilter2D
*
ctx
;
int
res
=
cv_hal_filterInit
(
&
ctx
,
kernel_data
,
kernel_step
,
kernel_type
,
kernel_width
,
kernel_height
,
width
,
height
,
stype
,
dtype
,
borderType
,
delta
,
anchor_x
,
anchor_y
,
isSubmatrix
,
src_data
==
dst_data
);
if
(
res
!=
CV_HAL_ERROR_OK
)
return
false
;
res
=
cv_hal_filter
(
ctx
,
src_data
,
src_step
,
dst_data
,
dst_step
,
width
,
height
,
full_width
,
full_height
,
offset_x
,
offset_y
);
bool
success
=
(
res
==
CV_HAL_ERROR_OK
);
res
=
cv_hal_filterFree
(
ctx
);
if
(
res
!=
CV_HAL_ERROR_OK
)
return
false
;
return
success
;
}
#ifdef HAVE_IPP
static
bool
ippFilter2D
(
int
stype
,
int
dtype
,
int
kernel_type
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
width
,
int
height
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernel_data
,
size_t
kernel_step
,
int
kernel_width
,
int
kernel_height
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
,
bool
isSubmatrix
)
{
#ifdef HAVE_IPP_IW
CV_INSTRUMENT_REGION_IPP
();
::
ipp
::
IwiSize
iwSize
(
width
,
height
);
::
ipp
::
IwiSize
kernelSize
(
kernel_width
,
kernel_height
);
IppDataType
type
=
ippiGetDataType
(
CV_MAT_DEPTH
(
stype
));
int
channels
=
CV_MAT_CN
(
stype
);
CV_UNUSED
(
isSubmatrix
);
#if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 <= 201702 // IPP bug with 1x1 kernel
if
(
kernel_width
==
1
&&
kernel_height
==
1
)
return
false
;
#endif
#if IPP_DISABLE_FILTER2D_BIG_MASK
// Too big difference compared to OpenCV FFT-based convolution
if
(
kernel_type
==
CV_32FC1
&&
(
type
==
ipp16s
||
type
==
ipp16u
)
&&
(
kernel_width
>
7
||
kernel_height
>
7
))
return
false
;
// Poor optimization for big kernels
if
(
kernel_width
>
7
||
kernel_height
>
7
)
return
false
;
#endif
if
(
src_data
==
dst_data
)
return
false
;
if
(
stype
!=
dtype
)
return
false
;
if
(
kernel_type
!=
CV_16SC1
&&
kernel_type
!=
CV_32FC1
)
return
false
;
// TODO: Implement offset for 8u, 16u
if
(
std
::
fabs
(
delta
)
>=
DBL_EPSILON
)
return
false
;
if
(
!
ippiCheckAnchor
(
anchor_x
,
anchor_y
,
kernel_width
,
kernel_height
))
return
false
;
try
{
::
ipp
::
IwiBorderSize
iwBorderSize
;
::
ipp
::
IwiBorderType
iwBorderType
;
::
ipp
::
IwiImage
iwKernel
(
ippiSize
(
kernel_width
,
kernel_height
),
ippiGetDataType
(
CV_MAT_DEPTH
(
kernel_type
)),
CV_MAT_CN
(
kernel_type
),
0
,
(
void
*
)
kernel_data
,
kernel_step
);
::
ipp
::
IwiImage
iwSrc
(
iwSize
,
type
,
channels
,
::
ipp
::
IwiBorderSize
(
offset_x
,
offset_y
,
full_width
-
offset_x
-
width
,
full_height
-
offset_y
-
height
),
(
void
*
)
src_data
,
src_step
);
::
ipp
::
IwiImage
iwDst
(
iwSize
,
type
,
channels
,
::
ipp
::
IwiBorderSize
(
offset_x
,
offset_y
,
full_width
-
offset_x
-
width
,
full_height
-
offset_y
-
height
),
(
void
*
)
dst_data
,
dst_step
);
iwBorderSize
=
::
ipp
::
iwiSizeToBorderSize
(
kernelSize
);
iwBorderType
=
ippiGetBorder
(
iwSrc
,
borderType
,
iwBorderSize
);
if
(
!
iwBorderType
)
return
false
;
CV_INSTRUMENT_FUN_IPP
(
::
ipp
::
iwiFilter
,
iwSrc
,
iwDst
,
iwKernel
,
::
ipp
::
IwiFilterParams
(
1
,
0
,
ippAlgHintNone
,
ippRndFinancial
),
iwBorderType
);
}
catch
(
const
::
ipp
::
IwException
&
ex
)
{
CV_UNUSED
(
ex
);
return
false
;
}
return
true
;
#else
CV_UNUSED
(
stype
);
CV_UNUSED
(
dtype
);
CV_UNUSED
(
kernel_type
);
CV_UNUSED
(
src_data
);
CV_UNUSED
(
src_step
);
CV_UNUSED
(
dst_data
);
CV_UNUSED
(
dst_step
);
CV_UNUSED
(
width
);
CV_UNUSED
(
height
);
CV_UNUSED
(
full_width
);
CV_UNUSED
(
full_height
);
CV_UNUSED
(
offset_x
);
CV_UNUSED
(
offset_y
);
CV_UNUSED
(
kernel_data
);
CV_UNUSED
(
kernel_step
);
CV_UNUSED
(
kernel_width
);
CV_UNUSED
(
kernel_height
);
CV_UNUSED
(
anchor_x
);
CV_UNUSED
(
anchor_y
);
CV_UNUSED
(
delta
);
CV_UNUSED
(
borderType
);
CV_UNUSED
(
isSubmatrix
);
return
false
;
#endif
}
#endif
static
bool
dftFilter2D
(
int
stype
,
int
dtype
,
int
kernel_type
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernel_data
,
size_t
kernel_step
,
int
kernel_width
,
int
kernel_height
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
)
{
{
int
sdepth
=
CV_MAT_DEPTH
(
stype
);
int
ddepth
=
CV_MAT_DEPTH
(
dtype
);
int
dft_filter_size
=
checkHardwareSupport
(
CV_CPU_SSE3
)
&&
((
sdepth
==
CV_8U
&&
(
ddepth
==
CV_8U
||
ddepth
==
CV_16S
))
||
(
sdepth
==
CV_32F
&&
ddepth
==
CV_32F
))
?
130
:
50
;
if
(
kernel_width
*
kernel_height
<
dft_filter_size
)
return
false
;
}
Point
anchor
=
Point
(
anchor_x
,
anchor_y
);
Mat
kernel
=
Mat
(
Size
(
kernel_width
,
kernel_height
),
kernel_type
,
kernel_data
,
kernel_step
);
Mat
src
(
Size
(
full_width
-
offset_x
,
full_height
-
offset_y
),
stype
,
src_data
,
src_step
);
Mat
dst
(
Size
(
full_width
,
full_height
),
dtype
,
dst_data
,
dst_step
);
Mat
temp
;
int
src_channels
=
CV_MAT_CN
(
stype
);
int
dst_channels
=
CV_MAT_CN
(
dtype
);
int
ddepth
=
CV_MAT_DEPTH
(
dtype
);
// crossCorr doesn't accept non-zero delta with multiple channels
if
(
src_channels
!=
1
&&
delta
!=
0
)
{
// The semantics of filter2D require that the delta be applied
// as floating-point math. So wee need an intermediate Mat
// with a float datatype. If the dest is already floats,
// we just use that.
int
corrDepth
=
ddepth
;
if
((
ddepth
==
CV_32F
||
ddepth
==
CV_64F
)
&&
src_data
!=
dst_data
)
{
temp
=
Mat
(
Size
(
full_width
,
full_height
),
dtype
,
dst_data
,
dst_step
);
}
else
{
corrDepth
=
ddepth
==
CV_64F
?
CV_64F
:
CV_32F
;
temp
.
create
(
Size
(
full_width
,
full_height
),
CV_MAKETYPE
(
corrDepth
,
dst_channels
));
}
crossCorr
(
src
,
kernel
,
temp
,
src
.
size
(),
CV_MAKETYPE
(
corrDepth
,
src_channels
),
anchor
,
0
,
borderType
);
add
(
temp
,
delta
,
temp
);
if
(
temp
.
data
!=
dst_data
)
{
temp
.
convertTo
(
dst
,
dst
.
type
());
}
}
else
{
if
(
src_data
!=
dst_data
)
temp
=
Mat
(
Size
(
full_width
,
full_height
),
dtype
,
dst_data
,
dst_step
);
else
temp
.
create
(
Size
(
full_width
,
full_height
),
dtype
);
crossCorr
(
src
,
kernel
,
temp
,
src
.
size
(),
CV_MAKETYPE
(
ddepth
,
src_channels
),
anchor
,
delta
,
borderType
);
if
(
temp
.
data
!=
dst_data
)
temp
.
copyTo
(
dst
);
}
return
true
;
}
static
void
ocvFilter2D
(
int
stype
,
int
dtype
,
int
kernel_type
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
width
,
int
height
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernel_data
,
size_t
kernel_step
,
int
kernel_width
,
int
kernel_height
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
)
{
int
borderTypeValue
=
borderType
&
~
BORDER_ISOLATED
;
Mat
kernel
=
Mat
(
Size
(
kernel_width
,
kernel_height
),
kernel_type
,
kernel_data
,
kernel_step
);
Ptr
<
FilterEngine
>
f
=
createLinearFilter
(
stype
,
dtype
,
kernel
,
Point
(
anchor_x
,
anchor_y
),
delta
,
borderTypeValue
);
Mat
src
(
Size
(
width
,
height
),
stype
,
src_data
,
src_step
);
Mat
dst
(
Size
(
width
,
height
),
dtype
,
dst_data
,
dst_step
);
f
->
apply
(
src
,
dst
,
Size
(
full_width
,
full_height
),
Point
(
offset_x
,
offset_y
));
}
static
bool
replacementSepFilter
(
int
stype
,
int
dtype
,
int
ktype
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
width
,
int
height
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernelx_data
,
int
kernelx_len
,
uchar
*
kernely_data
,
int
kernely_len
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
)
{
cvhalFilter2D
*
ctx
;
int
res
=
cv_hal_sepFilterInit
(
&
ctx
,
stype
,
dtype
,
ktype
,
kernelx_data
,
kernelx_len
,
kernely_data
,
kernely_len
,
anchor_x
,
anchor_y
,
delta
,
borderType
);
if
(
res
!=
CV_HAL_ERROR_OK
)
return
false
;
res
=
cv_hal_sepFilter
(
ctx
,
src_data
,
src_step
,
dst_data
,
dst_step
,
width
,
height
,
full_width
,
full_height
,
offset_x
,
offset_y
);
bool
success
=
(
res
==
CV_HAL_ERROR_OK
);
res
=
cv_hal_sepFilterFree
(
ctx
);
if
(
res
!=
CV_HAL_ERROR_OK
)
return
false
;
return
success
;
}
static
void
ocvSepFilter
(
int
stype
,
int
dtype
,
int
ktype
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
width
,
int
height
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernelx_data
,
int
kernelx_len
,
uchar
*
kernely_data
,
int
kernely_len
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
)
{
Mat
kernelX
(
Size
(
kernelx_len
,
1
),
ktype
,
kernelx_data
);
Mat
kernelY
(
Size
(
kernely_len
,
1
),
ktype
,
kernely_data
);
Ptr
<
FilterEngine
>
f
=
createSeparableLinearFilter
(
stype
,
dtype
,
kernelX
,
kernelY
,
Point
(
anchor_x
,
anchor_y
),
delta
,
borderType
&
~
BORDER_ISOLATED
);
Mat
src
(
Size
(
width
,
height
),
stype
,
src_data
,
src_step
);
Mat
dst
(
Size
(
width
,
height
),
dtype
,
dst_data
,
dst_step
);
f
->
apply
(
src
,
dst
,
Size
(
full_width
,
full_height
),
Point
(
offset_x
,
offset_y
));
};
//===================================================================
// HAL functions
//===================================================================
namespace
cv
{
namespace
hal
{
CV_DEPRECATED
Ptr
<
hal
::
Filter2D
>
Filter2D
::
create
(
uchar
*
,
size_t
,
int
,
int
,
int
,
int
,
int
,
int
,
int
,
int
,
double
,
int
,
int
,
bool
,
bool
)
{
return
Ptr
<
hal
::
Filter2D
>
();
}
CV_DEPRECATED
Ptr
<
hal
::
SepFilter2D
>
SepFilter2D
::
create
(
int
,
int
,
int
,
uchar
*
,
int
,
uchar
*
,
int
,
int
,
int
,
double
,
int
)
{
return
Ptr
<
hal
::
SepFilter2D
>
();
}
void
filter2D
(
int
stype
,
int
dtype
,
int
kernel_type
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
width
,
int
height
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernel_data
,
size_t
kernel_step
,
int
kernel_width
,
int
kernel_height
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
,
bool
isSubmatrix
)
{
bool
res
;
res
=
replacementFilter2D
(
stype
,
dtype
,
kernel_type
,
src_data
,
src_step
,
dst_data
,
dst_step
,
width
,
height
,
full_width
,
full_height
,
offset_x
,
offset_y
,
kernel_data
,
kernel_step
,
kernel_width
,
kernel_height
,
anchor_x
,
anchor_y
,
delta
,
borderType
,
isSubmatrix
);
if
(
res
)
return
;
CV_IPP_RUN_FAST
(
ippFilter2D
(
stype
,
dtype
,
kernel_type
,
src_data
,
src_step
,
dst_data
,
dst_step
,
width
,
height
,
full_width
,
full_height
,
offset_x
,
offset_y
,
kernel_data
,
kernel_step
,
kernel_width
,
kernel_height
,
anchor_x
,
anchor_y
,
delta
,
borderType
,
isSubmatrix
))
res
=
dftFilter2D
(
stype
,
dtype
,
kernel_type
,
src_data
,
src_step
,
dst_data
,
dst_step
,
full_width
,
full_height
,
offset_x
,
offset_y
,
kernel_data
,
kernel_step
,
kernel_width
,
kernel_height
,
anchor_x
,
anchor_y
,
delta
,
borderType
);
if
(
res
)
return
;
ocvFilter2D
(
stype
,
dtype
,
kernel_type
,
src_data
,
src_step
,
dst_data
,
dst_step
,
width
,
height
,
full_width
,
full_height
,
offset_x
,
offset_y
,
kernel_data
,
kernel_step
,
kernel_width
,
kernel_height
,
anchor_x
,
anchor_y
,
delta
,
borderType
);
}
//---------------------------------------------------------------
void
sepFilter2D
(
int
stype
,
int
dtype
,
int
ktype
,
uchar
*
src_data
,
size_t
src_step
,
uchar
*
dst_data
,
size_t
dst_step
,
int
width
,
int
height
,
int
full_width
,
int
full_height
,
int
offset_x
,
int
offset_y
,
uchar
*
kernelx_data
,
int
kernelx_len
,
uchar
*
kernely_data
,
int
kernely_len
,
int
anchor_x
,
int
anchor_y
,
double
delta
,
int
borderType
)
{
bool
res
=
replacementSepFilter
(
stype
,
dtype
,
ktype
,
src_data
,
src_step
,
dst_data
,
dst_step
,
width
,
height
,
full_width
,
full_height
,
offset_x
,
offset_y
,
kernelx_data
,
kernelx_len
,
kernely_data
,
kernely_len
,
anchor_x
,
anchor_y
,
delta
,
borderType
);
if
(
res
)
return
;
ocvSepFilter
(
stype
,
dtype
,
ktype
,
src_data
,
src_step
,
dst_data
,
dst_step
,
width
,
height
,
full_width
,
full_height
,
offset_x
,
offset_y
,
kernelx_data
,
kernelx_len
,
kernely_data
,
kernely_len
,
anchor_x
,
anchor_y
,
delta
,
borderType
);
}
}
// cv::hal::
}
// cv::
//================================================================
// Main interface
//================================================================
void
cv
::
filter2D
(
InputArray
_src
,
OutputArray
_dst
,
int
ddepth
,
InputArray
_kernel
,
Point
anchor0
,
double
delta
,
int
borderType
)
{
CV_INSTRUMENT_REGION
();
CV_OCL_RUN
(
_dst
.
isUMat
()
&&
_src
.
dims
()
<=
2
,
ocl_filter2D
(
_src
,
_dst
,
ddepth
,
_kernel
,
anchor0
,
delta
,
borderType
))
Mat
src
=
_src
.
getMat
(),
kernel
=
_kernel
.
getMat
();
if
(
ddepth
<
0
)
ddepth
=
src
.
depth
();
_dst
.
create
(
src
.
size
(),
CV_MAKETYPE
(
ddepth
,
src
.
channels
())
);
Mat
dst
=
_dst
.
getMat
();
Point
anchor
=
normalizeAnchor
(
anchor0
,
kernel
.
size
());
Point
ofs
;
Size
wsz
(
src
.
cols
,
src
.
rows
);
if
(
(
borderType
&
BORDER_ISOLATED
)
==
0
)
src
.
locateROI
(
wsz
,
ofs
);
hal
::
filter2D
(
src
.
type
(),
dst
.
type
(),
kernel
.
type
(),
src
.
data
,
src
.
step
,
dst
.
data
,
dst
.
step
,
dst
.
cols
,
dst
.
rows
,
wsz
.
width
,
wsz
.
height
,
ofs
.
x
,
ofs
.
y
,
kernel
.
data
,
kernel
.
step
,
kernel
.
cols
,
kernel
.
rows
,
anchor
.
x
,
anchor
.
y
,
delta
,
borderType
,
src
.
isSubmatrix
());
}
void
cv
::
sepFilter2D
(
InputArray
_src
,
OutputArray
_dst
,
int
ddepth
,
InputArray
_kernelX
,
InputArray
_kernelY
,
Point
anchor
,
double
delta
,
int
borderType
)
{
CV_INSTRUMENT_REGION
();
CV_OCL_RUN
(
_dst
.
isUMat
()
&&
_src
.
dims
()
<=
2
&&
(
size_t
)
_src
.
rows
()
>
_kernelY
.
total
()
&&
(
size_t
)
_src
.
cols
()
>
_kernelX
.
total
(),
ocl_sepFilter2D
(
_src
,
_dst
,
ddepth
,
_kernelX
,
_kernelY
,
anchor
,
delta
,
borderType
))
Mat
src
=
_src
.
getMat
(),
kernelX
=
_kernelX
.
getMat
(),
kernelY
=
_kernelY
.
getMat
();
if
(
ddepth
<
0
)
ddepth
=
src
.
depth
();
_dst
.
create
(
src
.
size
(),
CV_MAKETYPE
(
ddepth
,
src
.
channels
())
);
Mat
dst
=
_dst
.
getMat
();
Point
ofs
;
Size
wsz
(
src
.
cols
,
src
.
rows
);
if
(
(
borderType
&
BORDER_ISOLATED
)
==
0
)
src
.
locateROI
(
wsz
,
ofs
);
CV_Assert
(
kernelX
.
type
()
==
kernelY
.
type
()
&&
(
kernelX
.
cols
==
1
||
kernelX
.
rows
==
1
)
&&
(
kernelY
.
cols
==
1
||
kernelY
.
rows
==
1
)
);
Mat
contKernelX
=
kernelX
.
isContinuous
()
?
kernelX
:
kernelX
.
clone
();
Mat
contKernelY
=
kernelY
.
isContinuous
()
?
kernelY
:
kernelY
.
clone
();
hal
::
sepFilter2D
(
src
.
type
(),
dst
.
type
(),
kernelX
.
type
(),
src
.
data
,
src
.
step
,
dst
.
data
,
dst
.
step
,
dst
.
cols
,
dst
.
rows
,
wsz
.
width
,
wsz
.
height
,
ofs
.
x
,
ofs
.
y
,
contKernelX
.
data
,
kernelX
.
cols
+
kernelX
.
rows
-
1
,
contKernelY
.
data
,
kernelY
.
cols
+
kernelY
.
rows
-
1
,
anchor
.
x
,
anchor
.
y
,
delta
,
borderType
&
~
BORDER_ISOLATED
);
}
CV_IMPL
void
cvFilter2D
(
const
CvArr
*
srcarr
,
CvArr
*
dstarr
,
const
CvMat
*
_kernel
,
CvPoint
anchor
)
{
cv
::
Mat
src
=
cv
::
cvarrToMat
(
srcarr
),
dst
=
cv
::
cvarrToMat
(
dstarr
);
cv
::
Mat
kernel
=
cv
::
cvarrToMat
(
_kernel
);
CV_Assert
(
src
.
size
()
==
dst
.
size
()
&&
src
.
channels
()
==
dst
.
channels
()
);
cv
::
filter2D
(
src
,
dst
,
dst
.
depth
(),
kernel
,
anchor
,
0
,
cv
::
BORDER_REPLICATE
);
}
/* End of file. */
CV_CPU_OPTIMIZATION_NAMESPACE_END
}
// namespace
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