Skip to content

Commit 7b22448

Browse files
kallaballaIskXCr
authored andcommitted
Merge pull request opencv#23894 from kallaballa:blobFromImagesWithParams
Pertaining Issue: opencv#5697 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
1 parent 468e39d commit 7b22448

File tree

2 files changed

+155
-36
lines changed

2 files changed

+155
-36
lines changed

modules/dnn/src/dnn_utils.cpp

Lines changed: 140 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,48 @@ Image2BlobParams::Image2BlobParams(const Scalar& scalefactor_, const Size& size_
2222
datalayout(datalayout_), paddingmode(mode_)
2323
{}
2424

25+
void getVector(InputArrayOfArrays images_, std::vector<Mat>& images) {
26+
images_.getMatVector(images);
27+
}
28+
29+
void getVector(InputArrayOfArrays images_, std::vector<UMat>& images) {
30+
images_.getUMatVector(images);
31+
}
32+
33+
void getMat(UMat& blob, InputArray blob_, AccessFlag flag) {
34+
if(blob_.kind() == _InputArray::UMAT)
35+
blob = blob_.getUMat();
36+
else if(blob_.kind() == _InputArray::MAT) {
37+
blob = blob_.getUMat();
38+
}
39+
}
40+
41+
void getMat(Mat& blob, InputArray blob_, AccessFlag flag) {
42+
if(blob_.kind() == _InputArray::UMAT)
43+
blob = blob_.getMat();
44+
else if(blob_.kind() == _InputArray::MAT) {
45+
blob = blob_.getMat();
46+
}
47+
}
48+
49+
void getChannelFromBlob(Mat& m, InputArray blob, int i, int j, int rows, int cols, int type) {
50+
m = Mat(rows, cols, type, blob.getMat().ptr(i, j));
51+
}
52+
53+
void getChannelFromBlob(UMat& m, InputArray blob, int i, int j, int rows, int cols, int type) {
54+
UMat ublob = blob.getUMat();
55+
int offset = (i * ublob.step.p[0] + j * ublob.step.p[1]) / ublob.elemSize();
56+
int length = 1;
57+
for(int i = 0; i < ublob.dims; ++i) {
58+
length *= ublob.size[i];
59+
}
60+
61+
const int newShape[1] { length };
62+
UMat reshaped = ublob.reshape(1, 1, newShape);
63+
UMat roi = reshaped(Rect(0, offset, 1, rows * cols));
64+
m = roi.reshape(CV_MAT_CN(type), rows);
65+
}
66+
2567
Mat blobFromImage(InputArray image, const double scalefactor, const Size& size,
2668
const Scalar& mean, bool swapRB, bool crop, int ddepth)
2769
{
@@ -35,8 +77,13 @@ void blobFromImage(InputArray image, OutputArray blob, double scalefactor,
3577
const Size& size, const Scalar& mean, bool swapRB, bool crop, int ddepth)
3678
{
3779
CV_TRACE_FUNCTION();
38-
std::vector<Mat> images(1, image.getMat());
39-
blobFromImages(images, blob, scalefactor, size, mean, swapRB, crop, ddepth);
80+
if (image.kind() == _InputArray::UMAT) {
81+
std::vector<UMat> images(1, image.getUMat());
82+
blobFromImages(images, blob, scalefactor, size, mean, swapRB, crop, ddepth);
83+
} else {
84+
std::vector<Mat> images(1, image.getMat());
85+
blobFromImages(images, blob, scalefactor, size, mean, swapRB, crop, ddepth);
86+
}
4087
}
4188

4289
Mat blobFromImages(InputArrayOfArrays images, double scalefactor, Size size,
@@ -52,9 +99,9 @@ void blobFromImages(InputArrayOfArrays images_, OutputArray blob_, double scalef
5299
Size size, const Scalar& mean_, bool swapRB, bool crop, int ddepth)
53100
{
54101
CV_TRACE_FUNCTION();
55-
if (images_.kind() != _InputArray::STD_VECTOR_MAT && images_.kind() != _InputArray::STD_ARRAY_MAT &&
102+
if (images_.kind() != _InputArray::STD_VECTOR_UMAT && images_.kind() != _InputArray::STD_VECTOR_MAT && images_.kind() != _InputArray::STD_ARRAY_MAT &&
56103
images_.kind() != _InputArray::STD_VECTOR_VECTOR) {
57-
String error_message = "The data is expected as vectors of vectors or vectors of matrices.";
104+
String error_message = "The data is expected as vectors of vectors, vectors of Mats or vectors of UMats.";
58105
CV_Error(Error::StsBadArg, error_message);
59106
}
60107
Image2BlobParams param(Scalar::all(scalefactor), size, mean_, swapRB, ddepth);
@@ -71,13 +118,6 @@ Mat blobFromImageWithParams(InputArray image, const Image2BlobParams& param)
71118
return blob;
72119
}
73120

74-
void blobFromImageWithParams(InputArray image, OutputArray blob, const Image2BlobParams& param)
75-
{
76-
CV_TRACE_FUNCTION();
77-
std::vector<Mat> images(1, image.getMat());
78-
blobFromImagesWithParams(images, blob, param);
79-
}
80-
81121
Mat blobFromImagesWithParams(InputArrayOfArrays images, const Image2BlobParams& param)
82122
{
83123
CV_TRACE_FUNCTION();
@@ -86,19 +126,22 @@ Mat blobFromImagesWithParams(InputArrayOfArrays images, const Image2BlobParams&
86126
return blob;
87127
}
88128

89-
void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, const Image2BlobParams& param)
129+
template<class Tmat>
130+
void blobFromImagesWithParamsImpl(InputArrayOfArrays images_, Tmat& blob_, const Image2BlobParams& param)
90131
{
91132
CV_TRACE_FUNCTION();
92-
if (images_.kind() != _InputArray::STD_VECTOR_MAT && images_.kind() != _InputArray::STD_ARRAY_MAT &&
93-
images_.kind() != _InputArray::STD_VECTOR_VECTOR) {
94-
String error_message = "The data is expected as vectors of vectors or vectors of matrices.";
133+
if(!std::is_same<Tmat, UMat>::value && !std::is_same<Tmat, Mat>::value) {
134+
String error_message = "The template parameter is expected to be either a cv::Mat or a cv::UMat";
95135
CV_Error(Error::StsBadArg, error_message);
96136
}
137+
97138
CV_CheckType(param.ddepth, param.ddepth == CV_32F || param.ddepth == CV_8U,
98139
"Blob depth should be CV_32F or CV_8U");
99140
Size size = param.size;
100-
std::vector<Mat> images;
101-
images_.getMatVector(images);
141+
142+
std::vector<Tmat> images;
143+
getVector(images_, images);
144+
102145
CV_Assert(!images.empty());
103146

104147
if (param.ddepth == CV_8U)
@@ -164,12 +207,12 @@ void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, con
164207
if (images[i].depth() == CV_8U && param.ddepth == CV_32F)
165208
images[i].convertTo(images[i], CV_32F);
166209

167-
images[i] -= mean;
210+
subtract(images[i], mean, images[i]);
168211
multiply(images[i], scalefactor, images[i]);
169212
}
170213

171214
size_t nimages = images.size();
172-
Mat image0 = images[0];
215+
Tmat image0 = images[0];
173216
CV_Assert(image0.dims == 2);
174217

175218
if (param.datalayout == DNN_LAYOUT_NCHW)
@@ -178,21 +221,22 @@ void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, con
178221
{
179222
int sz[] = { (int)nimages, nch, image0.rows, image0.cols };
180223
blob_.create(4, sz, param.ddepth);
181-
Mat blob = blob_.getMat();
182-
Mat ch[4];
224+
std::vector<Tmat> ch(4);
183225

184226
for (size_t i = 0; i < nimages; i++)
185227
{
186-
const Mat& image = images[i];
228+
const Tmat& image = images[i];
187229
CV_Assert(image.depth() == blob_.depth());
188230
nch = image.channels();
189231
CV_Assert(image.dims == 2 && (nch == 3 || nch == 4));
190232
CV_Assert(image.size() == image0.size());
191233

192-
for (int j = 0; j < nch; j++)
193-
ch[j] = Mat(image.rows, image.cols, param.ddepth, blob.ptr((int)i, j));
234+
for (int j = 0; j < nch; j++) {
235+
getChannelFromBlob(ch[j], blob_, i, j ,image.rows, image.cols, param.ddepth);
236+
}
194237
if (param.swapRB)
195238
std::swap(ch[0], ch[2]);
239+
196240
split(image, ch);
197241
}
198242
}
@@ -201,11 +245,12 @@ void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, con
201245
CV_Assert(nch == 1);
202246
int sz[] = { (int)nimages, 1, image0.rows, image0.cols };
203247
blob_.create(4, sz, param.ddepth);
204-
Mat blob = blob_.getMat();
248+
Mat blob;
249+
getMat(blob, blob_, ACCESS_RW);
205250

206251
for (size_t i = 0; i < nimages; i++)
207252
{
208-
const Mat& image = images[i];
253+
const Tmat& image = images[i];
209254
CV_Assert(image.depth() == blob_.depth());
210255
nch = image.channels();
211256
CV_Assert(image.dims == 2 && (nch == 1));
@@ -219,11 +264,12 @@ void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, con
219264
{
220265
int sz[] = { (int)nimages, image0.rows, image0.cols, nch};
221266
blob_.create(4, sz, param.ddepth);
222-
Mat blob = blob_.getMat();
267+
Mat blob;
268+
getMat(blob, blob_, ACCESS_RW);
223269
int subMatType = CV_MAKETYPE(param.ddepth, nch);
224270
for (size_t i = 0; i < nimages; i++)
225271
{
226-
const Mat& image = images[i];
272+
const Tmat& image = images[i];
227273
CV_Assert(image.depth() == blob_.depth());
228274
CV_Assert(image.channels() == image0.channels());
229275
CV_Assert(image.size() == image0.size());
@@ -243,6 +289,72 @@ void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, con
243289
{
244290
CV_Error(Error::StsUnsupportedFormat, "Unsupported data layout in blobFromImagesWithParams function.");
245291
}
292+
CV_Assert(blob_.total());
293+
}
294+
295+
void blobFromImagesWithParams(InputArrayOfArrays images, OutputArray blob, const Image2BlobParams& param) {
296+
CV_TRACE_FUNCTION();
297+
298+
if (images.kind() == _InputArray::STD_VECTOR_UMAT) {
299+
if(blob.kind() == _InputArray::UMAT) {
300+
UMat& u = blob.getUMatRef();
301+
blobFromImagesWithParamsImpl<cv::UMat>(images, u, param);
302+
return;
303+
} else if(blob.kind() == _InputArray::MAT) {
304+
UMat u = blob.getMatRef().getUMat(ACCESS_WRITE);
305+
blobFromImagesWithParamsImpl<cv::UMat>(images, u, param);
306+
u.copyTo(blob);
307+
return;
308+
}
309+
} else if (images.kind() == _InputArray::STD_VECTOR_MAT) {
310+
if(blob.kind() == _InputArray::UMAT) {
311+
Mat m = blob.getUMatRef().getMat(ACCESS_WRITE);
312+
blobFromImagesWithParamsImpl<cv::Mat>(images, m, param);
313+
m.copyTo(blob);
314+
return;
315+
} else if(blob.kind() == _InputArray::MAT) {
316+
Mat& m = blob.getMatRef();
317+
blobFromImagesWithParamsImpl<cv::Mat>(images, m, param);
318+
return;
319+
}
320+
}
321+
322+
CV_Error(Error::StsBadArg, "Images are expected to be a vector of either a Mat or UMat and Blob is expected to be either a Mat or UMat");
323+
}
324+
325+
void blobFromImageWithParams(InputArray image, OutputArray blob, const Image2BlobParams& param)
326+
{
327+
CV_TRACE_FUNCTION();
328+
329+
if (image.kind() == _InputArray::UMAT) {
330+
if(blob.kind() == _InputArray::UMAT) {
331+
UMat& u = blob.getUMatRef();
332+
std::vector<UMat> images(1, image.getUMat());
333+
blobFromImagesWithParamsImpl<cv::UMat>(images, u, param);
334+
return;
335+
} else if(blob.kind() == _InputArray::MAT) {
336+
UMat u = blob.getMatRef().getUMat(ACCESS_RW);
337+
std::vector<UMat> images(1, image.getUMat());
338+
blobFromImagesWithParamsImpl<cv::UMat>(images, u, param);
339+
u.copyTo(blob);
340+
return;
341+
}
342+
} else if (image.kind() == _InputArray::MAT) {
343+
if(blob.kind() == _InputArray::UMAT) {
344+
Mat m = blob.getUMatRef().getMat(ACCESS_RW);
345+
std::vector<Mat> images(1, image.getMat());
346+
blobFromImagesWithParamsImpl<cv::Mat>(images, m, param);
347+
m.copyTo(blob);
348+
return;
349+
} else if(blob.kind() == _InputArray::MAT) {
350+
Mat& m = blob.getMatRef();
351+
std::vector<Mat> images(1, image.getMat());
352+
blobFromImagesWithParamsImpl<cv::Mat>(images, m, param);
353+
return;
354+
}
355+
}
356+
357+
CV_Error(Error::StsBadArg, "Image an Blob are expected to be either a Mat or UMat");
246358
}
247359

248360
void imagesFromBlob(const cv::Mat& blob_, OutputArrayOfArrays images_)

modules/objdetect/src/face_detect.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,21 @@ class FaceDetectorYNImpl : public FaceDetectorYN
102102
return 0;
103103
}
104104
CV_CheckEQ(input_image.size(), Size(inputW, inputH), "Size does not match. Call setInputSize(size) if input size does not match the preset size");
105-
// Pad input_image with divisor 32
106-
Mat pad_image = padWithDivisor(input_image);
107-
108-
// Build blob from input image
109-
Mat input_blob = dnn::blobFromImage(pad_image);
110105

106+
Mat input_blob;
107+
if(input_image.kind() == _InputArray::UMAT) {
108+
// Pad input_image with divisor 32
109+
UMat pad_image;
110+
padWithDivisor(input_image, pad_image);
111+
// Build blob from input image
112+
input_blob = dnn::blobFromImage(pad_image);
113+
} else {
114+
// Pad input_image with divisor 32
115+
Mat pad_image;
116+
padWithDivisor(input_image, pad_image);
117+
// Build blob from input image
118+
input_blob = dnn::blobFromImage(pad_image);
119+
}
111120
// Forward
112121
std::vector<String> output_names = { "cls_8", "cls_16", "cls_32", "obj_8", "obj_16", "obj_32", "bbox_8", "bbox_16", "bbox_32", "kps_8", "kps_16", "kps_32" };
113122
std::vector<Mat> output_blobs;
@@ -217,13 +226,11 @@ class FaceDetectorYNImpl : public FaceDetectorYN
217226
}
218227
}
219228

220-
Mat padWithDivisor(InputArray& input_image)
229+
void padWithDivisor(InputArray input_image, OutputArray pad_image)
221230
{
222231
int bottom = padH - inputH;
223232
int right = padW - inputW;
224-
Mat pad_image;
225233
copyMakeBorder(input_image, pad_image, 0, bottom, 0, right, BORDER_CONSTANT, 0);
226-
return pad_image;
227234
}
228235
private:
229236
dnn::Net net;

0 commit comments

Comments
 (0)