dnn::blobFromImage with OutputArray
authorDmitry Kurtaev <dmitry.kurtaev+github@gmail.com>
Sat, 13 Jan 2018 15:17:56 +0000 (18:17 +0300)
committerDmitry Kurtaev <dmitry.kurtaev+github@gmail.com>
Sat, 13 Jan 2018 15:20:24 +0000 (18:20 +0300)
modules/dnn/include/opencv2/dnn/dnn.hpp
modules/dnn/src/dnn.cpp
modules/dnn/test/test_misc.cpp

index 7488351..81d0f8d 100644 (file)
@@ -695,6 +695,16 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
      */
     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);
+
+    /** @brief Creates 4-dimensional blob from image.
+     *  @details This is an overloaded member function, provided for convenience.
+     *           It differs from the above function only in what argument(s) it accepts.
+     */
+    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);
+
+
     /** @brief Creates 4-dimensional blob from series of images. Optionally resizes and
      *  crops @p images from center, subtract @p mean values, scales values by @p scalefactor,
      *  swap Blue and Red channels.
@@ -711,9 +721,18 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
      *  If @p crop is false, direct resize without cropping and preserving aspect ratio is performed.
      *  @returns 4-dimansional Mat with NCHW dimensions order.
      */
-    CV_EXPORTS_W Mat blobFromImages(const std::vector<Mat>& images, double scalefactor=1.0,
+    CV_EXPORTS_W Mat blobFromImages(InputArrayOfArrays images, double scalefactor=1.0,
                                     Size size = Size(), const Scalar& mean = Scalar(), bool swapRB=true, bool crop=true);
 
+    /** @brief Creates 4-dimensional blob from series of images.
+     *  @details This is an overloaded member function, provided for convenience.
+     *           It differs from the above function only in what argument(s) it accepts.
+     */
+    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);
+
+
     /** @brief Convert all weights of Caffe network to half precision floating point.
      * @param src Path to origin model from Caffe framework contains single
      *            precision floating point weights (usually has `.caffemodel` extension).
index 051044a..a588fb3 100644 (file)
@@ -81,27 +81,39 @@ namespace
     };
 }
 
-template<typename T>
-static String toString(const T &v)
+Mat blobFromImage(InputArray image, double scalefactor, const Size& size,
+                  const Scalar& mean, bool swapRB, bool crop)
 {
-    std::ostringstream ss;
-    ss << v;
-    return ss.str();
+    CV_TRACE_FUNCTION();
+    Mat blob;
+    blobFromImage(image, blob, scalefactor, size, mean, swapRB, crop);
+    return blob;
 }
 
-Mat blobFromImage(InputArray image, double scalefactor, const Size& size,
-                  const Scalar& mean, bool swapRB, bool crop)
+void blobFromImage(InputArray image, OutputArray blob, double scalefactor,
+                   const Size& size, const Scalar& mean, bool swapRB, bool crop)
 {
     CV_TRACE_FUNCTION();
     std::vector<Mat> images(1, image.getMat());
-    return blobFromImages(images, scalefactor, size, mean, swapRB, crop);
+    blobFromImages(images, blob, scalefactor, size, mean, swapRB, crop);
 }
 
-Mat blobFromImages(const std::vector<Mat>& images_, double scalefactor, Size size,
-                   const Scalar& mean_, bool swapRB, bool crop)
+Mat blobFromImages(InputArrayOfArrays images, double scalefactor, Size size,
+                   const Scalar& mean, bool swapRB, bool crop)
 {
     CV_TRACE_FUNCTION();
-    std::vector<Mat> images = images_;
+    Mat blob;
+    blobFromImages(images, blob, scalefactor, size, mean, swapRB, crop);
+    return blob;
+}
+
+void blobFromImages(InputArrayOfArrays images_, OutputArray blob_, double scalefactor,
+                    Size size, const Scalar& mean_, bool swapRB, bool crop)
+{
+    CV_TRACE_FUNCTION();
+    std::vector<Mat> images;
+    images_.getMatVector(images);
+    CV_Assert(!images.empty());
     for (int i = 0; i < images.size(); i++)
     {
         Size imgSize = images[i].size();
@@ -133,16 +145,15 @@ Mat blobFromImages(const std::vector<Mat>& images_, double scalefactor, Size siz
     }
 
     size_t i, nimages = images.size();
-    if(nimages == 0)
-        return Mat();
     Mat image0 = images[0];
     int nch = image0.channels();
     CV_Assert(image0.dims == 2);
-    Mat blob, image;
+    Mat image;
     if (nch == 3 || nch == 4)
     {
         int sz[] = { (int)nimages, nch, image0.rows, image0.cols };
-        blob = Mat(4, sz, CV_32F);
+        blob_.create(4, sz, CV_32F);
+        Mat blob = blob_.getMat();
         Mat ch[4];
 
         for( i = 0; i < nimages; i++ )
@@ -164,7 +175,8 @@ Mat blobFromImages(const std::vector<Mat>& images_, double scalefactor, Size siz
     {
        CV_Assert(nch == 1);
        int sz[] = { (int)nimages, 1, image0.rows, image0.cols };
-       blob = Mat(4, sz, CV_32F);
+       blob_.create(4, sz, CV_32F);
+       Mat blob = blob_.getMat();
 
        for( i = 0; i < nimages; i++ )
        {
@@ -177,7 +189,6 @@ Mat blobFromImages(const std::vector<Mat>& images_, double scalefactor, Size siz
            image.copyTo(Mat(image.rows, image.cols, CV_32F, blob.ptr((int)i, 0)));
        }
     }
-    return blob;
 }
 
 class OpenCLBackendWrapper : public BackendWrapper
@@ -886,7 +897,8 @@ struct Net::Impl
         {
             LayerPin storedFrom = ld.inputBlobsId[inNum];
             if (storedFrom.valid() && !storedFrom.equal(from))
-                CV_Error(Error::StsError, "Input #" + toString(inNum) + "of layer \"" + ld.name + "\" already was connected");
+                CV_Error(Error::StsError, format("Input #%d of layer \"%s\" already was connected",
+                                                 inNum, ld.name.c_str()));
         }
 
         ld.inputBlobsId[inNum] = from;
@@ -1665,8 +1677,9 @@ struct Net::Impl
         LayerData &ld = layers[pin.lid];
         if ((size_t)pin.oid >= ld.outputBlobs.size())
         {
-            CV_Error(Error::StsOutOfRange, "Layer \"" + ld.name + "\" produce only " + toString(ld.outputBlobs.size()) +
-                                           " outputs, the #" + toString(pin.oid) + " was requsted");
+            CV_Error(Error::StsOutOfRange, format("Layer \"%s\" produce only %d outputs, "
+                                           "the #%d was requsted", ld.name.c_str(),
+                                           ld.outputBlobs.size(), pin.oid));
         }
         if (preferableTarget != DNN_TARGET_CPU)
         {
index 2eee54c..f53cdd2 100644 (file)
@@ -27,4 +27,14 @@ TEST(blobFromImage_4ch, Regression)
     }
 }
 
+TEST(blobFromImage, allocated)
+{
+    int size[] = {1, 3, 4, 5};
+    Mat img(size[2], size[3], CV_32FC(size[1]));
+    Mat blob(4, size, CV_32F);
+    void* blobData = blob.data;
+    dnn::blobFromImage(img, blob, 1.0 / 255, Size(), Scalar(), false, false);
+    ASSERT_EQ(blobData, blob.data);
+}
+
 }