From a9839af9031c0567a780b0004e48ddd14e6670e1 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Wed, 7 Aug 2019 14:51:41 +0300 Subject: [PATCH] Add preprocessing warps for separate parameters --- modules/dnn/include/opencv2/dnn/dnn.hpp | 23 ++++++++++++++--------- modules/dnn/misc/python/test/test_dnn.py | 20 ++++++++++++++++---- modules/dnn/src/model.cpp | 12 ++++++------ 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index 5cb98c1f1e..22eba0dfa5 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -999,9 +999,14 @@ CV__DNN_INLINE_NS_BEGIN * Model creates net from file with trained weights and config, * sets preprocessing input and runs forward pass. */ - class CV_EXPORTS_W Model : public Net + class CV_EXPORTS_W_SIMPLE Model : public Net { public: + /** + * @brief Default constructor. + */ + Model(); + /** * @brief Create model from deep learning network represented in one of the supported formats. * An order of @p model and @p config arguments does not matter. @@ -1020,7 +1025,7 @@ CV__DNN_INLINE_NS_BEGIN * @param[in] size New input size. * @note If shape of the new blob less than 0, then frame size not change. */ - Model& setInputSize(const Size& size); + CV_WRAP Model& setInputSize(const Size& size); /** @brief Set input size for frame. * @param[in] width New input width. @@ -1028,27 +1033,27 @@ CV__DNN_INLINE_NS_BEGIN * @note If shape of the new blob less than 0, * then frame size not change. */ - Model& setInputSize(int width, int height); + CV_WRAP Model& setInputSize(int width, int height); /** @brief Set mean value for frame. * @param[in] mean Scalar with mean values which are subtracted from channels. */ - Model& setInputMean(const Scalar& mean); + CV_WRAP Model& setInputMean(const Scalar& mean); /** @brief Set scalefactor value for frame. * @param[in] scale Multiplier for frame values. */ - Model& setInputScale(double scale); + CV_WRAP Model& setInputScale(double scale); /** @brief Set flag crop for frame. * @param[in] crop Flag which indicates whether image will be cropped after resize or not. */ - Model& setInputCrop(bool crop); + CV_WRAP Model& setInputCrop(bool crop); /** @brief Set flag swapRB for frame. * @param[in] swapRB Flag which indicates that swap first and last channels. */ - Model& setInputSwapRB(bool swapRB); + CV_WRAP Model& setInputSwapRB(bool swapRB); /** @brief Set preprocessing parameters for frame. * @param[in] size New input size. @@ -1078,7 +1083,7 @@ CV__DNN_INLINE_NS_BEGIN * ClassificationModel creates net from file with trained weights and config, * sets preprocessing input, runs forward pass and return top-1 prediction. */ - class CV_EXPORTS_W ClassificationModel : public Model + class CV_EXPORTS_W_SIMPLE ClassificationModel : public Model { public: /** @@ -1111,7 +1116,7 @@ CV__DNN_INLINE_NS_BEGIN * sets preprocessing input, runs forward pass and return result detections. * For DetectionModel SSD, Faster R-CNN, YOLO topologies are supported. */ - class CV_EXPORTS_W DetectionModel : public Model + class CV_EXPORTS_W_SIMPLE DetectionModel : public Model { public: /** diff --git a/modules/dnn/misc/python/test/test_dnn.py b/modules/dnn/misc/python/test/test_dnn.py index f4184df290..ed1e7a20ee 100644 --- a/modules/dnn/misc/python/test/test_dnn.py +++ b/modules/dnn/misc/python/test/test_dnn.py @@ -138,10 +138,7 @@ class dnn_test(NewOpenCVTests): config = self.find_dnn_file("dnn/MobileNetSSD_deploy.prototxt") frame = cv.imread(img_path) model = cv.dnn_DetectionModel(weights, config) - size = (300, 300) - mean = (127.5, 127.5, 127.5) - scale = 1.0 / 127.5 - model.setInputParams(size=size, mean=mean, scale=scale) + model.setInputParams(size=(300, 300), mean=(127.5, 127.5, 127.5), scale=1.0/127.5) iouDiff = 0.05 confThreshold = 0.0001 @@ -164,6 +161,21 @@ class dnn_test(NewOpenCVTests): cv.rectangle(frame, list(box), (0, 255, 0)) + def test_classification_model(self): + img_path = self.find_dnn_file("dnn/googlenet_0.png") + weights = self.find_dnn_file("dnn/squeezenet_v1.1.caffemodel") + config = self.find_dnn_file("dnn/squeezenet_v1.1.prototxt") + ref = np.load(self.find_dnn_file("dnn/squeezenet_v1.1_prob.npy")) + + frame = cv.imread(img_path) + model = cv.dnn_ClassificationModel(config, weights) + model.setInputSize(227, 227) + model.setInputCrop(True) + + out = model.predict(frame) + normAssert(self, out, ref) + + def test_face_detection(self): testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False)) proto = self.find_dnn_file('dnn/opencv_face_detector.prototxt', required=testdata_required) diff --git a/modules/dnn/src/model.cpp b/modules/dnn/src/model.cpp index 544beddad5..3aeb3a2b2a 100644 --- a/modules/dnn/src/model.cpp +++ b/modules/dnn/src/model.cpp @@ -23,7 +23,7 @@ struct Model::Impl Mat blob; std::vector outNames; - void predict(Net& net, const Mat& frame, std::vector& outs) + void predict(Net& net, const Mat& frame, OutputArrayOfArrays outs) { if (size.empty()) CV_Error(Error::StsBadSize, "Input size not specified"); @@ -41,16 +41,18 @@ struct Model::Impl } }; +Model::Model() : impl(new Impl) {} + Model::Model(const String& model, const String& config) : Net(readNet(model, config)), impl(new Impl) { impl->outNames = getUnconnectedOutLayersNames(); -}; +} Model::Model(const Net& network) : Net(network), impl(new Impl) { impl->outNames = getUnconnectedOutLayersNames(); -}; +} Model& Model::setInputSize(const Size& size) { @@ -100,9 +102,7 @@ void Model::setInputParams(double scale, const Size& size, const Scalar& mean, void Model::predict(InputArray frame, OutputArrayOfArrays outs) { - std::vector outputs; - outs.getMatVector(outputs); - impl->predict(*this, frame.getMat(), outputs); + impl->predict(*this, frame.getMat(), outs); } ClassificationModel::ClassificationModel(const String& model, const String& config)