diff --git a/apps/interactive-calibration/calibController.cpp b/apps/interactive-calibration/calibController.cpp index 1888ee57db..f0aa6df36e 100644 --- a/apps/interactive-calibration/calibController.cpp +++ b/apps/interactive-calibration/calibController.cpp @@ -224,8 +224,10 @@ void calib::calibDataController::filterFrames() cv::Mat newErrorsVec = cv::Mat((int)numberOfFrames - 1, 1, CV_64F); std::copy(mCalibData->perViewErrors.ptr(0), mCalibData->perViewErrors.ptr((int)worstElemIndex), newErrorsVec.ptr(0)); - std::copy(mCalibData->perViewErrors.ptr((int)worstElemIndex + 1), mCalibData->perViewErrors.ptr((int)numberOfFrames), + if((int)worstElemIndex < (int)numberOfFrames-1) { + std::copy(mCalibData->perViewErrors.ptr((int)worstElemIndex + 1), mCalibData->perViewErrors.ptr((int)numberOfFrames), newErrorsVec.ptr((int)worstElemIndex)); + } mCalibData->perViewErrors = newErrorsVec; } } diff --git a/modules/core/include/opencv2/core/cvstd.inl.hpp b/modules/core/include/opencv2/core/cvstd.inl.hpp index 631fe94e1a..ed37cacb30 100644 --- a/modules/core/include/opencv2/core/cvstd.inl.hpp +++ b/modules/core/include/opencv2/core/cvstd.inl.hpp @@ -269,6 +269,11 @@ static inline std::ostream& operator << (std::ostream& out, const MatSize& msize return out; } +static inline std::ostream &operator<< (std::ostream &s, cv::Range &r) +{ + return s << "[" << r.start << " : " << r.end << ")"; +} + } // cv #ifdef _MSC_VER diff --git a/modules/dnn/include/opencv2/dnn/shape_utils.hpp b/modules/dnn/include/opencv2/dnn/shape_utils.hpp index 953a437dc2..64811d8184 100644 --- a/modules/dnn/include/opencv2/dnn/shape_utils.hpp +++ b/modules/dnn/include/opencv2/dnn/shape_utils.hpp @@ -42,8 +42,8 @@ #ifndef OPENCV_DNN_DNN_SHAPE_UTILS_HPP #define OPENCV_DNN_DNN_SHAPE_UTILS_HPP -#include -#include +#include +#include // CV_MAX_DIM #include #include #include @@ -52,12 +52,6 @@ namespace cv { namespace dnn { CV__DNN_EXPERIMENTAL_NS_BEGIN -//Useful shortcut -inline std::ostream &operator<< (std::ostream &s, cv::Range &r) -{ - return s << "[" << r.start << ", " << r.end << ")"; -} - //Slicing struct _Range : public cv::Range diff --git a/modules/dnn/src/layers/reshape_layer.cpp b/modules/dnn/src/layers/reshape_layer.cpp index c9e632dd29..fdd33751f3 100644 --- a/modules/dnn/src/layers/reshape_layer.cpp +++ b/modules/dnn/src/layers/reshape_layer.cpp @@ -186,15 +186,20 @@ public: std::vector &outputs, std::vector &internals) const CV_OVERRIDE { - outputs.clear(); - - for (size_t i = 0; i < inputs.size(); i++) + if (inputs.size() == 1 || inputs.size() == requiredOutputs) { - outputs.push_back(MatShape()); - computeShapeByReshapeMask(inputs[i], newShapeDesc, newShapeRange, outputs.back()); + outputs.clear(); + for (size_t i = 0; i < inputs.size(); i++) + { + outputs.push_back(MatShape()); + computeShapeByReshapeMask(inputs[i], newShapeDesc, newShapeRange, outputs.back()); + } + } + else + { + CV_Assert(inputs.size() == 2, total(inputs[0]) == total(inputs[1])); + outputs.assign(1, inputs[1]); } - internals = outputs; - return true; } @@ -206,7 +211,7 @@ public: inps.getUMatVector(inputs); outs.getUMatVector(outputs); - for (size_t i = 0; i < inputs.size(); i++) + for (size_t i = 0; i < outputs.size(); i++) { UMat srcBlob = inputs[i]; void *src_handle = inputs[i].handle(ACCESS_READ); @@ -240,7 +245,7 @@ public: CV_TRACE_FUNCTION(); CV_TRACE_ARG_VALUE(name, "name", name.c_str()); - for (size_t i = 0; i < inputs.size(); i++) + for (size_t i = 0; i < outputs.size(); i++) { Mat srcBlob = *inputs[i]; if (outputs[i].data != srcBlob.data) @@ -248,7 +253,7 @@ public: } } - virtual Ptr initInfEngine(const std::vector >&) CV_OVERRIDE + virtual Ptr initInfEngine(const std::vector >& inputs) CV_OVERRIDE { #ifdef HAVE_INF_ENGINE InferenceEngine::LayerParams lp; @@ -256,7 +261,15 @@ public: lp.type = "Reshape"; lp.precision = InferenceEngine::Precision::FP32; std::shared_ptr ieLayer(new InferenceEngine::ReshapeLayer(lp)); - ieLayer->shape = newShapeDesc; + if (!newShapeDesc.empty()) + ieLayer->shape = newShapeDesc; + else + { + CV_Assert(inputs.size() == 2); + InferenceEngine::DataPtr shapeSrc = infEngineDataNode(inputs[1]); + // NOTE: shapeSrc->dims are reversed + ieLayer->shape = std::vector(shapeSrc->dims.rbegin(), shapeSrc->dims.rend()); + } return Ptr(new InfEngineBackendNode(ieLayer)); #endif // HAVE_INF_ENGINE return Ptr(); diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index 7d94b9d54a..f354d6966e 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -524,8 +524,7 @@ Mat infEngineBlobToMat(const InferenceEngine::Blob::Ptr& blob) { // NOTE: Inference Engine sizes are reversed. std::vector dims = blob->dims(); - std::vector size(dims.begin(), dims.end()); - std::reverse(size.begin(), size.end()); + std::vector size(dims.rbegin(), dims.rend()); return Mat(size, CV_32F, (void*)blob->buffer()); } @@ -540,8 +539,7 @@ bool InfEngineBackendLayer::getMemoryShapes(const std::vector &inputs, std::vector &internals) const { std::vector dims = output->dims; - std::vector shape(dims.begin(), dims.end()); - std::reverse(shape.begin(), shape.end()); + std::vector shape(dims.rbegin(), dims.rend()); outputs.assign(1, shape); return false; } diff --git a/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp b/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp index 3d8a97f240..241b8af790 100644 --- a/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp +++ b/modules/dnn/src/tensorflow/tf_graph_simplifier.cpp @@ -615,6 +615,19 @@ public: } }; +class ReshapeAsShapeSubgraph : public Subgraph +{ +public: + ReshapeAsShapeSubgraph() + { + int input = addNodeToMatch(""); + int shapeSrc = addNodeToMatch(""); + int shape = addNodeToMatch("Shape", shapeSrc); + addNodeToMatch("Reshape", input, shape); + setFusedNode("Reshape", input, shapeSrc); + } +}; + void simplifySubgraphs(tensorflow::GraphDef& net) { std::vector > subgraphs; @@ -630,6 +643,7 @@ void simplifySubgraphs(tensorflow::GraphDef& net) subgraphs.push_back(Ptr(new DeconvolutionSameKerasSubgraph())); subgraphs.push_back(Ptr(new ResizeBilinearSubgraph())); subgraphs.push_back(Ptr(new UpsamplingKerasSubgraph())); + subgraphs.push_back(Ptr(new ReshapeAsShapeSubgraph())); int numNodes = net.node_size(); std::vector matchedNodesIds; diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index 66c03a777e..b4427c5f32 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -1038,37 +1038,50 @@ void TFImporter::populateNet(Net dstNet) else if (type == "Reshape") { Pin inpId = parsePin(layer.input(0)); - Mat newShape = getTensorContent(getConstBlob(layer, value_id, 1)); - int inpLayout = getDataLayout(layer.input(0), data_layouts); - if (newShape.total() != 4 && inpLayout == DATA_LAYOUT_NHWC) + // There are two possible implementations: reshape an input using + // predefined sizes or use a second input blob as a source of new shape. + if (value_id.find(layer.input(1)) != value_id.end()) { - LayerParams permLP; - int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC. - permLP.set("order", DictValue::arrayInt(order, 4)); + Mat newShape = getTensorContent(getConstBlob(layer, value_id, 1)); - std::string permName = name + "/nchw"; - CV_Assert(layer_id.find(permName) == layer_id.end()); - int permId = dstNet.addLayer(permName, "Permute", permLP); - layer_id[permName] = permId; - connect(layer_id, dstNet, inpId, permId, 0); - inpId = Pin(permName); - inpLayout = DATA_LAYOUT_NCHW; + if (newShape.total() != 4 && inpLayout == DATA_LAYOUT_NHWC) + { + LayerParams permLP; + int order[] = {0, 2, 3, 1}; // From OpenCV's NCHW to NHWC. + permLP.set("order", DictValue::arrayInt(order, 4)); + + std::string permName = name + "/nchw"; + CV_Assert(layer_id.find(permName) == layer_id.end()); + int permId = dstNet.addLayer(permName, "Permute", permLP); + layer_id[permName] = permId; + connect(layer_id, dstNet, inpId, permId, 0); + inpId = Pin(permName); + inpLayout = DATA_LAYOUT_NCHW; + } + else if (newShape.total() == 4 && inpLayout == DATA_LAYOUT_NHWC) + { + // NHWC->NCHW + std::swap(*newShape.ptr(0, 2), *newShape.ptr(0, 3)); + std::swap(*newShape.ptr(0, 1), *newShape.ptr(0, 2)); + } + layerParams.set("dim", DictValue::arrayInt(newShape.ptr(), newShape.total())); + + int id = dstNet.addLayer(name, "Reshape", layerParams); + layer_id[name] = id; + + // one input only + connect(layer_id, dstNet, inpId, id, 0); + data_layouts[name] = newShape.total() == 2 ? DATA_LAYOUT_PLANAR : inpLayout; } - else if (newShape.total() == 4 && inpLayout == DATA_LAYOUT_NHWC) + else { - // NHWC->NCHW - std::swap(*newShape.ptr(0, 2), *newShape.ptr(0, 3)); - std::swap(*newShape.ptr(0, 1), *newShape.ptr(0, 2)); + int id = dstNet.addLayer(name, "Reshape", layerParams); + layer_id[name] = id; + connect(layer_id, dstNet, inpId, id, 0); + connect(layer_id, dstNet, parsePin(layer.input(1)), id, 1); + data_layouts[name] = inpLayout; } - layerParams.set("dim", DictValue::arrayInt(newShape.ptr(), newShape.total())); - - int id = dstNet.addLayer(name, "Reshape", layerParams); - layer_id[name] = id; - - // one input only - connect(layer_id, dstNet, inpId, id, 0); - data_layouts[name] = newShape.total() == 2 ? DATA_LAYOUT_PLANAR : inpLayout; } else if (type == "Flatten" || type == "Squeeze") { diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 63b43f1b72..bbf445f4e0 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -212,6 +212,7 @@ TEST_P(Test_TensorFlow_layers, reshape) runTensorFlowNet("shift_reshape_no_reorder"); runTensorFlowNet("reshape_no_reorder"); runTensorFlowNet("reshape_reduce"); + runTensorFlowNet("reshape_as_shape"); } TEST_P(Test_TensorFlow_layers, flatten) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 0ef29230cf..feec9bd19f 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -178,6 +178,8 @@ void cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) { CV_INSTRUMENT_REGION() + CV_Assert(!_src.empty()); + if(dcn <= 0) dcn = dstChannels(code); diff --git a/modules/imgproc/src/color.hpp b/modules/imgproc/src/color.hpp index 388a92c616..70e7844277 100644 --- a/modules/imgproc/src/color.hpp +++ b/modules/imgproc/src/color.hpp @@ -247,10 +247,14 @@ struct CvtHelper { CvtHelper(InputArray _src, OutputArray _dst, int dcn) { + CV_Assert(!_src.empty()); + int stype = _src.type(); scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype); - CV_Assert( VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) ); + CV_Check(scn, VScn::contains(scn), "Invalid number of channels in input image"); + CV_Check(dcn, VDcn::contains(dcn), "Invalid number of channels in output image"); + CV_CheckDepth(depth, VDepth::contains(depth), "Unsupported depth of input image"); if (_src.getObj() == _dst.getObj()) // inplace processing (#6653) _src.copyTo(src); diff --git a/modules/imgproc/src/color_rgb.cpp b/modules/imgproc/src/color_rgb.cpp index 03c3cd32d8..87aabb7d9e 100644 --- a/modules/imgproc/src/color_rgb.cpp +++ b/modules/imgproc/src/color_rgb.cpp @@ -5,6 +5,8 @@ #include "precomp.hpp" #include "color.hpp" +#define IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 1 + namespace cv { @@ -1228,10 +1230,12 @@ static ippiGeneralFunc ippiRGB2GrayC4Tab[] = }; +#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 static IppStatus ippiGrayToRGB_C1C3R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize) { return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_8u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); } +#endif static IppStatus ippiGrayToRGB_C1C3R(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize) { return CV_INSTRUMENT_FUN_IPP(ippiGrayToRGB_16u_C1C3R, pSrc, srcStep, pDst, dstStep, roiSize); @@ -1516,7 +1520,11 @@ void cvtGraytoBGR(const uchar * src_data, size_t src_step, if(dcn == 3) { if( depth == CV_8U ) + { +#if !IPP_DISABLE_CVTCOLOR_GRAY2BGR_8UC3 ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); +#endif + } else if( depth == CV_16U ) ippres = CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor()); else diff --git a/samples/python/asift.py b/samples/python/asift.py index 5a05021ce8..042e9bda3f 100755 --- a/samples/python/asift.py +++ b/samples/python/asift.py @@ -70,7 +70,7 @@ def affine_detect(detector, img, mask=None, pool=None): ''' affine_detect(detector, img, mask=None, pool=None) -> keypoints, descrs - Apply a set of affine transormations to the image, detect keypoints and + Apply a set of affine transformations to the image, detect keypoints and reproject them into initial image coordinates. See http://www.ipol.im/pub/algo/my_affine_sift/ for the details.