diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index a31730c57f..15c41b3079 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -735,6 +735,15 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN double scalefactor=1.0, Size size = Size(), const Scalar& mean = Scalar(), bool swapRB=true, bool crop=true); + /** @brief Parse a 4D blob and output the images it contains as 2D arrays through a simpler data structure + * (std::vector). + * @param[in] blob_ 4 dimensional array (images, channels, height, width) in floating point precision (CV_32F) from + * which you would like to extract the images. + * @param[out] images_ array of 2D Mat containing the images extracted from the blob in floating point precision + * (CV_32F). They are non normalized neither mean added. The number of returned images equals the first dimension + * of the blob (batch size). Every image has a number of channels equals to the second dimension of the blob (depth). + */ + CV_EXPORTS_W void imagesFromBlob(const cv::Mat& blob_, OutputArrayOfArrays images_); /** @brief Convert all weights of Caffe network to half precision floating point. * @param src Path to origin model from Caffe framework contains single diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 7cc44da2b5..be4767b28a 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -192,6 +192,31 @@ void blobFromImages(InputArrayOfArrays images_, OutputArray blob_, double scalef } } +void imagesFromBlob(const cv::Mat& blob_, OutputArrayOfArrays images_) +{ + CV_TRACE_FUNCTION(); + + //A blob is a 4 dimensional matrix in floating point precision + //blob_[0] = batchSize = nbOfImages + //blob_[1] = nbOfChannels + //blob_[2] = height + //blob_[3] = width + CV_Assert(blob_.depth() == CV_32F); + CV_Assert(blob_.dims == 4); + + images_.create(cv::Size(1, blob_.size[0]), blob_.depth()); + + std::vector vectorOfChannels(blob_.size[1]); + for (int n = 0; n < blob_.size[0]; ++n) + { + for (int c = 0; c < blob_.size[1]; ++c) + { + vectorOfChannels[c] = getPlane(blob_, n, c); + } + cv::merge(vectorOfChannels, images_.getMatRef(n)); + } +} + class OpenCLBackendWrapper : public BackendWrapper { public: diff --git a/modules/dnn/test/test_misc.cpp b/modules/dnn/test/test_misc.cpp index 5241c441bb..57aa7a9c0f 100644 --- a/modules/dnn/test/test_misc.cpp +++ b/modules/dnn/test/test_misc.cpp @@ -36,4 +36,25 @@ TEST(blobFromImage, allocated) ASSERT_EQ(blobData, blob.data); } +TEST(imagesFromBlob, Regression) +{ + int nbOfImages = 8; + + std::vector inputImgs(nbOfImages); + for (int i = 0; i < nbOfImages; i++) + { + inputImgs[i] = cv::Mat::ones(100, 100, CV_32FC3); + cv::randu(inputImgs[i], cv::Scalar::all(0), cv::Scalar::all(1)); + } + + cv::Mat blob = cv::dnn::blobFromImages(inputImgs, 1., cv::Size(), cv::Scalar(), false, false); + std::vector outputImgs; + cv::dnn::imagesFromBlob(blob, outputImgs); + + for (int i = 0; i < nbOfImages; i++) + { + ASSERT_EQ(cv::countNonZero(inputImgs[i] != outputImgs[i]), 0); + } +} + }} // namespace