@ -0,0 +1,3 @@ |
||||
set(the_description "Advanced edge-detection algorithms") |
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) |
||||
ocv_define_module(ximpgroc opencv_core opencv_imgproc OPTIONAL opencv_highgui) |
@ -0,0 +1,70 @@ |
||||
Structured forests for fast edge detection |
||||
****************************************** |
||||
|
||||
.. highlight:: cpp |
||||
|
||||
... |
||||
|
||||
StructuredEdgeDetection |
||||
----------------------- |
||||
|
||||
.. ocv:class:: StructuredEdgeDetection : public Algorithm |
||||
|
||||
Class implementing edge detection algorithm from [Dollar2013]_ :: |
||||
|
||||
/*! \class StructuredEdgeDetection |
||||
Prediction part of [P. Dollar and C. L. Zitnick. Structured Forests for Fast Edge Detection, 2013]. |
||||
*/ |
||||
class CV_EXPORTS_W StructuredEdgeDetection : public Algorithm |
||||
{ |
||||
public: |
||||
|
||||
/*! |
||||
* The function detects edges in src and draw them to dst |
||||
* |
||||
* \param src : source image (RGB, float, in [0;1]) to detect edges |
||||
* \param dst : destination image (grayscale, float, in [0;1]) |
||||
* where edges are drawn |
||||
*/ |
||||
CV_WRAP virtual void detectEdges(const Mat src, Mat dst) = 0; |
||||
}; |
||||
|
||||
/*! |
||||
* The only available constructor loading data from model file |
||||
* |
||||
* \param model : name of the file where the model is stored |
||||
*/ |
||||
CV_EXPORTS_W Ptr<StructuredEdgeDetection> createStructuredEdgeDetection(const String &model); |
||||
|
||||
StructuredEdgeDetection::detectEdges |
||||
++++++++++++++++++++++++++++++++++++ |
||||
.. ocv:function:: void detectEdges(const Mat src, Mat dst) |
||||
|
||||
The function detects edges in src and draw them to dst. The algorithm underlies this function |
||||
is much more robust to texture presence, than common approaches, e.g. Sobel |
||||
|
||||
:param src : source image (RGB, float, in [0;1]) to detect edges |
||||
:param dst : destination image (grayscale, float, in [0;1]) |
||||
where edges are drawn |
||||
|
||||
.. seealso:: |
||||
|
||||
:ocv:class:`Sobel`, |
||||
:ocv:class:`Canny` |
||||
|
||||
createStructuredEdgeDetection |
||||
+++++++++++++++++++++++++++++ |
||||
.. ocv:function:: Ptr<cv::StructuredEdgeDetection> createStructuredEdgeDetection(String model) |
||||
|
||||
The only available constructor |
||||
|
||||
:param model: model file name |
||||
|
||||
|
||||
Literature |
||||
---------- |
||||
|
||||
.. [Dollar2013] Dollár P., Zitnick C. L., "Structured forests for fast edge detection", |
||||
IEEE International Conference on Computer Vision (ICCV), 2013, |
||||
pp. 1841-1848. `DOI <http://dx.doi.org/10.1109/ICCV.2013.231>`_ |
||||
|
@ -0,0 +1,8 @@ |
||||
******************************************** |
||||
ximpgroc. Advanced edge-detection algorithms |
||||
******************************************** |
||||
|
||||
.. toctree:: |
||||
:maxdepth: 2 |
||||
|
||||
Structured forests for fast edge detection <structured_edge_detection/index> |
@ -0,0 +1,48 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_EDGEDETECTION_HPP__ |
||||
#define __OPENCV_EDGEDETECTION_HPP__ |
||||
|
||||
#include "opencv2/core.hpp" |
||||
#include "opencv2/ximpgroc/structured_edge_detection.hpp" |
||||
#endif |
@ -0,0 +1,127 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_STRUCTURED_EDGE_DETECTION_HPP__ |
||||
#define __OPENCV_STRUCTURED_EDGE_DETECTION_HPP__ |
||||
|
||||
/*
|
||||
* structured_edge_detection.hpp |
||||
* |
||||
* Created on: Jun 17, 2014 |
||||
* Author: Yury Gitman |
||||
*/ |
||||
|
||||
#include <opencv2/core.hpp> |
||||
|
||||
/*! \namespace cv
|
||||
Namespace where all the C++ OpenCV functionality resides |
||||
*/ |
||||
namespace cv |
||||
{ |
||||
|
||||
/*! \class RFFeatureGetter
|
||||
Helper class for training part of [P. Dollar and C. L. Zitnick. Structured Forests for Fast Edge Detection, 2013]. |
||||
*/ |
||||
class CV_EXPORTS_W RFFeatureGetter : public Algorithm |
||||
{ |
||||
public: |
||||
|
||||
/*!
|
||||
* This functions extracts feature channels from src. |
||||
* Than StructureEdgeDetection uses this feature space |
||||
* to detect edges. |
||||
* |
||||
* \param src : source image to extract features |
||||
* \param features : output n-channel floating point feature matrix. |
||||
* |
||||
* \param gnrmRad : __rf.options.gradientNormalizationRadius |
||||
* \param gsmthRad : __rf.options.gradientSmoothingRadius |
||||
* \param shrink : __rf.options.shrinkNumber |
||||
* \param outNum : __rf.options.numberOfOutputChannels |
||||
* \param gradNum : __rf.options.numberOfGradientOrientations |
||||
*/ |
||||
CV_WRAP virtual void getFeatures(const Mat &src, Mat &features, |
||||
const int gnrmRad, |
||||
const int gsmthRad, |
||||
const int shrink, |
||||
const int outNum, |
||||
const int gradNum) const = 0; |
||||
}; |
||||
|
||||
/*!
|
||||
* ... |
||||
*/ |
||||
CV_EXPORTS_W Ptr<RFFeatureGetter> createRFFeatureGetter(void); |
||||
|
||||
|
||||
|
||||
/*! \class StructuredEdgeDetection
|
||||
Prediction part of [P. Dollar and C. L. Zitnick. Structured Forests for Fast Edge Detection, 2013]. |
||||
*/ |
||||
class CV_EXPORTS_W StructuredEdgeDetection : public Algorithm |
||||
{ |
||||
public: |
||||
|
||||
/*!
|
||||
* The function detects edges in src and draw them to dst |
||||
* |
||||
* \param src : source image (RGB, float, in [0;1]) to detect edges |
||||
* \param dst : destination image (grayscale, float, in [0;1]) |
||||
* where edges are drawn |
||||
*/ |
||||
CV_WRAP virtual void detectEdges(const Mat &src, Mat &dst) const = 0; |
||||
}; |
||||
|
||||
/*!
|
||||
* The only constructor |
||||
* |
||||
* \param model : name of the file where the model is stored |
||||
* \param howToGetFeatures : optional object inheriting from RFFeatureGetter. |
||||
* You need it only if you would like to train your |
||||
* own forest, pass NULL otherwise |
||||
*/ |
||||
CV_EXPORTS_W Ptr<StructuredEdgeDetection> createStructuredEdgeDetection(const String &model, |
||||
const RFFeatureGetter *howToGetFeatures = NULL); |
||||
|
||||
} |
||||
|
||||
#endif /* __OPENCV_STRUCTURED_EDGE_DETECTION_HPP__ */ |
@ -0,0 +1,70 @@ |
||||
#include "opencv2/ximpgroc/structured_edge_detection.hpp" |
||||
|
||||
#include "opencv2/imgproc.hpp" |
||||
#include "opencv2/highgui.hpp" |
||||
|
||||
#include "opencv2/core/utility.hpp" |
||||
#include "opencv2/imgproc/types_c.h" |
||||
|
||||
#include <iostream> |
||||
|
||||
const char* keys = |
||||
{ |
||||
"{i || input image name}" |
||||
"{m || model name}" |
||||
"{o || output image name}" |
||||
}; |
||||
|
||||
int main( int argc, const char** argv ) |
||||
{ |
||||
bool printHelp = ( argc == 1 ); |
||||
printHelp = printHelp || ( argc == 2 && std::string(argv[1]) == "--help" ); |
||||
printHelp = printHelp || ( argc == 2 && std::string(argv[1]) == "-h" ); |
||||
|
||||
if ( printHelp ) |
||||
{ |
||||
printf("\nThis sample demonstrates structured forests for fast edge detection\n" |
||||
"Call:\n" |
||||
" structured_edge_detection -i=in_image_name -m=model_name [-o=out_image_name]\n\n"); |
||||
return 0; |
||||
} |
||||
|
||||
cv::CommandLineParser parser(argc, argv, keys); |
||||
if ( !parser.check() ) |
||||
{ |
||||
parser.printErrors(); |
||||
return -1; |
||||
} |
||||
|
||||
std::string modelFilename = parser.get<std::string>("m"); |
||||
std::string inFilename = parser.get<std::string>("i"); |
||||
std::string outFilename = parser.get<std::string>("o"); |
||||
|
||||
cv::Mat image = cv::imread(inFilename, 1); |
||||
if ( image.empty() ) |
||||
{ |
||||
printf("Cannot read image file: %s\n", inFilename.c_str()); |
||||
return -1; |
||||
} |
||||
|
||||
cv::cvtColor(image, image, CV_BGR2RGB); |
||||
image.convertTo(image, cv::DataType<float>::type, 1/255.0); |
||||
|
||||
cv::Mat edges(image.size(), image.type()); |
||||
|
||||
cv::Ptr<cv::StructuredEdgeDetection> pDollar = |
||||
cv::createStructuredEdgeDetection(modelFilename); |
||||
pDollar->detectEdges(image, edges); |
||||
|
||||
if ( outFilename == "" ) |
||||
{ |
||||
cv::namedWindow("edges", 1); |
||||
cv::imshow("edges", edges); |
||||
|
||||
cv::waitKey(0); |
||||
} |
||||
else |
||||
cv::imwrite(outFilename, 255*edges); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,87 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __ADVANCED_TYPES_HPP__ |
||||
#define __ADVANCED_TYPES_HPP__ |
||||
|
||||
#include <opencv2/core.hpp> |
||||
|
||||
/********************* Defines *********************/ |
||||
|
||||
#ifndef CV_SQR |
||||
# define CV_SQR(x) ((x)*(x)) |
||||
#endif |
||||
|
||||
#ifndef CV_CUBE |
||||
# define CV_CUBE(x) ((x)*(x)*(x)) |
||||
#endif |
||||
|
||||
#ifndef CV_INIT_VECTOR |
||||
# define CV_INIT_VECTOR(vname, type, ...) \ |
||||
static const type vname##_a[] = __VA_ARGS__; \
|
||||
std::vector <type> vname(vname##_a, \
|
||||
vname##_a + sizeof(vname##_a) / sizeof(*vname##_a)) |
||||
#endif |
||||
|
||||
/********************* Types *********************/ |
||||
|
||||
/*! fictitious type to highlight that function
|
||||
* can process n-channels arguments */ |
||||
typedef cv::Mat NChannelsMat; |
||||
|
||||
/********************* Functions *********************/ |
||||
|
||||
namespace cv |
||||
{ |
||||
|
||||
template <typename _Tp, typename _Tp2> inline |
||||
cv::Size_<_Tp> operator * (const _Tp2 &x, const cv::Size_<_Tp> &sz) |
||||
{ |
||||
return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(x*sz.width), cv::saturate_cast<_Tp>(x*sz.height)); |
||||
} |
||||
|
||||
template <typename _Tp, typename _Tp2> inline |
||||
cv::Size_<_Tp> operator / (const cv::Size_<_Tp> &sz, const _Tp2 &x) |
||||
{ |
||||
return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(sz.width/x), cv::saturate_cast<_Tp>(sz.height/x)); |
||||
} |
||||
|
||||
} // cv
|
||||
|
||||
#endif /* __ADVANCED_TYPES_HPP__ */ |
@ -0,0 +1,694 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include <vector> |
||||
#include <algorithm> |
||||
#include <iterator> |
||||
#include <iostream> |
||||
|
||||
#include "opencv2/ximpgroc/structured_edge_detection.hpp" |
||||
|
||||
#include "opencv2/imgproc.hpp" |
||||
|
||||
#include "opencv2/core.hpp" |
||||
#include "opencv2/core/core_c.h" |
||||
|
||||
#include "advanced_types.hpp" |
||||
#include "opencv2/core/types.hpp" |
||||
#include "opencv2/core/types_c.h" |
||||
|
||||
|
||||
/********************* Helper functions *********************/ |
||||
|
||||
/*!
|
||||
* Lightweight wrapper over cv::resize |
||||
* |
||||
* \param src : source image to resize |
||||
* \param dst : destination image size |
||||
* \return resized image |
||||
*/ |
||||
static cv::Mat imresize(const cv::Mat &src, const cv::Size &nSize) |
||||
{ |
||||
cv::Mat dst; |
||||
if (nSize.width < src.size().width |
||||
&& nSize.height < src.size().height) |
||||
cv::resize(src, dst, nSize, 0.0, 0.0, cv::INTER_AREA); |
||||
else |
||||
cv::resize(src, dst, nSize, 0.0, 0.0, cv::INTER_LINEAR); |
||||
|
||||
return dst; |
||||
} |
||||
|
||||
/*!
|
||||
* The function filters src with triangle filter with radius equal rad |
||||
* |
||||
* \param src : source image to filter |
||||
* \param rad : radius of filtering kernel |
||||
* \return filtering result |
||||
*/ |
||||
static cv::Mat imsmooth(const cv::Mat &src, const int rad) |
||||
{ |
||||
if (rad == 0) |
||||
return src; |
||||
else |
||||
{ |
||||
const float p = 12/rad/(rad + 2) - 2; |
||||
cv::Mat dst; |
||||
|
||||
if (rad <= 1) |
||||
{ |
||||
CV_INIT_VECTOR(kernelXY, float, {1/(p + 2), p/(p + 2), 1/(p + 2)}); |
||||
cv::sepFilter2D(src, dst, -1, kernelXY, kernelXY); |
||||
} |
||||
else |
||||
{ |
||||
float nrml = CV_SQR(rad + 1); |
||||
|
||||
std::vector <float> kernelXY(2*rad + 1); |
||||
for (int i = 0; i <= rad; ++i) |
||||
{ |
||||
kernelXY[2*rad - i] = (i + 1) / nrml; |
||||
kernelXY[i] = (i + 1) / nrml; |
||||
} |
||||
sepFilter2D(src, dst, -1, kernelXY, kernelXY); |
||||
} |
||||
|
||||
return dst; |
||||
} |
||||
} |
||||
|
||||
/*!
|
||||
* The function implements rgb to luv conversion in a way similar |
||||
* to UCSD computer vision toolbox |
||||
* |
||||
* \param src : source image (RGB, float, in [0;1]) to convert |
||||
* \return converted image in luv colorspace |
||||
*/ |
||||
static cv::Mat rgb2luv(const cv::Mat &src) |
||||
{ |
||||
cv::Mat dst(src.size(), src.type()); |
||||
|
||||
const float a = CV_CUBE(29.0f)/27; |
||||
const float y0 = 8.0f/a; |
||||
|
||||
const float mX[] = {0.430574f, 0.341550f, 0.178325f}; |
||||
const float mY[] = {0.222015f, 0.706655f, 0.071330f}; |
||||
const float mZ[] = {0.020183f, 0.129553f, 0.939180f}; |
||||
|
||||
const float maxi= 1.0f/270; |
||||
const float minu= -88*maxi; |
||||
const float minv= -134*maxi; |
||||
|
||||
const float un = 0.197833f; |
||||
const float vn = 0.468331f; |
||||
|
||||
// build (padded) lookup table for y->l conversion assuming y in [0,1]
|
||||
std::vector <float> lTable(1024); |
||||
for (int i = 0; i < 1024; ++i) |
||||
{ |
||||
float y = i/1024.0f; |
||||
float l = y > y0 ? 116*powf(y, 1.0f/3.0f) - 16 : y*a; |
||||
|
||||
lTable[i] = l*maxi; |
||||
} |
||||
for (int i = 0; i < 40; ++i) |
||||
lTable.push_back(*--lTable.end()); |
||||
|
||||
const int nchannels = 3; |
||||
|
||||
for (int i = 0; i < src.rows; ++i) |
||||
{ |
||||
const float *pSrc = src.ptr<float>(i); |
||||
float *pDst = dst.ptr<float>(i); |
||||
|
||||
for (int j = 0; j < src.cols*nchannels; j += nchannels) |
||||
{ |
||||
const float rgb[] = {pSrc[j + 0], pSrc[j + 1], pSrc[j + 2]}; |
||||
|
||||
const float xyz[] = {mX[0]*rgb[0] + mX[1]*rgb[1] + mX[2]*rgb[2], |
||||
mY[0]*rgb[0] + mY[1]*rgb[1] + mY[2]*rgb[2], |
||||
mZ[0]*rgb[0] + mZ[1]*rgb[1] + mZ[2]*rgb[2]}; |
||||
const float nz = 1.0f/(xyz[0] + 15*xyz[1] + 3*xyz[2] + 1e-35); |
||||
|
||||
const float l = pDst[j] = lTable[cvFloor(1024*xyz[1])]; |
||||
|
||||
pDst[j + 1] = l * (13*4*xyz[0]*nz - 13*un) - minu;; |
||||
pDst[j + 2] = l * (13*9*xyz[1]*nz - 13*vn) - minv; |
||||
} |
||||
} |
||||
|
||||
return dst; |
||||
} |
||||
|
||||
/*!
|
||||
* The function computes gradient magnitude and weighted (with magnitude) |
||||
* orientation histogram. Magnitude is additionally normalized |
||||
* by dividing on imsmooth(M, gnrmRad) + 0.01; |
||||
* |
||||
* \param src : source image |
||||
* \param magnitude : gradient magnitude |
||||
* \param histogram : gradient orientation nBins-channels histogram |
||||
* \param nBins : number of gradient orientations |
||||
* \param pSize : factor to downscale histogram |
||||
* \param gnrmRad : radius for magnitude normalization |
||||
*/ |
||||
static void gradientHist(const cv::Mat &src, cv::Mat &magnitude, cv::Mat &histogram, |
||||
const int nBins, const int pSize, const int gnrmRad) |
||||
{ |
||||
cv::Mat phase, Dx, Dy; |
||||
|
||||
magnitude.create( src.size(), cv::DataType<float>::type ); |
||||
phase.create( src.size(), cv::DataType<float>::type ); |
||||
histogram.create( src.size()/float(pSize), |
||||
CV_MAKETYPE(cv::DataType<float>::type, nBins) ); |
||||
|
||||
histogram.setTo(0); |
||||
|
||||
cv::Sobel( src, Dx, cv::DataType<float>::type, |
||||
1, 0, 1, 1.0, 0.0, cv::BORDER_REFLECT ); |
||||
cv::Sobel( src, Dy, cv::DataType<float>::type, |
||||
0, 1, 1, 1.0, 0.0, cv::BORDER_REFLECT ); |
||||
|
||||
int nchannels = src.channels(); |
||||
|
||||
for (int i = 0; i < src.rows; ++i) |
||||
{ |
||||
const float *pDx = Dx.ptr<float>(i); |
||||
const float *pDy = Dy.ptr<float>(i); |
||||
|
||||
float *pMagnitude = magnitude.ptr<float>(i); |
||||
float *pPhase = phase.ptr<float>(i); |
||||
|
||||
for (int j = 0; j < src.cols*nchannels; j += nchannels) |
||||
{ |
||||
float fMagn = -1e-5, fdx, fdy; |
||||
for (int k = 0; k < nchannels; ++k) |
||||
{ |
||||
float cMagn = CV_SQR( pDx[j + k] ) + CV_SQR( pDy[j + k] ); |
||||
if (cMagn > fMagn) |
||||
{ |
||||
fMagn = cMagn; |
||||
fdx = pDx[j + k]; |
||||
fdy = pDy[j + k]; |
||||
} |
||||
} |
||||
|
||||
pMagnitude[j/nchannels] = std::sqrtf(fMagn); |
||||
|
||||
float angle = cv::fastAtan2(fdy, fdx) / 180.0f - 1.0f * (fdy < 0); |
||||
if (std::fabs(fdx) + std::fabs(fdy) < 1e-5) |
||||
angle = 0.5f; |
||||
pPhase[j/nchannels] = angle; |
||||
} |
||||
} |
||||
|
||||
magnitude /= imsmooth( magnitude, gnrmRad ) |
||||
+ 0.01*cv::Mat::ones( magnitude.size(), magnitude.type() ); |
||||
|
||||
for (int i = 0; i < phase.rows; ++i) |
||||
{ |
||||
const float *pPhase = phase.ptr<float>(i); |
||||
const float *pMagn = magnitude.ptr<float>(i); |
||||
|
||||
float *pHist = histogram.ptr<float>(i/pSize); |
||||
|
||||
for (int j = 0; j < phase.cols; ++j) |
||||
pHist[cvRound((j/pSize + pPhase[j])*nBins)] += pMagn[j] / CV_SQR(pSize); |
||||
} |
||||
} |
||||
|
||||
/********************* RFFeatureGetter class *********************/ |
||||
|
||||
namespace cv |
||||
{ |
||||
|
||||
class RFFeatureGetterImpl : public RFFeatureGetter |
||||
{ |
||||
public: |
||||
/*!
|
||||
* Default constructor |
||||
*/ |
||||
RFFeatureGetterImpl() : name("RFFeatureGetter"){} |
||||
|
||||
/*!
|
||||
* The method extracts features from img and store them to features. |
||||
* Extracted features are appropriate for StructuredEdgeDetection::predictEdges. |
||||
* |
||||
* \param src : source image (RGB, float, in [0;1]) to extract features |
||||
* \param features : destination feature image |
||||
* |
||||
* \param gnrmRad : __rf.options.gradientNormalizationRadius |
||||
* \param gsmthRad : __rf.options.gradientSmoothingRadius |
||||
* \param shrink : __rf.options.shrinkNumber |
||||
* \param outNum : __rf.options.numberOfOutputChannels |
||||
* \param gradNum : __rf.options.numberOfGradientOrientations |
||||
*/ |
||||
virtual void getFeatures(const cv::Mat &src, NChannelsMat &features, |
||||
const int gnrmRad, const int gsmthRad, |
||||
const int shrink, const int outNum, const int gradNum) const |
||||
{ |
||||
cv::Mat luvImg = rgb2luv(src); |
||||
|
||||
std::vector <cv::Mat> featureArray; |
||||
|
||||
cv::Size nSize = src.size() / float(shrink); |
||||
split( imresize(luvImg, nSize), featureArray ); |
||||
|
||||
CV_INIT_VECTOR(scales, float, {1.0f, 0.5f}); |
||||
|
||||
for (size_t i = 0; i < scales.size(); ++i) |
||||
{ |
||||
int pSize = std::max( 1, int(shrink*scales[i]) ); |
||||
|
||||
cv::Mat magnitude, histogram; |
||||
gradientHist(/**/ imsmooth(imresize(luvImg, scales[i]*src.size()), gsmthRad), |
||||
magnitude, histogram, gradNum, pSize, gnrmRad /**/); |
||||
|
||||
featureArray.push_back(/**/ imresize( magnitude, nSize ).clone() /**/); |
||||
featureArray.push_back(/**/ imresize( histogram, nSize ).clone() /**/); |
||||
} |
||||
|
||||
// Mixing
|
||||
int resType = CV_MAKETYPE(cv::DataType<float>::type, outNum); |
||||
features.create(nSize, resType); |
||||
|
||||
std::vector <int> fromTo; |
||||
for (int i = 0; i < 2*outNum; ++i) |
||||
fromTo.push_back(i/2); |
||||
|
||||
mixChannels(featureArray, features, fromTo); |
||||
} |
||||
|
||||
protected: |
||||
/*! algorithm name */ |
||||
String name; |
||||
}; |
||||
|
||||
Ptr<RFFeatureGetter> createRFFeatureGetter(void) |
||||
{ |
||||
return makePtr<RFFeatureGetterImpl>(); |
||||
} |
||||
|
||||
}; |
||||
|
||||
/********************* StructuredEdgeDetection class *********************/ |
||||
|
||||
namespace cv |
||||
{ |
||||
|
||||
class StructuredEdgeDetectionImpl : public StructuredEdgeDetection |
||||
{ |
||||
public: |
||||
/*!
|
||||
* This constructor loads __rf model from filename |
||||
* |
||||
* \param filename : name of the file where the model is stored |
||||
*/ |
||||
StructuredEdgeDetectionImpl(const cv::String &filename, |
||||
const RFFeatureGetter *howToGetFeatures) |
||||
: name("StructuredEdgeDetection"), |
||||
howToGetFeatures( howToGetFeatures != NULL |
||||
? howToGetFeatures |
||||
: createRFFeatureGetter() ) |
||||
{ |
||||
cv::FileStorage modelFile(filename, FileStorage::READ); |
||||
CV_Assert( modelFile.isOpened() ); |
||||
|
||||
__rf.options.stride |
||||
= modelFile["options"]["stride"]; |
||||
__rf.options.shrinkNumber |
||||
= modelFile["options"]["shrinkNumber"]; |
||||
__rf.options.patchSize |
||||
= modelFile["options"]["patchSize"]; |
||||
__rf.options.patchInnerSize |
||||
= modelFile["options"]["patchInnerSize"]; |
||||
|
||||
__rf.options.numberOfGradientOrientations |
||||
= modelFile["options"]["numberOfGradientOrientations"]; |
||||
__rf.options.gradientSmoothingRadius |
||||
= modelFile["options"]["gradientSmoothingRadius"]; |
||||
__rf.options.regFeatureSmoothingRadius |
||||
= modelFile["options"]["regFeatureSmoothingRadius"]; |
||||
__rf.options.ssFeatureSmoothingRadius |
||||
= modelFile["options"]["ssFeatureSmoothingRadius"]; |
||||
__rf.options.gradientNormalizationRadius |
||||
= modelFile["options"]["gradientNormalizationRadius"]; |
||||
|
||||
__rf.options.selfsimilarityGridSize |
||||
= modelFile["options"]["selfsimilarityGridSize"]; |
||||
|
||||
__rf.options.numberOfTrees |
||||
= modelFile["options"]["numberOfTrees"]; |
||||
__rf.options.numberOfTreesToEvaluate |
||||
= modelFile["options"]["numberOfTreesToEvaluate"]; |
||||
|
||||
__rf.options.numberOfOutputChannels = |
||||
2*(__rf.options.numberOfGradientOrientations + 1) + 3; |
||||
//--------------------------------------------
|
||||
|
||||
cv::FileNode childs = modelFile["childs"]; |
||||
cv::FileNode featureIds = modelFile["featureIds"]; |
||||
|
||||
std::vector <int> currentTree; |
||||
|
||||
for(cv::FileNodeIterator it = childs.begin(); |
||||
it != childs.end(); ++it) |
||||
{ |
||||
(*it) >> currentTree; |
||||
std::copy(currentTree.begin(), currentTree.end(), |
||||
std::back_inserter(__rf.childs)); |
||||
} |
||||
|
||||
for(cv::FileNodeIterator it = featureIds.begin(); |
||||
it != featureIds.end(); ++it) |
||||
{ |
||||
(*it) >> currentTree; |
||||
std::copy(currentTree.begin(), currentTree.end(), |
||||
std::back_inserter(__rf.featureIds)); |
||||
} |
||||
|
||||
cv::FileNode thresholds = modelFile["thresholds"]; |
||||
std::vector <float> fcurrentTree; |
||||
|
||||
for(cv::FileNodeIterator it = thresholds.begin(); |
||||
it != thresholds.end(); ++it) |
||||
{ |
||||
(*it) >> fcurrentTree; |
||||
std::copy(fcurrentTree.begin(), fcurrentTree.end(), |
||||
std::back_inserter(__rf.thresholds)); |
||||
} |
||||
|
||||
cv::FileNode edgeBoundaries = modelFile["edgeBoundaries"]; |
||||
cv::FileNode edgeBins = modelFile["edgeBins"]; |
||||
|
||||
for(cv::FileNodeIterator it = edgeBoundaries.begin(); |
||||
it != edgeBoundaries.end(); ++it) |
||||
{ |
||||
(*it) >> currentTree; |
||||
std::copy(currentTree.begin(), currentTree.end(), |
||||
std::back_inserter(__rf.edgeBoundaries)); |
||||
} |
||||
|
||||
for(cv::FileNodeIterator it = edgeBins.begin(); |
||||
it != edgeBins.end(); ++it) |
||||
{ |
||||
(*it) >> currentTree; |
||||
std::copy(currentTree.begin(), currentTree.end(), |
||||
std::back_inserter(__rf.edgeBins)); |
||||
} |
||||
|
||||
__rf.numberOfTreeNodes = int( __rf.childs.size() ) / __rf.options.numberOfTrees; |
||||
} |
||||
|
||||
/*!
|
||||
* The function detects edges in src and draw them to dst |
||||
* |
||||
* \param src : source image (RGB, float, in [0;1]) to detect edges |
||||
* \param dst : destination image (grayscale, float, in [0;1]) |
||||
* where edges are drawn |
||||
*/ |
||||
void detectEdges(const cv::Mat &src, cv::Mat &dst) const |
||||
{ |
||||
CV_Assert( src.type() == CV_32FC3 ); |
||||
|
||||
dst.create( src.size(), cv::DataType<float>::type ); |
||||
|
||||
int padding = ( __rf.options.patchSize |
||||
- __rf.options.patchInnerSize )/2; |
||||
|
||||
cv::Mat nSrc; |
||||
copyMakeBorder( src, nSrc, padding, padding, |
||||
padding, padding, BORDER_REFLECT ); |
||||
|
||||
NChannelsMat features; |
||||
createRFFeatureGetter()->getFeatures( nSrc, features, |
||||
__rf.options.gradientNormalizationRadius, |
||||
__rf.options.gradientSmoothingRadius, |
||||
__rf.options.shrinkNumber, |
||||
__rf.options.numberOfOutputChannels, |
||||
__rf.options.numberOfGradientOrientations ); |
||||
predictEdges( features, dst ); |
||||
} |
||||
|
||||
protected: |
||||
/*!
|
||||
* Private method used by process method. The function |
||||
* predict edges in n-channel feature image and store them to dst. |
||||
* |
||||
* \param features : source image (n-channels, float) to detect edges |
||||
* \param dst : destination image (grayscale, float, in [0;1]) where edges are drawn |
||||
*/ |
||||
void predictEdges(const NChannelsMat &features, cv::Mat &dst) const |
||||
{ |
||||
int shrink = __rf.options.shrinkNumber; |
||||
int rfs = __rf.options.regFeatureSmoothingRadius; |
||||
int sfs = __rf.options.ssFeatureSmoothingRadius; |
||||
|
||||
int nTreesEval = __rf.options.numberOfTreesToEvaluate; |
||||
int nTrees = __rf.options.numberOfTrees; |
||||
int nTreesNodes = __rf.numberOfTreeNodes; |
||||
|
||||
const int nchannels = features.channels(); |
||||
int pSize = __rf.options.patchSize; |
||||
|
||||
int nFeatures = CV_SQR(pSize/shrink)*nchannels; |
||||
int outNum = __rf.options.numberOfOutputChannels; |
||||
|
||||
int stride = __rf.options.stride; |
||||
int ipSize = __rf.options.patchInnerSize; |
||||
int gridSize = __rf.options.selfsimilarityGridSize; |
||||
|
||||
const int height = cvCeil( double(features.rows*shrink - pSize) / stride ); |
||||
const int width = cvCeil( double(features.cols*shrink - pSize) / stride ); |
||||
// image size in patches with overlapping
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
NChannelsMat regFeatures = imsmooth(features, cvRound(rfs / float(shrink))); |
||||
NChannelsMat ssFeatures = imsmooth(features, cvRound(sfs / float(shrink))); |
||||
|
||||
NChannelsMat indexes(height, width, CV_MAKETYPE(DataType<int>::type, nTreesEval)); |
||||
|
||||
std::vector <int> offsetI(/**/ CV_SQR(pSize/shrink)*nchannels, 0); |
||||
for (int i = 0; i < CV_SQR(pSize/shrink)*nchannels; ++i) |
||||
{ |
||||
int z = i / CV_SQR(pSize/shrink); |
||||
int y = ( i % CV_SQR(pSize/shrink) )/(pSize/shrink); |
||||
int x = ( i % CV_SQR(pSize/shrink) )%(pSize/shrink); |
||||
|
||||
offsetI[i] = x*features.cols*nchannels + y*nchannels + z; |
||||
} |
||||
// lookup table for mapping linear index to offsets
|
||||
|
||||
std::vector <int> offsetE(/**/ CV_SQR(ipSize)*outNum, 0); |
||||
for (int i = 0; i < CV_SQR(ipSize)*outNum; ++i) |
||||
{ |
||||
int z = i / CV_SQR(ipSize); |
||||
int y = ( i % CV_SQR(ipSize) )/ipSize; |
||||
int x = ( i % CV_SQR(ipSize) )%ipSize; |
||||
|
||||
offsetE[i] = x*dst.cols*outNum + y*outNum + z; |
||||
} |
||||
// lookup table for mapping linear index to offsets
|
||||
|
||||
std::vector <int> offsetX( CV_SQR(gridSize)*(CV_SQR(gridSize) - 1)/2 * nchannels, 0); |
||||
std::vector <int> offsetY( CV_SQR(gridSize)*(CV_SQR(gridSize) - 1)/2 * nchannels, 0); |
||||
|
||||
int hc = cvRound( (pSize/shrink) / (2.0*gridSize) ); |
||||
// half of cell
|
||||
std::vector <int> gridPositions; |
||||
for(int i = 0; i < gridSize; i++) |
||||
gridPositions.push_back( (i+1)*(pSize/shrink + 2*hc - 1)/(gridSize + 1.0) - hc + 0.5 ); |
||||
|
||||
for (int i = 0, n = 0; i < CV_SQR(gridSize)*nchannels; ++i) |
||||
for (int j = (i%CV_SQR(gridSize)) + 1; j < CV_SQR(gridSize); ++j, ++n) |
||||
{ |
||||
int z = i / CV_SQR(gridSize); |
||||
|
||||
int x1 = gridPositions[i%CV_SQR(gridSize)%gridSize]; |
||||
int y1 = gridPositions[i%CV_SQR(gridSize)/gridSize]; |
||||
|
||||
int x2 = gridPositions[j%gridSize]; |
||||
int y2 = gridPositions[j/gridSize]; |
||||
|
||||
offsetX[n] = x1*features.cols*nchannels + y1*nchannels + z; |
||||
offsetY[n] = x2*features.cols*nchannels + y2*nchannels + z; |
||||
} |
||||
// lookup tables for mapping linear index to offset pairs
|
||||
|
||||
for (int i = 0; i < height; ++i) |
||||
{ |
||||
float *regFeaturesPtr = regFeatures.ptr<float>(i*stride/shrink); |
||||
float *ssFeaturesPtr = ssFeatures.ptr<float>(i*stride/shrink); |
||||
|
||||
int *indexPtr = indexes.ptr<int>(i); |
||||
|
||||
for (int j = 0, k = 0; j < width; ++k, j += !(k %= nTreesEval)) |
||||
// for j,k in [0;width)x[0;nTreesEval)
|
||||
{ |
||||
int baseNode = ( ((i + j)%(2*nTreesEval) + k)%nTrees )*nTreesNodes; |
||||
int currentNode = baseNode; |
||||
// select root node of the tree to evaluate
|
||||
|
||||
int offset = (j*stride/shrink)*nchannels; |
||||
while ( __rf.childs[currentNode] != 0 ) |
||||
{ |
||||
int currentId = __rf.featureIds[currentNode]; |
||||
float currentFeature; |
||||
|
||||
if (currentId >= nFeatures) |
||||
{ |
||||
int xIndex = offsetX[currentId - nFeatures]; |
||||
float A = ssFeaturesPtr[offset + xIndex]; |
||||
|
||||
int yIndex = offsetY[currentId - nFeatures]; |
||||
float B = ssFeaturesPtr[offset + yIndex]; |
||||
|
||||
currentFeature = A - B; |
||||
} |
||||
else |
||||
currentFeature = regFeaturesPtr[offset + offsetI[currentId]]; |
||||
|
||||
// compare feature to threshold and move left or right accordingly
|
||||
if (currentFeature < __rf.thresholds[currentNode]) |
||||
currentNode = baseNode + __rf.childs[currentNode] - 1; |
||||
else |
||||
currentNode = baseNode + __rf.childs[currentNode]; |
||||
} |
||||
|
||||
indexPtr[j*nTreesEval + k] = currentNode; |
||||
} |
||||
} |
||||
|
||||
NChannelsMat dstM(dst.size(), |
||||
CV_MAKETYPE(DataType<float>::type, outNum)); |
||||
dstM.setTo(0); |
||||
|
||||
float step = 2.0f * CV_SQR(stride) / CV_SQR(ipSize) / nTreesEval; |
||||
for (int i = 0; i < height; ++i) |
||||
{ |
||||
int *pIndex = indexes.ptr<int>(i); |
||||
float *pDst = dstM.ptr<float>(i*stride); |
||||
|
||||
for (int j = 0, k = 0; j < width; ++k, j += !(k %= nTreesEval)) |
||||
{// for j,k in [0;width)x[0;nTreesEval)
|
||||
|
||||
int currentNode = pIndex[j*nTreesEval + k]; |
||||
|
||||
int start = __rf.edgeBoundaries[currentNode]; |
||||
int finish = __rf.edgeBoundaries[currentNode + 1]; |
||||
|
||||
if (start == finish) |
||||
continue; |
||||
|
||||
int offset = j*stride*outNum; |
||||
for (int p = start; p < finish; ++p) |
||||
pDst[offset + offsetE[__rf.edgeBins[p]]] += step; |
||||
} |
||||
} |
||||
|
||||
cv::reduce( dstM.reshape(1, dstM.total() ), dstM, 2, CV_REDUCE_SUM); |
||||
imsmooth( dstM.reshape(1, dst.rows), 1 ).copyTo(dst); |
||||
} |
||||
|
||||
/********************* Members *********************/ |
||||
protected: |
||||
/*! algorithm name */ |
||||
String name; |
||||
|
||||
/*! optional feature getter (getFeatures method) */ |
||||
const RFFeatureGetter *howToGetFeatures; |
||||
|
||||
/*! random forest used to detect edges */ |
||||
struct RandomForest |
||||
{ |
||||
/*! random forest options, e.g. number of trees */ |
||||
struct RandomForestOptions |
||||
{ |
||||
// model params
|
||||
|
||||
int numberOfOutputChannels; /*!< number of edge orientation bins for output */ |
||||
|
||||
int patchSize; /*!< width of image patches */ |
||||
int patchInnerSize; /*!< width of predicted part inside patch*/ |
||||
|
||||
// feature params
|
||||
|
||||
int regFeatureSmoothingRadius; /*!< radius for smoothing of regular features
|
||||
* (using convolution with triangle filter) */ |
||||
|
||||
int ssFeatureSmoothingRadius; /*!< radius for smoothing of additional features
|
||||
* (using convolution with triangle filter) */ |
||||
|
||||
int shrinkNumber; /*!< amount to shrink channels */ |
||||
|
||||
int numberOfGradientOrientations; /*!< number of orientations per gradient scale */ |
||||
|
||||
int gradientSmoothingRadius; /*!< radius for smoothing of gradients
|
||||
* (using convolution with triangle filter) */ |
||||
|
||||
int gradientNormalizationRadius; /*!< gradient normalization radius */ |
||||
int selfsimilarityGridSize; /*!< number of self similarity cells */ |
||||
|
||||
// detection params
|
||||
int numberOfTrees; /*!< number of trees in forest to train */ |
||||
int numberOfTreesToEvaluate; /*!< number of trees to evaluate per location */ |
||||
|
||||
int stride; /*!< stride at which to compute edges */ |
||||
|
||||
} options; |
||||
|
||||
int numberOfTreeNodes; |
||||
|
||||
std::vector <int> featureIds; /*!< feature coordinate thresholded at k-th node */ |
||||
std::vector <float> thresholds; /*!< threshold applied to featureIds[k] at k-th node */ |
||||
std::vector <int> childs; /*!< k --> child[k] - 1, child[k] */ |
||||
|
||||
std::vector <int> edgeBoundaries; /*!< ... */ |
||||
std::vector <int> edgeBins; /*!< ... */ |
||||
} __rf; |
||||
}; |
||||
|
||||
Ptr<StructuredEdgeDetection> createStructuredEdgeDetection(const String &model, |
||||
const RFFeatureGetter *howToGetFeatures) |
||||
{ |
||||
return makePtr<StructuredEdgeDetectionImpl>(model, howToGetFeatures); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,39 @@ |
||||
#include "test_precomp.hpp" |
||||
|
||||
namespace cvtest |
||||
{ |
||||
|
||||
TEST(ximpgroc_StructuredEdgeDetection, regression) |
||||
{ |
||||
cv::String dir = "C:/Users/Yury/Projects/opencv/sources/opencv_contrib/modules/ximpgroc/testdata/";//cvtest::TS::ptr()->get_data_path();
|
||||
int nTests = 12; |
||||
float threshold = 0.01; |
||||
|
||||
cv::String modelName = dir + "model.yml.gz"; |
||||
cv::Ptr<cv::StructuredEdgeDetection> pDollar = |
||||
cv::createStructuredEdgeDetection(modelName); |
||||
|
||||
for (int i = 0; i < nTests; ++i) |
||||
{ |
||||
cv::String srcName = dir + cv::format( "sources/%02d.png", i + 1); |
||||
cv::Mat src = cv::imread( srcName, 1 ); |
||||
|
||||
cv::String previousResultName = dir + cv::format( "results/%02d.png", i + 1 ); |
||||
cv::Mat previousResult = cv::imread( previousResultName, 0 ); |
||||
previousResult.convertTo( previousResult, cv::DataType<float>::type, 1/255.0 ); |
||||
|
||||
cv::cvtColor( src, src, CV_BGR2RGB ); |
||||
src.convertTo( src, cv::DataType<float>::type, 1/255.0 ); |
||||
|
||||
cv::Mat currentResult( src.size(), src.type() ); |
||||
pDollar->detectEdges( src, currentResult ); |
||||
|
||||
cv::Mat sqrError = ( currentResult - previousResult ) |
||||
.mul( currentResult - previousResult ); |
||||
cv::Scalar mse = cv::sum(sqrError) / cv::Scalar::all( sqrError.total() ); |
||||
|
||||
EXPECT_LE( mse[0], threshold ); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,3 @@ |
||||
#include "test_precomp.hpp" |
||||
|
||||
CV_TEST_MAIN("ximpgroc") |
@ -0,0 +1,20 @@ |
||||
#ifdef __GNUC__ |
||||
# pragma GCC diagnostic ignored "-Wmissing-declarations" |
||||
# if defined __clang__ || defined __APPLE__ |
||||
# pragma GCC diagnostic ignored "-Wmissing-prototypes" |
||||
# pragma GCC diagnostic ignored "-Wextra" |
||||
# endif |
||||
#endif |
||||
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__ |
||||
#define __OPENCV_TEST_PRECOMP_HPP__ |
||||
|
||||
#include "opencv2/core.hpp" |
||||
#include "opencv2/imgproc.hpp" |
||||
#include "opencv2/imgproc/types_c.h" |
||||
#include "opencv2/highgui.hpp" |
||||
#include "opencv2/ximpgroc.hpp" |
||||
#include "opencv2/ts.hpp" |
||||
#include <iostream> |
||||
|
||||
#endif |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 375 KiB |
After Width: | Height: | Size: 471 KiB |
After Width: | Height: | Size: 520 KiB |
After Width: | Height: | Size: 393 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 309 KiB |
After Width: | Height: | Size: 257 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 425 KiB |
After Width: | Height: | Size: 181 KiB |
After Width: | Height: | Size: 505 KiB |
After Width: | Height: | Size: 502 KiB |