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
070393df
Commit
070393df
authored
Jun 04, 2018
by
Dmitry Kurtaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uint8 inputs for deep learning networks
parent
6c4f618d
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
408 additions
and
76 deletions
+408
-76
dnn.hpp
modules/dnn/include/opencv2/dnn/dnn.hpp
+23
-13
dnn.cpp
modules/dnn/src/dnn.cpp
+224
-38
op_inf_engine.cpp
modules/dnn/src/op_inf_engine.cpp
+41
-9
op_inf_engine.hpp
modules/dnn/src/op_inf_engine.hpp
+7
-3
test_halide_layers.cpp
modules/dnn/test/test_halide_layers.cpp
+4
-6
test_layers.cpp
modules/dnn/test/test_layers.cpp
+69
-7
test_misc.cpp
modules/dnn/test/test_misc.cpp
+40
-0
No files found.
modules/dnn/include/opencv2/dnn/dnn.hpp
View file @
070393df
...
...
@@ -46,9 +46,9 @@
#include <opencv2/core.hpp>
#if !defined CV_DOXYGEN && !defined CV_DNN_DONT_ADD_EXPERIMENTAL_NS
#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_v
5
{
#define CV__DNN_EXPERIMENTAL_NS_BEGIN namespace experimental_dnn_v
6
{
#define CV__DNN_EXPERIMENTAL_NS_END }
namespace
cv
{
namespace
dnn
{
namespace
experimental_dnn_v
5
{
}
using
namespace
experimental_dnn_v5
;
}}
namespace
cv
{
namespace
dnn
{
namespace
experimental_dnn_v
6
{
}
using
namespace
experimental_dnn_v6
;
}}
#else
#define CV__DNN_EXPERIMENTAL_NS_BEGIN
#define CV__DNN_EXPERIMENTAL_NS_END
...
...
@@ -487,14 +487,19 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
*/
CV_WRAP
void
setPreferableTarget
(
int
targetId
);
/** @brief Sets the new value for the layer output blob
* @param name descriptor of the updating layer output blob.
* @param blob new blob.
/** @brief Sets the new input value for the network
* @param blob A new blob. Should have CV_32F or CV_8U depth.
* @param name A name of input layer.
* @param scalefactor An optional normalization scale.
* @param mean An optional mean subtraction values.
* @see connect(String, String) to know format of the descriptor.
* @note If updating blob is not empty then @p blob must have the same shape,
* because network reshaping is not implemented yet.
*
* If scale or mean values are specified, a final input blob is computed
* as:
* \f[input(n,c,h,w) = scalefactor \times (blob(n,c,h,w) - mean_c)\f]
*/
CV_WRAP
void
setInput
(
InputArray
blob
,
const
String
&
name
=
""
);
CV_WRAP
void
setInput
(
InputArray
blob
,
const
String
&
name
=
""
,
double
scalefactor
=
1.0
,
const
Scalar
&
mean
=
Scalar
());
/** @brief Sets the new value for the learned param of the layer.
* @param layer name or id of the layer.
...
...
@@ -805,13 +810,15 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @param swapRB flag which indicates that swap first and last channels
* in 3-channel image is necessary.
* @param crop flag which indicates whether image will be cropped after resize or not
* @param ddepth Depth of output blob. Choose CV_32F or CV_8U.
* @details if @p crop is true, input image is resized so one side after resize is equal to corresponding
* dimension in @p size and another one is equal or larger. Then, crop from the center is performed.
* If @p crop is false, direct resize without cropping and preserving aspect ratio is performed.
* @returns 4-dimensional Mat with NCHW dimensions order.
*/
CV_EXPORTS_W
Mat
blobFromImage
(
InputArray
image
,
double
scalefactor
=
1.0
,
const
Size
&
size
=
Size
(),
const
Scalar
&
mean
=
Scalar
(),
bool
swapRB
=
true
,
bool
crop
=
true
);
const
Scalar
&
mean
=
Scalar
(),
bool
swapRB
=
true
,
bool
crop
=
true
,
int
ddepth
=
CV_32F
);
/** @brief Creates 4-dimensional blob from image.
* @details This is an overloaded member function, provided for convenience.
...
...
@@ -819,7 +826,7 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
*/
CV_EXPORTS
void
blobFromImage
(
InputArray
image
,
OutputArray
blob
,
double
scalefactor
=
1.0
,
const
Size
&
size
=
Size
(),
const
Scalar
&
mean
=
Scalar
(),
bool
swapRB
=
true
,
bool
crop
=
true
);
bool
swapRB
=
true
,
bool
crop
=
true
,
int
ddepth
=
CV_32F
);
/** @brief Creates 4-dimensional blob from series of images. Optionally resizes and
...
...
@@ -833,13 +840,15 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
* @param swapRB flag which indicates that swap first and last channels
* in 3-channel image is necessary.
* @param crop flag which indicates whether image will be cropped after resize or not
* @param ddepth Depth of output blob. Choose CV_32F or CV_8U.
* @details if @p crop is true, input image is resized so one side after resize is equal to corresponding
* dimension in @p size and another one is equal or larger. Then, crop from the center is performed.
* If @p crop is false, direct resize without cropping and preserving aspect ratio is performed.
* @returns 4-dim
a
nsional Mat with NCHW dimensions order.
* @returns 4-dim
e
nsional Mat with NCHW dimensions order.
*/
CV_EXPORTS_W
Mat
blobFromImages
(
InputArrayOfArrays
images
,
double
scalefactor
=
1.0
,
Size
size
=
Size
(),
const
Scalar
&
mean
=
Scalar
(),
bool
swapRB
=
true
,
bool
crop
=
true
);
Size
size
=
Size
(),
const
Scalar
&
mean
=
Scalar
(),
bool
swapRB
=
true
,
bool
crop
=
true
,
int
ddepth
=
CV_32F
);
/** @brief Creates 4-dimensional blob from series of images.
* @details This is an overloaded member function, provided for convenience.
...
...
@@ -847,7 +856,8 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
*/
CV_EXPORTS
void
blobFromImages
(
InputArrayOfArrays
images
,
OutputArray
blob
,
double
scalefactor
=
1.0
,
Size
size
=
Size
(),
const
Scalar
&
mean
=
Scalar
(),
bool
swapRB
=
true
,
bool
crop
=
true
);
const
Scalar
&
mean
=
Scalar
(),
bool
swapRB
=
true
,
bool
crop
=
true
,
int
ddepth
=
CV_32F
);
/** @brief Parse a 4D blob and output the images it contains as 2D arrays through a simpler data structure
* (std::vector<cv::Mat>).
...
...
modules/dnn/src/dnn.cpp
View file @
070393df
...
...
@@ -97,35 +97,42 @@ namespace
}
Mat
blobFromImage
(
InputArray
image
,
double
scalefactor
,
const
Size
&
size
,
const
Scalar
&
mean
,
bool
swapRB
,
bool
crop
)
const
Scalar
&
mean
,
bool
swapRB
,
bool
crop
,
int
ddepth
)
{
CV_TRACE_FUNCTION
();
Mat
blob
;
blobFromImage
(
image
,
blob
,
scalefactor
,
size
,
mean
,
swapRB
,
crop
);
blobFromImage
(
image
,
blob
,
scalefactor
,
size
,
mean
,
swapRB
,
crop
,
ddepth
);
return
blob
;
}
void
blobFromImage
(
InputArray
image
,
OutputArray
blob
,
double
scalefactor
,
const
Size
&
size
,
const
Scalar
&
mean
,
bool
swapRB
,
bool
crop
)
const
Size
&
size
,
const
Scalar
&
mean
,
bool
swapRB
,
bool
crop
,
int
ddepth
)
{
CV_TRACE_FUNCTION
();
std
::
vector
<
Mat
>
images
(
1
,
image
.
getMat
());
blobFromImages
(
images
,
blob
,
scalefactor
,
size
,
mean
,
swapRB
,
crop
);
blobFromImages
(
images
,
blob
,
scalefactor
,
size
,
mean
,
swapRB
,
crop
,
ddepth
);
}
Mat
blobFromImages
(
InputArrayOfArrays
images
,
double
scalefactor
,
Size
size
,
const
Scalar
&
mean
,
bool
swapRB
,
bool
crop
)
const
Scalar
&
mean
,
bool
swapRB
,
bool
crop
,
int
ddepth
)
{
CV_TRACE_FUNCTION
();
Mat
blob
;
blobFromImages
(
images
,
blob
,
scalefactor
,
size
,
mean
,
swapRB
,
crop
);
blobFromImages
(
images
,
blob
,
scalefactor
,
size
,
mean
,
swapRB
,
crop
,
ddepth
);
return
blob
;
}
void
blobFromImages
(
InputArrayOfArrays
images_
,
OutputArray
blob_
,
double
scalefactor
,
Size
size
,
const
Scalar
&
mean_
,
bool
swapRB
,
bool
crop
)
Size
size
,
const
Scalar
&
mean_
,
bool
swapRB
,
bool
crop
,
int
ddepth
)
{
CV_TRACE_FUNCTION
();
CV_CheckType
(
ddepth
,
ddepth
==
CV_32F
||
ddepth
==
CV_8U
,
"Blob depth should be CV_32F or CV_8U"
);
if
(
ddepth
==
CV_8U
)
{
CV_CheckEQ
(
scalefactor
,
1.0
,
"Scaling is not supported for CV_8U blob depth"
);
CV_Assert
(
mean_
==
Scalar
(),
"Mean subtraction is not supported for CV_8U blob depth"
);
}
std
::
vector
<
Mat
>
images
;
images_
.
getMatVector
(
images
);
CV_Assert
(
!
images
.
empty
());
...
...
@@ -149,7 +156,7 @@ void blobFromImages(InputArrayOfArrays images_, OutputArray blob_, double scalef
else
resize
(
images
[
i
],
images
[
i
],
size
,
0
,
0
,
INTER_LINEAR
);
}
if
(
images
[
i
].
depth
()
==
CV_8U
)
if
(
images
[
i
].
depth
()
==
CV_8U
&&
ddepth
==
CV_32F
)
images
[
i
].
convertTo
(
images
[
i
],
CV_32F
);
Scalar
mean
=
mean_
;
if
(
swapRB
)
...
...
@@ -167,20 +174,20 @@ void blobFromImages(InputArrayOfArrays images_, OutputArray blob_, double scalef
if
(
nch
==
3
||
nch
==
4
)
{
int
sz
[]
=
{
(
int
)
nimages
,
nch
,
image0
.
rows
,
image0
.
cols
};
blob_
.
create
(
4
,
sz
,
CV_32F
);
blob_
.
create
(
4
,
sz
,
ddepth
);
Mat
blob
=
blob_
.
getMat
();
Mat
ch
[
4
];
for
(
i
=
0
;
i
<
nimages
;
i
++
)
{
image
=
images
[
i
];
CV_Assert
(
image
.
depth
()
==
CV_32F
);
CV_Assert
(
image
.
depth
()
==
blob_
.
depth
()
);
nch
=
image
.
channels
();
CV_Assert
(
image
.
dims
==
2
&&
(
nch
==
3
||
nch
==
4
));
CV_Assert
(
image
.
size
()
==
image0
.
size
());
for
(
int
j
=
0
;
j
<
nch
;
j
++
)
ch
[
j
]
=
Mat
(
image
.
rows
,
image
.
cols
,
CV_32F
,
blob
.
ptr
((
int
)
i
,
j
));
ch
[
j
]
=
Mat
(
image
.
rows
,
image
.
cols
,
ddepth
,
blob
.
ptr
((
int
)
i
,
j
));
if
(
swapRB
)
std
::
swap
(
ch
[
0
],
ch
[
2
]);
split
(
image
,
ch
);
...
...
@@ -190,18 +197,18 @@ void blobFromImages(InputArrayOfArrays images_, OutputArray blob_, double scalef
{
CV_Assert
(
nch
==
1
);
int
sz
[]
=
{
(
int
)
nimages
,
1
,
image0
.
rows
,
image0
.
cols
};
blob_
.
create
(
4
,
sz
,
CV_32F
);
blob_
.
create
(
4
,
sz
,
ddepth
);
Mat
blob
=
blob_
.
getMat
();
for
(
i
=
0
;
i
<
nimages
;
i
++
)
{
Mat
image
=
images
[
i
];
CV_Assert
(
image
.
depth
()
==
CV_32F
);
CV_Assert
(
image
.
depth
()
==
blob_
.
depth
()
);
nch
=
image
.
channels
();
CV_Assert
(
image
.
dims
==
2
&&
(
nch
==
1
));
CV_Assert
(
image
.
size
()
==
image0
.
size
());
image
.
copyTo
(
Mat
(
image
.
rows
,
image
.
cols
,
CV_32F
,
blob
.
ptr
((
int
)
i
,
0
)));
image
.
copyTo
(
Mat
(
image
.
rows
,
image
.
cols
,
ddepth
,
blob
.
ptr
((
int
)
i
,
0
)));
}
}
}
...
...
@@ -408,7 +415,16 @@ struct LayerData
//fake layer containing network input blobs
struct
DataLayer
:
public
Layer
{
void
finalize
(
const
std
::
vector
<
Mat
*>&
,
std
::
vector
<
Mat
>&
)
CV_OVERRIDE
{}
DataLayer
()
:
Layer
()
{
skip
=
false
;
}
virtual
bool
supportBackend
(
int
backendId
)
CV_OVERRIDE
{
return
backendId
==
DNN_BACKEND_OPENCV
||
backendId
==
DNN_BACKEND_INFERENCE_ENGINE
&&
inputsData
.
size
()
==
1
;
}
void
forward
(
InputArrayOfArrays
inputs
,
OutputArrayOfArrays
outputs
,
OutputArrayOfArrays
internals
)
CV_OVERRIDE
{
...
...
@@ -423,11 +439,36 @@ struct DataLayer : public Layer
void
forward
(
std
::
vector
<
Mat
*>&
,
std
::
vector
<
Mat
>&
outputs
,
std
::
vector
<
Mat
>
&
)
CV_OVERRIDE
{
// Supported modes:
// | Input type | Output type |
// | fp32 | fp32 |
// | uint8 | fp32 |
for
(
int
i
=
0
;
i
<
inputsData
.
size
();
++
i
)
{
if
(
inputsData
[
i
].
type
()
==
CV_32F
&&
outputs
[
i
].
type
()
==
CV_16S
)
double
scale
=
scaleFactors
[
i
];
Scalar
&
mean
=
means
[
i
];
CV_Assert
(
mean
==
Scalar
()
||
inputsData
[
i
].
size
[
1
]
<=
4
,
outputs
[
i
].
type
()
==
CV_32F
);
bool
singleMean
=
true
;
for
(
int
j
=
1
;
j
<
std
::
min
(
4
,
inputsData
[
i
].
size
[
1
])
&&
singleMean
;
++
j
)
{
convertFp16
(
inputsData
[
i
],
outputs
[
i
]);
singleMean
=
mean
[
j
]
==
mean
[
j
-
1
];
}
if
(
singleMean
)
{
inputsData
[
i
].
convertTo
(
outputs
[
i
],
CV_32F
,
scale
,
-
mean
[
0
]
*
scale
);
}
else
{
for
(
int
n
=
0
;
n
<
inputsData
[
i
].
size
[
0
];
++
n
)
for
(
int
c
=
0
;
c
<
inputsData
[
i
].
size
[
1
];
++
c
)
{
Mat
inp
=
getPlane
(
inputsData
[
i
],
n
,
c
);
Mat
out
=
getPlane
(
outputs
[
i
],
n
,
c
);
inp
.
convertTo
(
out
,
CV_32F
,
scale
,
-
mean
[
c
]
*
scale
);
}
}
}
}
...
...
@@ -435,13 +476,66 @@ struct DataLayer : public Layer
#ifdef HAVE_OPENCL
bool
forward_ocl
(
InputArrayOfArrays
,
OutputArrayOfArrays
outputs_
,
OutputArrayOfArrays
internals_
)
{
if
(
outputs_
.
depth
()
==
CV_16S
)
// Supported modes:
// | Input type | Output type |
// | fp32 | fp32 |
// | fp32 | fp16 |
// | uint8 | fp32 |
std
::
vector
<
UMat
>
outputs
;
outputs_
.
getUMatVector
(
outputs
);
for
(
int
i
=
0
;
i
<
inputsData
.
size
();
++
i
)
{
std
::
vector
<
UMat
>
outputs
;
outputs_
.
getUMatVector
(
outputs
);
for
(
int
i
=
0
;
i
<
inputsData
.
size
();
++
i
)
double
scale
=
scaleFactors
[
i
];
Scalar
&
mean
=
means
[
i
];
CV_Assert
(
mean
==
Scalar
()
||
inputsData
[
i
].
size
[
1
]
<=
4
);
bool
singleMean
=
true
;
for
(
int
j
=
1
;
j
<
std
::
min
(
4
,
inputsData
[
i
].
size
[
1
])
&&
singleMean
;
++
j
)
{
convertFp16
(
inputsData
[
i
],
outputs
[
i
]);
singleMean
=
mean
[
j
]
==
mean
[
j
-
1
];
}
if
(
outputs_
.
depth
()
==
CV_16S
)
{
if
(
singleMean
)
convertFp16
(
scale
*
(
inputsData
[
i
]
-
mean
[
0
]),
outputs
[
i
]);
else
{
for
(
int
n
=
0
;
n
<
inputsData
[
i
].
size
[
0
];
++
n
)
for
(
int
c
=
0
;
c
<
inputsData
[
i
].
size
[
1
];
++
c
)
{
Mat
inp
=
getPlane
(
inputsData
[
i
],
n
,
c
);
std
::
vector
<
cv
::
Range
>
plane
(
4
,
Range
::
all
());
plane
[
0
]
=
Range
(
n
,
n
+
1
);
plane
[
1
]
=
Range
(
c
,
c
+
1
);
UMat
out
=
outputs
[
i
](
plane
).
reshape
(
1
,
inp
.
dims
,
inp
.
size
);
convertFp16
(
scale
*
(
inp
-
mean
[
c
]),
out
);
}
}
}
else
{
CV_Assert
(
outputs_
.
depth
()
==
CV_32F
);
if
(
singleMean
)
inputsData
[
i
].
convertTo
(
outputs
[
i
],
CV_32F
,
scale
,
-
mean
[
0
]
*
scale
);
else
{
for
(
int
n
=
0
;
n
<
inputsData
[
i
].
size
[
0
];
++
n
)
for
(
int
c
=
0
;
c
<
inputsData
[
i
].
size
[
1
];
++
c
)
{
Mat
inp
=
getPlane
(
inputsData
[
i
],
n
,
c
);
std
::
vector
<
cv
::
Range
>
plane
(
4
,
Range
::
all
());
plane
[
0
]
=
Range
(
n
,
n
+
1
);
plane
[
1
]
=
Range
(
c
,
c
+
1
);
UMat
out
=
outputs
[
i
](
plane
).
reshape
(
1
,
inp
.
dims
,
inp
.
size
);
inp
.
convertTo
(
out
,
CV_32F
,
scale
,
-
mean
[
c
]
*
scale
);
}
}
}
}
return
true
;
...
...
@@ -469,8 +563,61 @@ struct DataLayer : public Layer
return
false
;
}
void
finalize
(
const
std
::
vector
<
Mat
*>&
,
std
::
vector
<
Mat
>&
outputs
)
CV_OVERRIDE
{
CV_Assert
(
outputs
.
size
()
==
scaleFactors
.
size
(),
outputs
.
size
()
==
means
.
size
(),
inputsData
.
size
()
==
outputs
.
size
());
skip
=
true
;
for
(
int
i
=
0
;
skip
&&
i
<
inputsData
.
size
();
++
i
)
{
if
(
inputsData
[
i
].
data
!=
outputs
[
i
].
data
||
scaleFactors
[
i
]
!=
1.0
||
means
[
i
]
!=
Scalar
())
skip
=
false
;
}
}
virtual
Ptr
<
BackendNode
>
initInfEngine
(
const
std
::
vector
<
Ptr
<
BackendWrapper
>
>&
)
CV_OVERRIDE
{
#ifdef HAVE_INF_ENGINE
InferenceEngine
::
LayerParams
lp
;
lp
.
name
=
name
;
lp
.
type
=
"ScaleShift"
;
lp
.
precision
=
InferenceEngine
::
Precision
::
FP32
;
std
::
shared_ptr
<
InferenceEngine
::
ScaleShiftLayer
>
ieLayer
(
new
InferenceEngine
::
ScaleShiftLayer
(
lp
));
CV_Assert
(
inputsData
.
size
()
==
1
,
inputsData
[
0
].
dims
==
4
);
const
size_t
numChannels
=
inputsData
[
0
].
size
[
1
];
CV_Assert
(
numChannels
<=
4
);
// Scale
auto
weights
=
InferenceEngine
::
make_shared_blob
<
float
>
(
InferenceEngine
::
Precision
::
FP32
,
{
numChannels
});
weights
->
allocate
();
weights
->
set
(
std
::
vector
<
float
>
(
numChannels
,
scaleFactors
[
0
]));
ieLayer
->
_weights
=
weights
;
// Mean subtraction
auto
biases
=
InferenceEngine
::
make_shared_blob
<
float
>
(
InferenceEngine
::
Precision
::
FP32
,
{
numChannels
});
biases
->
allocate
();
std
::
vector
<
float
>
biasesVec
(
numChannels
);
for
(
int
i
=
0
;
i
<
numChannels
;
++
i
)
{
biasesVec
[
i
]
=
-
means
[
0
][
i
]
*
scaleFactors
[
0
];
}
biases
->
set
(
biasesVec
);
ieLayer
->
_biases
=
biases
;
return
Ptr
<
BackendNode
>
(
new
InfEngineBackendNode
(
ieLayer
));
#endif // HAVE_INF_ENGINE
return
Ptr
<
BackendNode
>
();
}
std
::
vector
<
String
>
outNames
;
// Preprocessing parameters for each network's input.
std
::
vector
<
double
>
scaleFactors
;
std
::
vector
<
Scalar
>
means
;
std
::
vector
<
Mat
>
inputsData
;
bool
skip
;
};
struct
BlobManager
...
...
@@ -739,7 +886,7 @@ struct Net::Impl
netInputLayer
=
Ptr
<
DataLayer
>
(
new
DataLayer
());
LayerData
&
inpl
=
layers
.
insert
(
make_pair
(
0
,
LayerData
())
).
first
->
second
;
inpl
.
id
=
0
;
inpl
.
name
=
"_input"
;
netInputLayer
->
name
=
inpl
.
name
=
"_input"
;
inpl
.
type
=
"__NetInputLayer__"
;
inpl
.
layerInstance
=
netInputLayer
;
layerNameToId
.
insert
(
std
::
make_pair
(
inpl
.
name
,
inpl
.
id
));
...
...
@@ -930,6 +1077,11 @@ struct Net::Impl
clear
();
allocateLayers
(
blobsToKeep_
);
MapIdToLayerData
::
iterator
it
=
layers
.
find
(
0
);
CV_Assert
(
it
!=
layers
.
end
());
it
->
second
.
skip
=
netInputLayer
->
skip
;
initBackend
();
if
(
!
netWasAllocated
)
...
...
@@ -1179,6 +1331,29 @@ struct Net::Impl
MapIdToLayerData
::
iterator
it
;
Ptr
<
InfEngineBackendNet
>
net
;
for
(
it
=
layers
.
begin
();
it
!=
layers
.
end
();
++
it
)
{
LayerData
&
ld
=
it
->
second
;
if
(
ld
.
id
==
0
)
{
CV_Assert
((
netInputLayer
->
outNames
.
empty
()
&&
ld
.
outputBlobsWrappers
.
size
()
==
1
)
||
(
netInputLayer
->
outNames
.
size
()
==
ld
.
outputBlobsWrappers
.
size
()));
for
(
int
i
=
0
;
i
<
ld
.
outputBlobsWrappers
.
size
();
++
i
)
{
InferenceEngine
::
DataPtr
dataPtr
=
infEngineDataNode
(
ld
.
outputBlobsWrappers
[
i
]);
dataPtr
->
name
=
netInputLayer
->
outNames
.
empty
()
?
ld
.
name
:
netInputLayer
->
outNames
[
i
];
}
}
else
{
for
(
int
i
=
0
;
i
<
ld
.
outputBlobsWrappers
.
size
();
++
i
)
{
InferenceEngine
::
DataPtr
dataPtr
=
infEngineDataNode
(
ld
.
outputBlobsWrappers
[
i
]);
dataPtr
->
name
=
ld
.
name
;
}
}
}
if
(
skipInfEngineInit
)
{
Ptr
<
BackendNode
>
node
=
layers
[
lastLayerId
].
backendNodes
[
preferableBackend
];
...
...
@@ -1190,11 +1365,21 @@ struct Net::Impl
for
(
it
=
layers
.
begin
();
it
!=
layers
.
end
();
++
it
)
{
LayerData
&
ld
=
it
->
second
;
for
(
int
i
=
0
;
i
<
ld
.
outputBlobsWrappers
.
size
();
++
i
)
if
(
ld
.
id
==
0
)
{
InferenceEngine
::
DataPtr
dataPtr
=
infEngineDataNode
(
ld
.
outputBlobsWrappers
[
i
]);
dataPtr
->
name
=
ld
.
id
==
0
?
netInputLayer
->
outNames
[
i
]
:
ld
.
name
;
for
(
int
i
=
0
;
i
<
ld
.
inputBlobsWrappers
.
size
();
++
i
)
{
InferenceEngine
::
DataPtr
dataPtr
=
infEngineDataNode
(
ld
.
inputBlobsWrappers
[
i
]);
dataPtr
->
name
=
netInputLayer
->
outNames
[
i
];
}
}
else
{
for
(
int
i
=
0
;
i
<
ld
.
outputBlobsWrappers
.
size
();
++
i
)
{
InferenceEngine
::
DataPtr
dataPtr
=
infEngineDataNode
(
ld
.
outputBlobsWrappers
[
i
]);
dataPtr
->
name
=
ld
.
name
;
}
}
ieNode
->
net
->
addBlobs
(
ld
.
inputBlobsWrappers
);
ieNode
->
net
->
addBlobs
(
ld
.
outputBlobsWrappers
);
...
...
@@ -1210,11 +1395,11 @@ struct Net::Impl
// some of layers is not implemented.
// Set of all input and output blobs wrappers for current network.
std
::
map
<
int
,
Ptr
<
BackendWrapper
>
>
netBlobsWrappers
;
std
::
map
<
LayerPin
,
Ptr
<
BackendWrapper
>
>
netBlobsWrappers
;
for
(
it
=
layers
.
begin
();
it
!=
layers
.
end
();
++
it
)
{
LayerData
&
ld
=
it
->
second
;
if
(
ld
.
id
==
0
)
if
(
ld
.
id
==
0
&&
ld
.
skip
)
continue
;
bool
fused
=
ld
.
skip
;
...
...
@@ -1251,20 +1436,17 @@ struct Net::Impl
// So we need to rewrap all the external blobs.
for
(
int
i
=
0
;
i
<
ld
.
inputBlobsId
.
size
();
++
i
)
{
int
lid
=
ld
.
inputBlobsId
[
i
].
lid
;
LayerData
&
inpLd
=
layers
[
lid
];
auto
it
=
netBlobsWrappers
.
find
(
lid
);
LayerPin
inPin
=
ld
.
inputBlobsId
[
i
];
auto
it
=
netBlobsWrappers
.
find
(
inPin
);
if
(
it
==
netBlobsWrappers
.
end
())
{
ld
.
inputBlobsWrappers
[
i
]
=
wrap
(
*
ld
.
inputBlobs
[
i
]);
auto
dataPtr
=
infEngineDataNode
(
ld
.
inputBlobsWrappers
[
i
]);
dataPtr
->
name
=
inpLd
.
name
;
netBlobsWrappers
[
lid
]
=
ld
.
inputBlobsWrappers
[
i
];
ld
.
inputBlobsWrappers
[
i
]
=
InfEngineBackendWrapper
::
create
(
ld
.
inputBlobsWrappers
[
i
]);
netBlobsWrappers
[
inPin
]
=
ld
.
inputBlobsWrappers
[
i
];
}
else
ld
.
inputBlobsWrappers
[
i
]
=
it
->
second
;
}
netBlobsWrappers
[
ld
.
id
]
=
ld
.
outputBlobsWrappers
[
0
];
netBlobsWrappers
[
LayerPin
(
ld
.
id
,
0
)
]
=
ld
.
outputBlobsWrappers
[
0
];
Ptr
<
BackendNode
>
node
;
if
(
!
net
.
empty
())
...
...
@@ -2343,7 +2525,7 @@ void Net::setInputsNames(const std::vector<String> &inputBlobNames)
impl
->
netInputLayer
->
setNames
(
inputBlobNames
);
}
void
Net
::
setInput
(
InputArray
blob
,
const
String
&
name
)
void
Net
::
setInput
(
InputArray
blob
,
const
String
&
name
,
double
scalefactor
,
const
Scalar
&
mean
)
{
CV_TRACE_FUNCTION
();
CV_TRACE_ARG_VALUE
(
name
,
"name"
,
name
.
c_str
());
...
...
@@ -2360,6 +2542,8 @@ void Net::setInput(InputArray blob, const String& name)
ld
.
outputBlobs
.
resize
(
numInputs
);
ld
.
outputBlobsWrappers
.
resize
(
numInputs
);
impl
->
netInputLayer
->
inputsData
.
resize
(
numInputs
);
impl
->
netInputLayer
->
scaleFactors
.
resize
(
numInputs
);
impl
->
netInputLayer
->
means
.
resize
(
numInputs
);
MatShape
prevShape
=
shape
(
impl
->
netInputLayer
->
inputsData
[
pin
.
oid
]);
Mat
blob_
=
blob
.
getMat
();
...
...
@@ -2378,6 +2562,8 @@ void Net::setInput(InputArray blob, const String& name)
{
ld
.
outputBlobsWrappers
[
pin
.
oid
]
->
setHostDirty
();
}
impl
->
netInputLayer
->
scaleFactors
[
pin
.
oid
]
=
scalefactor
;
impl
->
netInputLayer
->
means
[
pin
.
oid
]
=
mean
;
impl
->
netWasAllocated
=
impl
->
netWasAllocated
&&
oldShape
;
}
...
...
modules/dnn/src/op_inf_engine.cpp
View file @
070393df
...
...
@@ -68,19 +68,32 @@ static InferenceEngine::DataPtr wrapToInfEngineDataNode(const Mat& m, const std:
{
std
::
vector
<
size_t
>
reversedShape
(
&
m
.
size
[
0
],
&
m
.
size
[
0
]
+
m
.
dims
);
std
::
reverse
(
reversedShape
.
begin
(),
reversedShape
.
end
());
return
InferenceEngine
::
DataPtr
(
new
InferenceEngine
::
Data
(
name
,
reversedShape
,
InferenceEngine
::
Precision
::
FP32
,
estimateLayout
(
m
))
);
if
(
m
.
type
()
==
CV_32F
)
return
InferenceEngine
::
DataPtr
(
new
InferenceEngine
::
Data
(
name
,
reversedShape
,
InferenceEngine
::
Precision
::
FP32
,
estimateLayout
(
m
))
);
else
if
(
m
.
type
()
==
CV_8U
)
return
InferenceEngine
::
DataPtr
(
new
InferenceEngine
::
Data
(
name
,
reversedShape
,
InferenceEngine
::
Precision
::
U8
,
estimateLayout
(
m
))
);
else
CV_Error
(
Error
::
StsNotImplemented
,
format
(
"Unsupported data type %d"
,
m
.
type
()));
}
InferenceEngine
::
TBlob
<
float
>
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
const
std
::
vector
<
size_t
>&
shape
,
InferenceEngine
::
Layout
layout
)
InferenceEngine
::
Blob
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
const
std
::
vector
<
size_t
>&
shape
,
InferenceEngine
::
Layout
layout
)
{
return
InferenceEngine
::
make_shared_blob
<
float
>
(
InferenceEngine
::
Precision
::
FP32
,
layout
,
shape
,
(
float
*
)
m
.
data
);
if
(
m
.
type
()
==
CV_32F
)
return
InferenceEngine
::
make_shared_blob
<
float
>
(
InferenceEngine
::
Precision
::
FP32
,
layout
,
shape
,
(
float
*
)
m
.
data
);
else
if
(
m
.
type
()
==
CV_8U
)
return
InferenceEngine
::
make_shared_blob
<
uint8_t
>
(
InferenceEngine
::
Precision
::
U8
,
layout
,
shape
,
(
uint8_t
*
)
m
.
data
);
else
CV_Error
(
Error
::
StsNotImplemented
,
format
(
"Unsupported data type %d"
,
m
.
type
()));
}
InferenceEngine
::
TBlob
<
float
>
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
InferenceEngine
::
Layout
layout
)
InferenceEngine
::
Blob
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
InferenceEngine
::
Layout
layout
)
{
std
::
vector
<
size_t
>
reversedShape
(
&
m
.
size
[
0
],
&
m
.
size
[
0
]
+
m
.
dims
);
std
::
reverse
(
reversedShape
.
begin
(),
reversedShape
.
end
());
...
...
@@ -102,6 +115,24 @@ InfEngineBackendWrapper::InfEngineBackendWrapper(int targetId, const cv::Mat& m)
blob
=
wrapToInfEngineBlob
(
m
,
estimateLayout
(
m
));
}
InfEngineBackendWrapper
::
InfEngineBackendWrapper
(
Ptr
<
BackendWrapper
>
wrapper
)
:
BackendWrapper
(
DNN_BACKEND_INFERENCE_ENGINE
,
wrapper
->
targetId
)
{
Ptr
<
InfEngineBackendWrapper
>
ieWrapper
=
wrapper
.
dynamicCast
<
InfEngineBackendWrapper
>
();
CV_Assert
(
!
ieWrapper
.
empty
());
InferenceEngine
::
DataPtr
srcData
=
ieWrapper
->
dataPtr
;
dataPtr
=
InferenceEngine
::
DataPtr
(
new
InferenceEngine
::
Data
(
srcData
->
name
,
srcData
->
dims
,
srcData
->
precision
,
srcData
->
layout
)
);
blob
=
ieWrapper
->
blob
;
}
Ptr
<
BackendWrapper
>
InfEngineBackendWrapper
::
create
(
Ptr
<
BackendWrapper
>
wrapper
)
{
return
Ptr
<
BackendWrapper
>
(
new
InfEngineBackendWrapper
(
wrapper
));
}
InfEngineBackendWrapper
::~
InfEngineBackendWrapper
()
{
...
...
@@ -329,6 +360,7 @@ void InfEngineBackendNet::init(int targetId)
{
CV_Assert
(
allBlobs
.
find
(
it
.
first
)
!=
allBlobs
.
end
());
inpBlobs
[
it
.
first
]
=
allBlobs
[
it
.
first
];
it
.
second
->
setPrecision
(
inpBlobs
[
it
.
first
]
->
precision
());
}
// Set up output blobs.
...
...
@@ -427,7 +459,7 @@ void InfEngineBackendNet::addBlobs(const std::vector<Ptr<BackendWrapper> >& ptrs
auto
wrappers
=
infEngineWrappers
(
ptrs
);
for
(
const
auto
&
wrapper
:
wrappers
)
{
allBlobs
[
wrapper
->
dataPtr
->
name
]
=
wrapper
->
blob
;
allBlobs
.
insert
({
wrapper
->
dataPtr
->
name
,
wrapper
->
blob
})
;
}
}
...
...
modules/dnn/src/op_inf_engine.hpp
View file @
070393df
...
...
@@ -115,19 +115,23 @@ class InfEngineBackendWrapper : public BackendWrapper
public
:
InfEngineBackendWrapper
(
int
targetId
,
const
Mat
&
m
);
InfEngineBackendWrapper
(
Ptr
<
BackendWrapper
>
wrapper
);
~
InfEngineBackendWrapper
();
static
Ptr
<
BackendWrapper
>
create
(
Ptr
<
BackendWrapper
>
wrapper
);
virtual
void
copyToHost
()
CV_OVERRIDE
;
virtual
void
setHostDirty
()
CV_OVERRIDE
;
InferenceEngine
::
DataPtr
dataPtr
;
InferenceEngine
::
TBlob
<
float
>
::
Ptr
blob
;
InferenceEngine
::
Blob
::
Ptr
blob
;
};
InferenceEngine
::
TBlob
<
float
>
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
InferenceEngine
::
Layout
layout
=
InferenceEngine
::
Layout
::
ANY
);
InferenceEngine
::
Blob
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
InferenceEngine
::
Layout
layout
=
InferenceEngine
::
Layout
::
ANY
);
InferenceEngine
::
TBlob
<
float
>
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
const
std
::
vector
<
size_t
>&
shape
,
InferenceEngine
::
Layout
layout
);
InferenceEngine
::
Blob
::
Ptr
wrapToInfEngineBlob
(
const
Mat
&
m
,
const
std
::
vector
<
size_t
>&
shape
,
InferenceEngine
::
Layout
layout
);
InferenceEngine
::
DataPtr
infEngineDataNode
(
const
Ptr
<
BackendWrapper
>&
ptr
);
...
...
modules/dnn/test/test_halide_layers.cpp
View file @
070393df
...
...
@@ -107,12 +107,10 @@ TEST_P(Convolution, Accuracy)
if
(
backendId
==
DNN_BACKEND_INFERENCE_ENGINE
&&
targetId
==
DNN_TARGET_MYRIAD
)
throw
SkipTestException
(
""
);
// TODO: unstable test cases
if
(
backendId
==
DNN_BACKEND_OPENCV
&&
(
targetId
==
DNN_TARGET_OPENCL
||
targetId
==
DNN_TARGET_OPENCL_FP16
)
&&
inChannels
==
6
&&
outChannels
==
9
&&
group
==
1
&&
inSize
==
Size
(
5
,
6
)
&&
kernel
==
Size
(
3
,
1
)
&&
stride
==
Size
(
1
,
1
)
&&
pad
==
Size
(
0
,
1
)
&&
dilation
==
Size
(
1
,
1
)
&&
hasBias
)
throw
SkipTestException
(
""
);
if
(
cvtest
::
skipUnstableTests
&&
backendId
==
DNN_BACKEND_OPENCV
&&
(
targetId
==
DNN_TARGET_OPENCL
||
targetId
==
DNN_TARGET_OPENCL_FP16
)
&&
kernel
==
Size
(
3
,
1
)
&&
stride
==
Size
(
1
,
1
)
&&
pad
==
Size
(
0
,
1
))
throw
SkipTestException
(
"Skip unstable test"
);
int
sz
[]
=
{
outChannels
,
inChannels
/
group
,
kernel
.
height
,
kernel
.
width
};
Mat
weights
(
4
,
&
sz
[
0
],
CV_32F
);
...
...
modules/dnn/test/test_layers.cpp
View file @
070393df
...
...
@@ -291,7 +291,7 @@ TEST_P(Test_Caffe_layers, Fused_Concat)
TEST_P
(
Test_Caffe_layers
,
Eltwise
)
{
if
(
backend
==
DNN_BACKEND_INFERENCE_ENGINE
)
if
(
backend
==
DNN_BACKEND_INFERENCE_ENGINE
&&
target
==
DNN_TARGET_MYRIAD
)
throw
SkipTestException
(
""
);
testLayerUsingCaffeModels
(
"layer_eltwise"
);
}
...
...
@@ -939,6 +939,25 @@ TEST(Layer_Test_Convolution_DLDT, Accuracy)
ASSERT_EQ
(
net
.
getLayer
(
outLayers
[
0
])
->
type
,
"Concat"
);
}
TEST
(
Layer_Test_Convolution_DLDT
,
setInput_uint8
)
{
Mat
inp
=
blobFromNPY
(
_tf
(
"blob.npy"
));
Mat
inputs
[]
=
{
Mat
(
inp
.
dims
,
inp
.
size
,
CV_8U
),
Mat
()};
randu
(
inputs
[
0
],
0
,
255
);
inputs
[
0
].
convertTo
(
inputs
[
1
],
CV_32F
);
Mat
outs
[
2
];
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
Net
net
=
readNet
(
_tf
(
"layer_convolution.xml"
),
_tf
(
"layer_convolution.bin"
));
net
.
setInput
(
inputs
[
i
]);
outs
[
i
]
=
net
.
forward
();
ASSERT_EQ
(
outs
[
i
].
type
(),
CV_32F
);
}
normAssert
(
outs
[
0
],
outs
[
1
]);
}
// 1. Create a .prototxt file with the following network:
// layer {
// type: "Input" name: "data" top: "data"
...
...
@@ -961,22 +980,65 @@ TEST(Layer_Test_Convolution_DLDT, Accuracy)
// net.save('/path/to/caffemodel')
//
// 3. Convert using ModelOptimizer.
TEST
(
Test_DLDT
,
two_inputs
)
typedef
testing
::
TestWithParam
<
tuple
<
int
,
int
>
>
Test_DLDT_two_inputs
;
TEST_P
(
Test_DLDT_two_inputs
,
as_IR
)
{
int
firstInpType
=
get
<
0
>
(
GetParam
());
int
secondInpType
=
get
<
1
>
(
GetParam
());
// TODO: It looks like a bug in Inference Engine.
if
(
secondInpType
==
CV_8U
)
throw
SkipTestException
(
""
);
Net
net
=
readNet
(
_tf
(
"net_two_inputs.xml"
),
_tf
(
"net_two_inputs.bin"
));
int
inpSize
[]
=
{
1
,
2
,
3
};
Mat
firstInp
(
3
,
&
inpSize
[
0
],
CV_32F
);
Mat
secondInp
(
3
,
&
inpSize
[
0
],
CV_32F
);
randu
(
firstInp
,
-
1
,
1
);
randu
(
secondInp
,
-
1
,
1
);
Mat
firstInp
(
3
,
&
inpSize
[
0
],
firstInpType
);
Mat
secondInp
(
3
,
&
inpSize
[
0
],
secondInpType
);
randu
(
firstInp
,
0
,
255
);
randu
(
secondInp
,
0
,
255
);
net
.
setInput
(
firstInp
,
"data"
);
net
.
setInput
(
secondInp
,
"second_input"
);
Mat
out
=
net
.
forward
();
normAssert
(
out
,
firstInp
+
secondInp
);
Mat
ref
;
cv
::
add
(
firstInp
,
secondInp
,
ref
,
Mat
(),
CV_32F
);
normAssert
(
out
,
ref
);
}
TEST_P
(
Test_DLDT_two_inputs
,
as_backend
)
{
static
const
float
kScale
=
0.5
f
;
static
const
float
kScaleInv
=
1.0
f
/
kScale
;
Net
net
;
LayerParams
lp
;
lp
.
type
=
"Eltwise"
;
lp
.
name
=
"testLayer"
;
lp
.
set
(
"operation"
,
"sum"
);
int
eltwiseId
=
net
.
addLayerToPrev
(
lp
.
name
,
lp
.
type
,
lp
);
// connect to a first input
net
.
connect
(
0
,
1
,
eltwiseId
,
1
);
// connect to a second input
int
inpSize
[]
=
{
1
,
2
,
3
};
Mat
firstInp
(
3
,
&
inpSize
[
0
],
get
<
0
>
(
GetParam
()));
Mat
secondInp
(
3
,
&
inpSize
[
0
],
get
<
1
>
(
GetParam
()));
randu
(
firstInp
,
0
,
255
);
randu
(
secondInp
,
0
,
255
);
net
.
setInputsNames
({
"data"
,
"second_input"
});
net
.
setInput
(
firstInp
,
"data"
,
kScale
);
net
.
setInput
(
secondInp
,
"second_input"
,
kScaleInv
);
net
.
setPreferableBackend
(
DNN_BACKEND_INFERENCE_ENGINE
);
Mat
out
=
net
.
forward
();
Mat
ref
;
addWeighted
(
firstInp
,
kScale
,
secondInp
,
kScaleInv
,
0
,
ref
,
CV_32F
);
normAssert
(
out
,
ref
);
}
INSTANTIATE_TEST_CASE_P
(
/*nothing*/
,
Test_DLDT_two_inputs
,
Combine
(
Values
(
CV_8U
,
CV_32F
),
Values
(
CV_8U
,
CV_32F
)
));
class
UnsupportedLayer
:
public
Layer
{
public
:
...
...
modules/dnn/test/test_misc.cpp
View file @
070393df
...
...
@@ -138,4 +138,44 @@ TEST(LayerFactory, custom_layers)
LayerFactory
::
unregisterLayer
(
"CustomType"
);
}
typedef
testing
::
TestWithParam
<
tuple
<
float
,
Vec3f
,
int
,
tuple
<
Backend
,
Target
>
>
>
setInput
;
TEST_P
(
setInput
,
normalization
)
{
const
float
kScale
=
get
<
0
>
(
GetParam
());
const
Scalar
kMean
=
get
<
1
>
(
GetParam
());
const
int
dtype
=
get
<
2
>
(
GetParam
());
const
int
backend
=
get
<
0
>
(
get
<
3
>
(
GetParam
()));
const
int
target
=
get
<
1
>
(
get
<
3
>
(
GetParam
()));
const
bool
kSwapRB
=
true
;
if
(
backend
==
DNN_BACKEND_INFERENCE_ENGINE
&&
target
==
DNN_TARGET_MYRIAD
&&
!
checkMyriadTarget
())
throw
SkipTestException
(
"Myriad is not available/disabled in OpenCV"
);
if
(
backend
==
DNN_BACKEND_OPENCV
&&
target
==
DNN_TARGET_OPENCL_FP16
&&
dtype
!=
CV_32F
)
throw
SkipTestException
(
""
);
Mat
inp
(
5
,
5
,
CV_8UC3
);
randu
(
inp
,
0
,
255
);
Mat
ref
=
blobFromImage
(
inp
,
kScale
,
Size
(),
kMean
,
kSwapRB
,
/*crop*/
false
);
LayerParams
lp
;
Net
net
;
net
.
addLayerToPrev
(
"testLayer"
,
"Identity"
,
lp
);
net
.
setPreferableBackend
(
backend
);
net
.
setPreferableTarget
(
target
);
Mat
blob
=
blobFromImage
(
inp
,
1.0
,
Size
(),
Scalar
(),
kSwapRB
,
/*crop*/
false
,
dtype
);
ASSERT_EQ
(
blob
.
type
(),
dtype
);
net
.
setInput
(
blob
,
""
,
kScale
,
kMean
);
Mat
out
=
net
.
forward
();
ASSERT_EQ
(
out
.
type
(),
CV_32F
);
normAssert
(
ref
,
out
,
""
,
4e-4
,
1e-3
);
}
INSTANTIATE_TEST_CASE_P
(
/**/
,
setInput
,
Combine
(
Values
(
1.0
f
,
1.0
/
127.5
),
Values
(
Vec3f
(),
Vec3f
(
50
,
50
,
50
),
Vec3f
(
10
,
50
,
140
)),
Values
(
CV_32F
,
CV_8U
),
dnnBackendsAndTargets
()
));
}}
// 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