From 09c63e4f007d9e9f6f7da4c69f2c61a15bc21011 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 9 Jun 2018 16:13:52 +0300 Subject: [PATCH 1/8] videoio(msmf): fix reopen condition in configureHW() `camid` value is always -1 after close(). --- modules/videoio/src/cap_msmf.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index a0c82ed435..cf7a95ea63 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -805,7 +805,7 @@ bool CvCapture_MSMF::configureHW(bool enable) if (SUCCEEDED(D3DMgr->ResetDevice(D3DDev.Get(), mgrRToken))) { captureMode = MODE_HW; - return reopen ? camid >= 0 ? open(prevcam) : open(prevfile.c_str()) : true; + return reopen ? (prevcam >= 0 ? open(prevcam) : open(prevfile.c_str())) : true; } D3DMgr.Reset(); } @@ -821,7 +821,7 @@ bool CvCapture_MSMF::configureHW(bool enable) if (D3DDev) D3DDev.Reset(); captureMode = MODE_SW; - return reopen ? camid >= 0 ? open(prevcam) : open(prevfile.c_str()) : true; + return reopen ? (prevcam >= 0 ? open(prevcam) : open(prevfile.c_str())) : true; } #else return !enable; From 5fd7cfbcad635859aa6aec8c1da526fc80f687fa Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 13 Jun 2018 18:55:31 +0300 Subject: [PATCH 2/8] dnn: add runtime parameter OPENCV_DNN_BACKEND_DEFAULT to control DNN_BACKEND_DEFAULT enumeration value behavior --- modules/dnn/src/dnn.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 98d6fdc186..84967ced96 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -66,6 +66,15 @@ static bool DNN_DISABLE_MEMORY_OPTIMIZATIONS = utils::getConfigurationParameterB static bool DNN_OPENCL_ALLOW_ALL_DEVICES = utils::getConfigurationParameterBool("OPENCV_DNN_OPENCL_ALLOW_ALL_DEVICES", false); #endif +static int PARAM_DNN_BACKEND_DEFAULT = (int)utils::getConfigurationParameterSizeT("OPENCV_DNN_BACKEND_DEFAULT", +#ifdef HAVE_INF_ENGINE + (size_t)DNN_BACKEND_INFERENCE_ENGINE +#else + (size_t)DNN_BACKEND_OPENCV +#endif +); + + using std::vector; using std::map; using std::make_pair; @@ -851,11 +860,8 @@ struct Net::Impl CV_TRACE_FUNCTION(); if (preferableBackend == DNN_BACKEND_DEFAULT) -#ifdef HAVE_INF_ENGINE - preferableBackend = DNN_BACKEND_INFERENCE_ENGINE; -#else - preferableBackend = DNN_BACKEND_OPENCV; -#endif + preferableBackend = (Backend)PARAM_DNN_BACKEND_DEFAULT; + CV_Assert(preferableBackend != DNN_BACKEND_OPENCV || preferableTarget == DNN_TARGET_CPU || preferableTarget == DNN_TARGET_OPENCL || From 018eab70403d52a823486c9e3cdd3acc3056e4bc Mon Sep 17 00:00:00 2001 From: vishwesh5 Date: Thu, 14 Jun 2018 12:30:06 +0530 Subject: [PATCH 3/8] Corrected formula Corrected formula for weighted within-class variance --- .../py_imgproc/py_thresholding/py_thresholding.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/py_tutorials/py_imgproc/py_thresholding/py_thresholding.markdown b/doc/py_tutorials/py_imgproc/py_thresholding/py_thresholding.markdown index 1326bc5126..896b5f7d0c 100644 --- a/doc/py_tutorials/py_imgproc/py_thresholding/py_thresholding.markdown +++ b/doc/py_tutorials/py_imgproc/py_thresholding/py_thresholding.markdown @@ -183,7 +183,7 @@ minimizes the **weighted within-class variance** given by the relation : where -\f[q_1(t) = \sum_{i=1}^{t} P(i) \quad \& \quad q_1(t) = \sum_{i=t+1}^{I} P(i)\f]\f[\mu_1(t) = \sum_{i=1}^{t} \frac{iP(i)}{q_1(t)} \quad \& \quad \mu_2(t) = \sum_{i=t+1}^{I} \frac{iP(i)}{q_2(t)}\f]\f[\sigma_1^2(t) = \sum_{i=1}^{t} [i-\mu_1(t)]^2 \frac{P(i)}{q_1(t)} \quad \& \quad \sigma_2^2(t) = \sum_{i=t+1}^{I} [i-\mu_1(t)]^2 \frac{P(i)}{q_2(t)}\f] +\f[q_1(t) = \sum_{i=1}^{t} P(i) \quad \& \quad q_2(t) = \sum_{i=t+1}^{I} P(i)\f]\f[\mu_1(t) = \sum_{i=1}^{t} \frac{iP(i)}{q_1(t)} \quad \& \quad \mu_2(t) = \sum_{i=t+1}^{I} \frac{iP(i)}{q_2(t)}\f]\f[\sigma_1^2(t) = \sum_{i=1}^{t} [i-\mu_1(t)]^2 \frac{P(i)}{q_1(t)} \quad \& \quad \sigma_2^2(t) = \sum_{i=t+1}^{I} [i-\mu_2(t)]^2 \frac{P(i)}{q_2(t)}\f] It actually finds a value of t which lies in between two peaks such that variances to both classes are minimum. It can be simply implemented in Python as follows: From 693a7663e7e92e55e8f1e47d877c56ad759d2a2c Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Thu, 14 Jun 2018 13:30:30 +0300 Subject: [PATCH 4/8] Import ClipByValue from Keras --- modules/dnn/src/tensorflow/tf_importer.cpp | 21 +++++++++++++++++++++ modules/dnn/test/test_tf_importer.cpp | 1 + 2 files changed, 22 insertions(+) diff --git a/modules/dnn/src/tensorflow/tf_importer.cpp b/modules/dnn/src/tensorflow/tf_importer.cpp index 4bff84175d..9140368522 100644 --- a/modules/dnn/src/tensorflow/tf_importer.cpp +++ b/modules/dnn/src/tensorflow/tf_importer.cpp @@ -1641,6 +1641,27 @@ void TFImporter::populateNet(Net dstNet) connect(layer_id, dstNet, Pin(name), flattenId, 0); } } + else if (type == "ClipByValue") + { + // op: "ClipByValue" + // input: "input" + // input: "mix" + // input: "max" + CV_Assert(layer.input_size() == 3); + + Mat minValue = getTensorContent(getConstBlob(layer, value_id, 1)); + Mat maxValue = getTensorContent(getConstBlob(layer, value_id, 2)); + CV_Assert(minValue.total() == 1, minValue.type() == CV_32F, + maxValue.total() == 1, maxValue.type() == CV_32F); + + layerParams.set("min_value", minValue.at(0)); + layerParams.set("max_value", maxValue.at(0)); + + int id = dstNet.addLayer(name, "ReLU6", layerParams); + layer_id[name] = id; + + connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); + } else if (type == "Abs" || type == "Tanh" || type == "Sigmoid" || type == "Relu" || type == "Elu" || type == "Identity" || type == "Relu6") diff --git a/modules/dnn/test/test_tf_importer.cpp b/modules/dnn/test/test_tf_importer.cpp index 4f024114ef..5ac8890e50 100644 --- a/modules/dnn/test/test_tf_importer.cpp +++ b/modules/dnn/test/test_tf_importer.cpp @@ -415,6 +415,7 @@ TEST(Test_TensorFlow, softmax) TEST(Test_TensorFlow, relu6) { runTensorFlowNet("keras_relu6"); + runTensorFlowNet("keras_relu6", DNN_TARGET_CPU, /*hasText*/ true); } TEST(Test_TensorFlow, keras_mobilenet_head) From 2bb5d1bca3c42cc45be6917e5b5abf1cf71dbdba Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 10 Jun 2018 15:32:09 +0300 Subject: [PATCH 5/8] videoio(msmf): cleanup unused methods from ComPtr wrapper Use Win32 TRUE/FALSE in SetUINT32() calls for bool parameters --- modules/videoio/src/cap_msmf.cpp | 113 ++++++++----------------------- 1 file changed, 28 insertions(+), 85 deletions(-) diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index d6786b02a7..501a0172c5 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -122,89 +122,36 @@ public: T** operator&() { - assert(p == NULL); + CV_Assert(p == NULL); return p.operator&(); } T* operator->() const { - assert(p != NULL); + CV_Assert(p != NULL); return p.operator->(); } - bool operator!() const - { - return p.operator==(NULL); - } - bool operator==(_In_opt_ T* pT) const - { - return p.operator==(pT); - } - bool operator!=(_In_opt_ T* pT) const - { - return p.operator!=(pT); - } operator bool() { return p.operator!=(NULL); } - T* const* GetAddressOf() const - { - return &p; - } - - T** GetAddressOf() - { - return &p; - } - - T** ReleaseAndGetAddressOf() - { - p.Release(); - return &p; - } - T* Get() const { return p; } - // Attach to an existing interface (does not AddRef) - void Attach(_In_opt_ T* p2) + void Release() { - p.Attach(p2); - } - // Detach the interface (does not Release) - T* Detach() - { - return p.Detach(); - } - _Check_return_ HRESULT CopyTo(_Deref_out_opt_ T** ppT) - { - assert(ppT != NULL); - if (ppT == NULL) - return E_POINTER; - *ppT = p; - if (p != NULL) - p->AddRef(); - return S_OK; - } - - void Reset() - { - p.Release(); + if (p) + p.Release(); } // query for U interface template - HRESULT As(_Inout_ U** lp) const + HRESULT As(_Out_ ComPtr& lp) const { - return p->QueryInterface(__uuidof(U), reinterpret_cast(lp)); - } - // query for U interface - template - HRESULT As(_Out_ ComPtr* lp) const - { - return p->QueryInterface(__uuidof(U), reinterpret_cast(lp->ReleaseAndGetAddressOf())); + lp.Release(); + return p->QueryInterface(__uuidof(U), reinterpret_cast((T**)&lp)); } private: _COM_SMARTPTR_TYPEDEF(T, __uuidof(T)); @@ -734,12 +681,10 @@ void CvCapture_MSMF::close() if (isOpen) { isOpen = false; - if (videoSample) - videoSample.Reset(); - if (videoFileSource) - videoFileSource.Reset(); + videoSample.Release(); + videoFileSource.Release(); camid = -1; - filename = ""; + filename.clear(); } } @@ -759,7 +704,7 @@ bool CvCapture_MSMF::configureHW(bool enable) D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_VIDEO_SUPPORT, - levels, sizeof(levels) / sizeof(*levels), D3D11_SDK_VERSION, D3DDev.GetAddressOf(), NULL, NULL))) + levels, sizeof(levels) / sizeof(*levels), D3D11_SDK_VERSION, &D3DDev, NULL, NULL))) { // NOTE: Getting ready for multi-threaded operation _ComPtr D3DDevMT; @@ -767,27 +712,27 @@ bool CvCapture_MSMF::configureHW(bool enable) if (SUCCEEDED(D3DDev->QueryInterface(IID_PPV_ARGS(&D3DDevMT)))) { D3DDevMT->SetMultithreadProtected(TRUE); - D3DDevMT.Reset(); - if (SUCCEEDED(MFCreateDXGIDeviceManager(&mgrRToken, D3DMgr.GetAddressOf()))) + D3DDevMT.Release(); + if (SUCCEEDED(MFCreateDXGIDeviceManager(&mgrRToken, &D3DMgr))) { if (SUCCEEDED(D3DMgr->ResetDevice(D3DDev.Get(), mgrRToken))) { captureMode = MODE_HW; return reopen ? (prevcam >= 0 ? open(prevcam) : open(prevfile.c_str())) : true; } - D3DMgr.Reset(); + D3DMgr.Release(); } } - D3DDev.Reset(); + D3DDev.Release(); } return false; } else { if (D3DMgr) - D3DMgr.Reset(); + D3DMgr.Release(); if (D3DDev) - D3DDev.Reset(); + D3DDev.Release(); captureMode = MODE_SW; return reopen ? (prevcam >= 0 ? open(prevcam) : open(prevfile.c_str())) : true; } @@ -911,7 +856,7 @@ bool CvCapture_MSMF::open(int _index) close(); _ComPtr msAttr = NULL; - if (SUCCEEDED(MFCreateAttributes(msAttr.GetAddressOf(), 1)) && + if (SUCCEEDED(MFCreateAttributes(&msAttr, 1)) && SUCCEEDED(msAttr->SetGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID @@ -933,10 +878,10 @@ bool CvCapture_MSMF::open(int _index) _ComPtr srAttr; if (SUCCEEDED(ppDevices[ind]->ActivateObject(__uuidof(IMFMediaSource), (void**)&mSrc)) && mSrc && SUCCEEDED(MFCreateAttributes(&srAttr, 10)) && - SUCCEEDED(srAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true)) && - SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, false)) && - SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, false)) && - SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, true))) + SUCCEEDED(srAttr->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE)) && + SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_DISABLE_DXVA, FALSE)) && + SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, FALSE)) && + SUCCEEDED(srAttr->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE))) { #ifdef HAVE_DXVA if (D3DMgr) @@ -1019,8 +964,7 @@ bool CvCapture_MSMF::grabFrame() if (isOpen) { DWORD streamIndex, flags; - if (videoSample) - videoSample.Reset(); + videoSample.Release(); HRESULT hr; for(;;) { @@ -1123,7 +1067,7 @@ bool CvCapture_MSMF::retrieveFrame(int, cv::OutputArray frame) _ComPtr buffer2d; if (convertFormat) { - if (SUCCEEDED(buf.As(&buffer2d))) + if (SUCCEEDED(buf.As(buffer2d))) { CV_TRACE_REGION_NEXT("lock2d"); if (SUCCEEDED(buffer2d->Lock2D(&ptr, &pitch))) @@ -1204,8 +1148,7 @@ bool CvCapture_MSMF::setTime(double time, bool rough) if (SUCCEEDED(videoFileSource->GetPresentationAttribute((DWORD)MF_SOURCE_READER_MEDIASOURCE, MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS, &var)) && var.vt == VT_UI4 && var.ulVal & MFMEDIASOURCE_CAN_SEEK) { - if (videoSample) - videoSample.Reset(); + videoSample.Release(); bool useGrabbing = time > 0 && !rough && !(var.ulVal & MFMEDIASOURCE_HAS_SLOW_SEEK); PropVariantClear(&var); sampleTime = (useGrabbing && time >= frameStep) ? (LONGLONG)floor(time + 0.5) - frameStep : (LONGLONG)floor(time + 0.5); @@ -1216,7 +1159,7 @@ bool CvCapture_MSMF::setTime(double time, bool rough) if (resOK && useGrabbing) { LONGLONG timeborder = (LONGLONG)floor(time + 0.5) - frameStep / 2; - do { resOK = grabFrame(); videoSample.Reset(); } while (resOK && sampleTime < timeborder); + do { resOK = grabFrame(); videoSample.Release(); } while (resOK && sampleTime < timeborder); } return resOK; } @@ -1958,7 +1901,7 @@ void CvVideoWriter_MSMF::close() { initiated = false; sinkWriter->Finalize(); - sinkWriter.Reset(); + sinkWriter.Release(); } } From bd87eb6e66d4db4f3d994f02e1e58e9c192e824a Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Thu, 14 Jun 2018 15:22:08 +0300 Subject: [PATCH 6/8] Import average pooling and softmax layers from Darknet --- modules/dnn/src/darknet/darknet_io.cpp | 49 ++++++++++++++++++++++ modules/dnn/test/test_darknet_importer.cpp | 5 +++ 2 files changed, 54 insertions(+) diff --git a/modules/dnn/src/darknet/darknet_io.cpp b/modules/dnn/src/darknet/darknet_io.cpp index 91ebb0fa8b..03805dd364 100644 --- a/modules/dnn/src/darknet/darknet_io.cpp +++ b/modules/dnn/src/darknet/darknet_io.cpp @@ -212,6 +212,44 @@ namespace cv { fused_layer_names.push_back(last_layer); } + void setAvgpool() + { + cv::dnn::LayerParams avgpool_param; + avgpool_param.set("pool", "ave"); + avgpool_param.set("global_pooling", true); + avgpool_param.name = "Pooling-name"; + avgpool_param.type = "Pooling"; + darknet::LayerParameter lp; + + std::string layer_name = cv::format("avgpool_%d", layer_id); + lp.layer_name = layer_name; + lp.layer_type = avgpool_param.type; + lp.layerParams = avgpool_param; + lp.bottom_indexes.push_back(last_layer); + last_layer = layer_name; + net->layers.push_back(lp); + layer_id++; + fused_layer_names.push_back(last_layer); + } + + void setSoftmax() + { + cv::dnn::LayerParams softmax_param; + softmax_param.name = "Softmax-name"; + softmax_param.type = "Softmax"; + darknet::LayerParameter lp; + + std::string layer_name = cv::format("softmax_%d", layer_id); + lp.layer_name = layer_name; + lp.layer_type = softmax_param.type; + lp.layerParams = softmax_param; + lp.bottom_indexes.push_back(last_layer); + last_layer = layer_name; + net->layers.push_back(lp); + layer_id++; + fused_layer_names.push_back(last_layer); + } + void setConcat(int number_of_inputs, int *input_indexes) { cv::dnn::LayerParams concat_param; @@ -541,6 +579,17 @@ namespace cv { int pad = getParam(layer_params, "pad", 0); setParams.setMaxpool(kernel_size, pad, stride); } + else if (layer_type == "avgpool") + { + setParams.setAvgpool(); + } + else if (layer_type == "softmax") + { + int groups = getParam(layer_params, "groups", 1); + if (groups != 1) + CV_Error(Error::StsNotImplemented, "Softmax from Darknet with groups != 1"); + setParams.setSoftmax(); + } else if (layer_type == "route") { std::string bottom_layers = getParam(layer_params, "layers", ""); diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index aaa7ef5c11..e28d9dc11e 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -228,4 +228,9 @@ TEST(Test_Darknet, upsample) testDarknetLayer("upsample"); } +TEST(Test_Darknet, avgpool_softmax) +{ + testDarknetLayer("avgpool_softmax"); +} + }} // namespace From ecf4b639e103818b86a9c2235b316fd40a626e9c Mon Sep 17 00:00:00 2001 From: Adam Rankin Date: Thu, 14 Jun 2018 18:24:14 -0400 Subject: [PATCH 7/8] Adding the ability to toggle autofocus on/off for DirectShow webcams --- modules/videoio/src/cap_dshow.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/modules/videoio/src/cap_dshow.cpp b/modules/videoio/src/cap_dshow.cpp index f29eb98cc3..3a92a81d49 100644 --- a/modules/videoio/src/cap_dshow.cpp +++ b/modules/videoio/src/cap_dshow.cpp @@ -3220,6 +3220,11 @@ double VideoCapture_DShow::getProperty(int propIdx) const return g_VI.getFourcc(m_index); case CV_CAP_PROP_FPS: return g_VI.getFPS(m_index); + case CV_CAP_PROP_AUTOFOCUS: + // Flags indicate whether or not autofocus is enabled + if (g_VI.getVideoSettingCamera(m_index, CameraControl_Focus, min_value, max_value, stepping_delta, current_value, flags, defaultValue)) + return (double)flags; + return -1; // video filter properties case CV_CAP_PROP_BRIGHTNESS: @@ -3284,6 +3289,7 @@ bool VideoCapture_DShow::setProperty(int propIdx, double propVal) break; case CV_CAP_PROP_FPS: + { int fps = cvRound(propVal); if (fps != g_VI.getFPS(m_index)) { @@ -3297,6 +3303,19 @@ bool VideoCapture_DShow::setProperty(int propIdx, double propVal) return g_VI.isDeviceSetup(m_index); } + case CV_CAP_PROP_AUTOFOCUS: + { + // Flags are required to toggle autofocus or not, but the setProperty interface does not support multiple parameters + bool enabled = cvRound(propVal) == 1; + long minFocus, maxFocus, delta, currentFocus, flags, defaultValue; + if (!g_VI.getVideoSettingCamera(m_index, CameraControl_Focus, minFocus, maxFocus, delta, currentFocus, flags, defaultValue)) + { + return false; + } + return g_VI.setVideoSettingCamera(m_index, CameraControl_Focus, currentFocus, enabled ? CameraControl_Flags_Auto | CameraControl_Flags_Manual : CameraControl_Flags_Manual, enabled ? true : false); + } + } + if (handled) { // a stream setting From 5e2c112697889f06fad1d16a2244f29e707572d6 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 15 Jun 2018 19:37:58 +0300 Subject: [PATCH 8/8] photo: remove redundant broken check `dest(roi_d)` operation contains similar check inside. --- modules/photo/src/seamless_cloning.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index 9865d62ab3..16376def62 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -88,10 +88,6 @@ void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point int minxd = p.x - lenx/2; int minyd = p.y - leny/2; - int maxxd = minxd + lenx; - int maxyd = minyd + leny; - - CV_Assert(minxd >= 0 && minyd >= 0 && maxxd <= dest.rows && maxyd <= dest.cols); Rect roi_d(minxd,minyd,lenx,leny); Rect roi_s(minx,miny,lenx,leny);