Merge branch 'master' into text_detector_dnn

pull/1399/head
Vladislav Sovrasov 7 years ago
commit c33629e053
  1. 2
      modules/aruco/tutorials/aruco_detection/aruco_detection.markdown
  2. 22
      modules/bgsegm/src/bgfg_gmg.cpp
  3. 2
      modules/ccalib/include/opencv2/ccalib.hpp
  4. 4
      modules/ccalib/include/opencv2/ccalib/omnidir.hpp
  5. 4
      modules/ccalib/src/ccalib.cpp
  6. 20
      modules/ccalib/src/multicalib.cpp
  7. 48
      modules/ccalib/src/omnidir.cpp
  8. 14
      modules/datasets/samples/tr_icdar_benchmark.cpp
  9. 8
      modules/datasets/samples/tr_svt_benchmark.cpp
  10. 2
      modules/face/include/opencv2/face/facerec.hpp
  11. 4
      modules/face/src/eigen_faces.cpp
  12. 4
      modules/face/src/fisher_faces.cpp
  13. 4
      modules/face/src/lbph_faces.cpp
  14. 2
      modules/face/tutorials/face_tutorial.markdown
  15. 6
      modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp
  16. 2
      modules/optflow/src/simpleflow.cpp
  17. 1
      modules/plot/include/opencv2/plot.hpp
  18. 41
      modules/plot/samples/plot_demo.cpp
  19. 18
      modules/plot/src/plot.cpp
  20. 2
      modules/rgbd/include/opencv2/rgbd/linemod.hpp
  21. 31
      modules/saliency/src/BING/FilterTIG.cpp
  22. 5
      modules/sfm/CMakeLists.txt
  23. 8
      modules/stereo/include/opencv2/stereo/matching.hpp
  24. 8
      modules/stereo/perf/perf_bm.cpp
  25. 8
      modules/stereo/perf/perf_descriptor.cpp
  26. 21
      modules/stereo/test/test_block_matching.cpp
  27. 16
      modules/stereo/test/test_descriptors.cpp
  28. 2
      modules/structured_light/include/opencv2/structured_light/structured_light.hpp
  29. 6
      modules/structured_light/src/graycodepattern.cpp
  30. 4
      modules/structured_light/src/sinusoidalpattern.cpp
  31. 270
      modules/text/samples/webcam_demo.cpp
  32. 116
      modules/text/tutorials/install_tesseract/install_tesseract.markdown
  33. 10
      modules/text/tutorials/table_of_content_text.markdown
  34. 2
      modules/tracking/include/opencv2/tracking/tracker.hpp
  35. 4
      modules/tracking/samples/tutorial_multitracker.cpp
  36. 26
      modules/tracking/src/gtrTracker.cpp
  37. 9
      modules/tracking/src/tldTracker.cpp
  38. 4
      modules/tracking/src/trackerKCF.cpp
  39. 4
      modules/tracking/test/test_trackers.cpp
  40. 4
      modules/xfeatures2d/perf/perf_surf.cpp
  41. 55
      modules/xfeatures2d/src/harris_lapace_detector.cpp
  42. 94
      modules/xfeatures2d/src/opencl/surf.cl
  43. 216
      modules/xfeatures2d/src/sift.cpp
  44. 2
      modules/xfeatures2d/src/surf.cpp
  45. 14
      modules/xfeatures2d/src/surf.ocl.cpp
  46. 61
      modules/xfeatures2d/test/test_features2d.cpp
  47. 4
      modules/xfeatures2d/test/test_precomp.hpp
  48. 24
      modules/xfeatures2d/test/test_rotation_and_scale_invariance.cpp
  49. 79
      modules/xfeatures2d/test/test_surf.ocl.cpp
  50. 1
      modules/ximgproc/README.md
  51. 1
      modules/ximgproc/include/opencv2/ximgproc.hpp
  52. 31
      modules/ximgproc/include/opencv2/ximgproc/peilin.hpp
  53. 59
      modules/ximgproc/samples/peilin.cpp
  54. BIN
      modules/ximgproc/samples/peilin_plane.png
  55. BIN
      modules/ximgproc/samples/peilin_shape.png
  56. 46
      modules/ximgproc/src/dtfilter_cpu.inl.hpp
  57. 14
      modules/ximgproc/src/fgs_filter.cpp
  58. 4
      modules/ximgproc/src/joint_bilateral_filter.cpp
  59. 57
      modules/ximgproc/src/peilin.cpp
  60. 2
      modules/ximgproc/test/test_domain_transform.cpp
  61. 2
      modules/ximgproc/test/test_joint_bilateral_filter.cpp
  62. 4
      modules/ximgproc/test/test_structured_edge_detection.cpp

@ -318,7 +318,7 @@ A basic full example for pose estimation from single markers:
if (ids.size() > 0) {
cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);
std::vector<cv::Mat> rvecs, tvecs;
std::vector<cv::Vec3d> rvecs, tvecs;
cv::aruco::estimatePoseSingleMarkers(corners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs);
// draw axis for each marker
for(int i=0; i<ids.size(); i++)

@ -194,7 +194,7 @@ private:
String name_;
Mat_<int> nfeatures_;
Mat_<unsigned int> colors_;
Mat_<int> colors_;
Mat_<float> weights_;
Mat buf_;
@ -223,7 +223,7 @@ void BackgroundSubtractorGMGImpl::initialize(Size frameSize, double minVal, doub
nfeatures_.setTo(Scalar::all(0));
}
static float findFeature(unsigned int color, const unsigned int* colors, const float* weights, int nfeatures)
static float findFeature(int color, const int* colors, const float* weights, int nfeatures)
{
for (int i = 0; i < nfeatures; ++i)
{
@ -248,7 +248,7 @@ static void normalizeHistogram(float* weights, int nfeatures)
}
}
static bool insertFeature(unsigned int color, float weight, unsigned int* colors, float* weights, int& nfeatures, int maxFeatures)
static bool insertFeature(int color, float weight, int* colors, float* weights, int& nfeatures, int maxFeatures)
{
int idx = -1;
for (int i = 0; i < nfeatures; ++i)
@ -266,7 +266,7 @@ static bool insertFeature(unsigned int color, float weight, unsigned int* colors
{
// move feature to beginning of list
::memmove(colors + 1, colors, idx * sizeof(unsigned int));
::memmove(colors + 1, colors, idx * sizeof(int));
::memmove(weights + 1, weights, idx * sizeof(float));
colors[0] = color;
@ -276,7 +276,7 @@ static bool insertFeature(unsigned int color, float weight, unsigned int* colors
{
// discard oldest feature
::memmove(colors + 1, colors, (nfeatures - 1) * sizeof(unsigned int));
::memmove(colors + 1, colors, (nfeatures - 1) * sizeof(int));
::memmove(weights + 1, weights, (nfeatures - 1) * sizeof(float));
colors[0] = color;
@ -297,7 +297,7 @@ static bool insertFeature(unsigned int color, float weight, unsigned int* colors
template <typename T> struct Quantization
{
static unsigned int apply(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels)
static int apply(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels)
{
const T* src = static_cast<const T*>(src_);
src += x * cn;
@ -313,7 +313,7 @@ template <typename T> struct Quantization
class GMG_LoopBody : public ParallelLoopBody
{
public:
GMG_LoopBody(const Mat& frame, const Mat& fgmask, const Mat_<int>& nfeatures, const Mat_<unsigned int>& colors, const Mat_<float>& weights,
GMG_LoopBody(const Mat& frame, const Mat& fgmask, const Mat_<int>& nfeatures, const Mat_<int>& colors, const Mat_<float>& weights,
int maxFeatures, double learningRate, int numInitializationFrames, int quantizationLevels, double backgroundPrior, double decisionThreshold,
double maxVal, double minVal, int frameNum, bool updateBackgroundModel) :
frame_(frame), fgmask_(fgmask), nfeatures_(nfeatures), colors_(colors), weights_(weights),
@ -331,7 +331,7 @@ private:
mutable Mat_<uchar> fgmask_;
mutable Mat_<int> nfeatures_;
mutable Mat_<unsigned int> colors_;
mutable Mat_<int> colors_;
mutable Mat_<float> weights_;
int maxFeatures_;
@ -349,7 +349,7 @@ private:
void GMG_LoopBody::operator() (const Range& range) const
{
typedef unsigned int (*func_t)(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels);
typedef int (*func_t)(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels);
static const func_t funcs[] =
{
Quantization<uchar>::apply,
@ -375,10 +375,10 @@ void GMG_LoopBody::operator() (const Range& range) const
for (int x = 0; x < frame_.cols; ++x, ++featureIdx)
{
int nfeatures = nfeatures_row[x];
unsigned int* colors = colors_[featureIdx];
int* colors = colors_[featureIdx];
float* weights = weights_[featureIdx];
unsigned int newFeatureColor = func(frame_row, x, cn, minVal_, maxVal_, quantizationLevels_);
int newFeatureColor = func(frame_row, x, cn, minVal_, maxVal_, quantizationLevels_);
bool isForeground = false;

@ -71,7 +71,7 @@ public:
bool isInitialized();
void getPatternPoints(OutputArray original_points);
void getPatternPoints(std::vector<KeyPoint>& original_points);
/**<
Returns a vector<Point> of the original points.
*/

@ -278,8 +278,6 @@ namespace internal
double computeMeanReproErrStereo(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, InputArray K1, InputArray K2,
InputArray D1, InputArray D2, double xi1, double xi2, InputArray om, InputArray T, InputArrayOfArrays omL, InputArrayOfArrays TL);
void checkFixed(Mat &G, int flags, int n);
void subMatrix(const Mat& src, Mat& dst, const std::vector<int>& cols, const std::vector<int>& rows);
void flags2idx(int flags, std::vector<int>& idx, int n);
@ -309,4 +307,4 @@ namespace internal
} // omnidir
} //cv
#endif
#endif

@ -405,9 +405,9 @@ bool CustomPattern::findPattern(InputArray image, OutputArray matched_features,
return (!m_ftrs.empty());
}
void CustomPattern::getPatternPoints(OutputArray original_points)
void CustomPattern::getPatternPoints(std::vector<KeyPoint>& original_points)
{
return Mat(keypoints).copyTo(original_points);
original_points = keypoints;
}
double CustomPattern::getPixelSize()

@ -749,12 +749,12 @@ void MultiCameraCalibration::writeParameters(const std::string& filename)
for (int camIdx = 0; camIdx < _nCamera; ++camIdx)
{
char num[10];
sprintf(num, "%d", camIdx);
std::string cameraMatrix = "camera_matrix_" + std::string(num);
std::string cameraPose = "camera_pose_" + std::string(num);
std::string cameraDistortion = "camera_distortion_" + std::string(num);
std::string cameraXi = "xi_" + std::string(num);
std::stringstream tmpStr;
tmpStr << camIdx;
std::string cameraMatrix = "camera_matrix_" + tmpStr.str();
std::string cameraPose = "camera_pose_" + tmpStr.str();
std::string cameraDistortion = "camera_distortion_" + tmpStr.str();
std::string cameraXi = "xi_" + tmpStr.str();
fs << cameraMatrix << _cameraMatrix[camIdx];
fs << cameraDistortion << _distortCoeffs[camIdx];
@ -770,11 +770,11 @@ void MultiCameraCalibration::writeParameters(const std::string& filename)
for (int photoIdx = _nCamera; photoIdx < (int)_vertexList.size(); ++photoIdx)
{
char timestamp[100];
sprintf(timestamp, "%d", _vertexList[photoIdx].timestamp);
std::string photoTimestamp = "pose_timestamp_" + std::string(timestamp);
std::stringstream tmpStr;
tmpStr << _vertexList[photoIdx].timestamp;
std::string photoTimestamp = "pose_timestamp_" + tmpStr.str();
fs << photoTimestamp << _vertexList[photoIdx].pose;
}
}
}} // namespace multicalib, cv
}} // namespace multicalib, cv

@ -1785,8 +1785,6 @@ void cv::omnidir::internal::estimateUncertainties(InputArrayOfArrays objectPoint
errors = 3 * s * _JTJ_inv.diag();
checkFixed(errors, flags, n);
rms = 0;
const Vec2d* ptr_ex = reprojError.ptr<Vec2d>();
for (int i = 0; i < (int)reprojError.total(); i++)
@ -1995,52 +1993,6 @@ double cv::omnidir::internal::computeMeanReproErrStereo(InputArrayOfArrays objec
return reProErr;
}
void cv::omnidir::internal::checkFixed(Mat& G, int flags, int n)
{
int _flags = flags;
if(_flags >= omnidir::CALIB_FIX_CENTER)
{
G.at<double>(6*n+3) = 0;
G.at<double>(6*n+4) = 0;
_flags -= omnidir::CALIB_FIX_CENTER;
}
if(_flags >= omnidir::CALIB_FIX_GAMMA)
{
G.at<double>(6*n) = 0;
G.at<double>(6*n+1) = 0;
_flags -= omnidir::CALIB_FIX_GAMMA;
}
if(_flags >= omnidir::CALIB_FIX_XI)
{
G.at<double>(6*n + 5) = 0;
_flags -= omnidir::CALIB_FIX_XI;
}
if(_flags >= omnidir::CALIB_FIX_P2)
{
G.at<double>(6*n + 9) = 0;
_flags -= omnidir::CALIB_FIX_P2;
}
if(_flags >= omnidir::CALIB_FIX_P1)
{
G.at<double>(6*n + 8) = 0;
_flags -= omnidir::CALIB_FIX_P1;
}
if(_flags >= omnidir::CALIB_FIX_K2)
{
G.at<double>(6*n + 7) = 0;
_flags -= omnidir::CALIB_FIX_K2;
}
if(_flags >= omnidir::CALIB_FIX_K1)
{
G.at<double>(6*n + 6) = 0;
_flags -= omnidir::CALIB_FIX_K1;
}
if(_flags >= omnidir::CALIB_FIX_SKEW)
{
G.at<double>(6*n + 2) = 0;
}
}
// This function is from fisheye.cpp
void cv::omnidir::internal::subMatrix(const Mat& src, Mat& dst, const std::vector<int>& cols, const std::vector<int>& rows)
{

@ -133,6 +133,12 @@ void er_draw(vector<Mat> &channels, vector<vector<ERStat> > &regions, vector<Vec
}
}
// std::toupper is int->int
static char char_toupper(char ch)
{
return (char)std::toupper((int)ch);
}
int main(int argc, char *argv[])
{
const char *keys =
@ -200,7 +206,7 @@ int main(int argc, char *argv[])
for (size_t w=0; w<example->words.size(); w++)
{
string w_upper = example->words[w].value;
transform(w_upper.begin(), w_upper.end(), w_upper.begin(), ::toupper);
transform(w_upper.begin(), w_upper.end(), w_upper.begin(), char_toupper);
if ((find (lex->begin(), lex->end(), w_upper) == lex->end()) &&
(is_word_spotting) && (selected_lex != 0))
example->words[w].value = "###";
@ -297,7 +303,7 @@ int main(int argc, char *argv[])
continue;
}
std::transform(words[j].begin(), words[j].end(), words[j].begin(), ::toupper);
std::transform(words[j].begin(), words[j].end(), words[j].begin(), char_toupper);
/* Increase confidence of predicted words matching a word in the lexicon */
if (lex->size() > 0)
@ -413,7 +419,7 @@ int main(int argc, char *argv[])
}
}
std::transform(t.value.begin(), t.value.end(), t.value.begin(), ::toupper);
std::transform(t.value.begin(), t.value.end(), t.value.begin(), char_toupper);
if (((t.value==final_words[j]) || (alnum_value==final_words[j])) &&
!(final_boxes[j].tl().x > t.x+t.width || final_boxes[j].br().x < t.x ||
final_boxes[j].tl().y > t.y+t.height || final_boxes[j].br().y < t.y))
@ -430,7 +436,7 @@ int main(int argc, char *argv[])
for (vector<word>::iterator it=example->words.begin(); it!=example->words.end(); ++it)
{
word &t = (*it);
std::transform(t.value.begin(), t.value.end(), t.value.begin(), ::toupper);
std::transform(t.value.begin(), t.value.end(), t.value.begin(), char_toupper);
if ((t.value == "###") &&
!(final_boxes[j].tl().x > t.x+t.width || final_boxes[j].br().x < t.x ||
final_boxes[j].tl().y > t.y+t.height || final_boxes[j].br().y < t.y))

@ -133,6 +133,12 @@ void er_draw(vector<Mat> &channels, vector<vector<ERStat> > &regions, vector<Vec
}
}
// std::toupper is int->int
static char char_toupper(char ch)
{
return (char)std::toupper((int)ch);
}
int main(int argc, char *argv[])
{
const char *keys =
@ -244,7 +250,7 @@ int main(int argc, char *argv[])
continue;
}
std::transform(words[j].begin(), words[j].end(), words[j].begin(), ::toupper);
std::transform(words[j].begin(), words[j].end(), words[j].begin(), char_toupper);
if (find(example->lex.begin(), example->lex.end(), words[j]) == example->lex.end())
{

@ -151,7 +151,7 @@ public:
/**
@param radius The radius used for building the Circular Local Binary Pattern. The greater the
radius, the
radius, the smoother the image but more spatial information you can get.
@param neighbors The number of sample points to build a Circular Local Binary Pattern from. An
appropriate value is to use `8` sample points. Keep in mind: the more sample points you include,
the higher the computational cost.

@ -47,6 +47,10 @@ public:
// Send all predict results to caller side for custom result handling
void predict(InputArray src, Ptr<PredictCollector> collector) const;
String getDefaultName() const
{
return "opencv_eigenfaces";
}
};
//------------------------------------------------------------------------------

@ -42,6 +42,10 @@ public:
// Send all predict results to caller side for custom result handling
void predict(InputArray src, Ptr<PredictCollector> collector) const;
String getDefaultName() const
{
return "opencv_fisherfaces";
}
};
// Removes duplicate elements in a given vector.

@ -103,6 +103,10 @@ public:
bool empty() const {
return (_labels.empty());
}
String getDefaultName() const
{
return "opencv_lbphfaces";
}
CV_IMPL_PROPERTY(int, GridX, _grid_x)
CV_IMPL_PROPERTY(int, GridY, _grid_y)

@ -60,7 +60,7 @@ the euclidean distance between feature vectors of a probe and reference image. S
robust against changes in illumination by its nature, but has a huge drawback: the accurate
registration of the marker points is complicated, even with state of the art algorithms. Some of the
latest work on geometric face recognition was carried out in @cite Bru92 . A 22-dimensional feature
vector was used and experiments on large datasets have shown, that geometrical features alone my not
vector was used and experiments on large datasets have shown, that geometrical features alone may not
carry enough information for face recognition.
The Eigenfaces method described in @cite TP91 took a holistic approach to face recognition: A facial

@ -401,6 +401,12 @@ class CV_EXPORTS BinaryDescriptor : public Algorithm
unsigned int octaveCount;
//the decriptor of line
std::vector<float> descriptor;
OctaveSingleLine() : startPointX(0), startPointY(0), endPointX(0), endPointY(0),
sPointInOctaveX(0), sPointInOctaveY(0), ePointInOctaveX(0), ePointInOctaveY(0),
direction(0), salience(0), lineLength(0), numOfPixels(0), octaveCount(0),
descriptor(std::vector<float>())
{}
};
struct Pixel

@ -131,7 +131,7 @@ public:
flag(flag_),
spaceWeights(spaceWeights_),
expLut(expLut_) {
CV_DbgAssert(joint.type() == JointVec::type && confidence.type() == CV_32F && src.type() == dst.type() && src.type() == SrcVec::type);
CV_DbgAssert(joint.type() == traits::Type<JointVec>::value && confidence.type() == CV_32F && src.type() == dst.type() && src.type() == traits::Type<SrcVec>::value);
CV_DbgAssert(joint.rows == src.rows && confidence.rows == src.rows && src.rows == dst.rows + 2 * radius);
CV_DbgAssert(joint.cols == src.cols && confidence.cols == src.cols && src.cols == dst.cols + 2 * radius);
}

@ -87,6 +87,7 @@ namespace cv
CV_WRAP virtual void setShowGrid(bool needShowGrid) = 0;
CV_WRAP virtual void setShowText(bool needShowText) = 0;
CV_WRAP virtual void setGridLinesNumber(int gridLinesNumber) = 0;
CV_WRAP virtual void setInvertOrientation(bool _invertOrientation) = 0;
/**
* @brief Sets the index of a point which coordinates will be printed on the top left corner of the plot (if ShowText flag is true).
*

@ -0,0 +1,41 @@
#include <opencv2/highgui.hpp>
#include <opencv2/plot.hpp>
#include <iostream>
using namespace cv;
int main()
{
Mat data_x( 1, 51, CV_64F );
Mat data_y( 1, 51, CV_64F );
for ( int i = 0; i < data_x.cols; i++ )
{
double x = ( i - data_x.cols / 2 );
data_x.at<double>( 0, i ) = x;
data_y.at<double>( 0, i ) = x * x * x;
}
std::cout << "data_x : " << data_x << std::endl;
std::cout << "data_y : " << data_y << std::endl;
Mat plot_result;
Ptr<plot::Plot2d> plot = plot::Plot2d::create( data_x, data_y );
plot->render(plot_result);
imshow( "The plot rendered with default visualization options", plot_result );
plot->setShowText( false );
plot->setShowGrid( false );
plot->setPlotBackgroundColor( Scalar( 255, 200, 200 ) );
plot->setPlotLineColor( Scalar( 255, 0, 0 ) );
plot->setPlotLineWidth( 2 );
plot->setInvertOrientation( true );
plot->render( plot_result );
imshow( "The plot rendered with some of custom visualization options", plot_result );
waitKey();
return 0;
}

@ -132,6 +132,10 @@ namespace cv
{
plotLineWidth = _plotLineWidth;
}
void setInvertOrientation(bool _invertOrientation)
{
invertOrientation = _invertOrientation;
}
void setNeedPlotLine(bool _needPlotLine)
{
needPlotLine = _needPlotLine;
@ -199,11 +203,15 @@ namespace cv
int NumVecElements = plotDataX.rows;
Mat InterpXdata = linearInterpolation(plotMinX, plotMaxX, 0, plotSizeWidth, plotDataX);
Mat InterpYdata = linearInterpolation(plotMinY, plotMaxY, 0, plotSizeHeight, plotDataY);
Mat InterpYdata = invertOrientation ?
linearInterpolation(plotMaxY, plotMinY, 0, plotSizeHeight, plotDataY) :
linearInterpolation(plotMinY, plotMaxY, 0, plotSizeHeight, plotDataY);
//Find the zeros in image coordinates
Mat InterpXdataFindZero = linearInterpolation(plotMinX_plusZero, plotMaxX_plusZero, 0, plotSizeWidth, plotDataX_plusZero);
Mat InterpYdataFindZero = linearInterpolation(plotMinY_plusZero, plotMaxY_plusZero, 0, plotSizeHeight, plotDataY_plusZero);
Mat InterpYdataFindZero = invertOrientation ?
linearInterpolation(plotMaxY_plusZero, plotMinY_plusZero, 0, plotSizeHeight, plotDataY_plusZero) :
linearInterpolation(plotMinY_plusZero, plotMaxY_plusZero, 0, plotSizeHeight, plotDataY_plusZero);
int ImageXzero = (int)InterpXdataFindZero.at<double>(NumVecElements,0);
int ImageYzero = (int)InterpYdataFindZero.at<double>(NumVecElements,0);
@ -264,6 +272,7 @@ namespace cv
double plotMinY_plusZero;
double plotMaxY_plusZero;
int plotLineWidth;
bool invertOrientation;
bool needShowGrid;
bool needShowText;
int gridLinesNumber;
@ -307,6 +316,7 @@ namespace cv
double MaxY_plusZero;
needPlotLine = true;
invertOrientation = false;
//Obtain the minimum and maximum values of Xdata
minMaxLoc(plotDataX,&MinX,&MaxX);
@ -377,7 +387,6 @@ namespace cv
}
}
//Vertical Y axis
drawLine(ImageXzero, ImageXzero, 0, plotSizeHeight, axisColor);
LineSpace = cvRound(LineSpace * (float)plotSizeWidth / plotSizeHeight );
@ -406,7 +415,6 @@ namespace cv
if(Ydata.at<double>(i,0)<0)
Ydata.at<double>(i,0)=0;
}
return Ydata;
@ -450,13 +458,11 @@ namespace cv
line(plotResult, Axis_start, Axis_end, lineColor, plotLineWidth, 8, 0);
}
};
Ptr<Plot2d> Plot2d::create(InputArray _plotData)
{
return Ptr<Plot2dImpl> (new Plot2dImpl (_plotData));
}
Ptr<Plot2d> Plot2d::create(InputArray _plotDataX, InputArray _plotDataY)

@ -80,7 +80,7 @@ struct CV_EXPORTS_W_SIMPLE Template
CV_PROP int width;
CV_PROP int height;
CV_PROP int pyramid_level;
CV_PROP std::vector<Feature> features;
std::vector<Feature> features; // FIXIT: CV_PROP
void read(const FileNode& fn);
void write(FileStorage& fs) const;

@ -47,19 +47,22 @@ namespace cv
namespace saliency
{
typedef int64_t TIG_TYPE;
typedef double MAT_TIG_TYPE; // cv::Mat has no native support for int64/uint64
struct TIGbits
{
TIGbits() : bc0(0), bc1(0) {}
inline void accumulate(int64_t tig, int64_t tigMask0, int64_t tigMask1, uchar shift)
inline void accumulate(TIG_TYPE tig, TIG_TYPE tigMask0, TIG_TYPE tigMask1, uchar shift)
{
bc0 += ((POPCNT64(tigMask0 & tig) << 1) - POPCNT64(tig)) << shift;
bc1 += ((POPCNT64(tigMask1 & tig) << 1) - POPCNT64(tig)) << shift;
}
int64_t bc0;
int64_t bc1;
TIG_TYPE bc0;
TIG_TYPE bc1;
};
float ObjectnessBING::FilterTIG::dot( int64_t tig1, int64_t tig2, int64_t tig4, int64_t tig8 )
float ObjectnessBING::FilterTIG::dot( TIG_TYPE tig1, TIG_TYPE tig2, TIG_TYPE tig4, TIG_TYPE tig8 )
{
TIGbits x;
x.accumulate(tig1, _bTIGs[0], _bTIGs[1], 0);
@ -111,22 +114,22 @@ Mat ObjectnessBING::FilterTIG::matchTemplate( const Mat &mag1u )
{
const int H = mag1u.rows, W = mag1u.cols;
const Size sz( W + 1, H + 1 ); // Expand original size to avoid dealing with boundary conditions
Mat_<int64_t> Tig1 = Mat_<int64_t>::zeros( sz ), Tig2 = Mat_<int64_t>::zeros( sz );
Mat_<int64_t> Tig4 = Mat_<int64_t>::zeros( sz ), Tig8 = Mat_<int64_t>::zeros( sz );
Mat_<MAT_TIG_TYPE> Tig1 = Mat_<MAT_TIG_TYPE>::zeros( sz ), Tig2 = Mat_<MAT_TIG_TYPE>::zeros( sz );
Mat_<MAT_TIG_TYPE> Tig4 = Mat_<MAT_TIG_TYPE>::zeros( sz ), Tig8 = Mat_<MAT_TIG_TYPE>::zeros( sz );
Mat_<BYTE> Row1 = Mat_<BYTE>::zeros( sz ), Row2 = Mat_<BYTE>::zeros( sz );
Mat_<BYTE> Row4 = Mat_<BYTE>::zeros( sz ), Row8 = Mat_<BYTE>::zeros( sz );
Mat_<float> scores( sz );
for ( int y = 1; y <= H; y++ )
{
const BYTE* G = mag1u.ptr<BYTE>( y - 1 );
int64_t* T1 = Tig1.ptr<int64_t>( y ); // Binary TIG of current row
int64_t* T2 = Tig2.ptr<int64_t>( y );
int64_t* T4 = Tig4.ptr<int64_t>( y );
int64_t* T8 = Tig8.ptr<int64_t>( y );
int64_t* Tu1 = Tig1.ptr<int64_t>( y - 1 ); // Binary TIG of upper row
int64_t* Tu2 = Tig2.ptr<int64_t>( y - 1 );
int64_t* Tu4 = Tig4.ptr<int64_t>( y - 1 );
int64_t* Tu8 = Tig8.ptr<int64_t>( y - 1 );
TIG_TYPE* T1 = Tig1.ptr<TIG_TYPE>( y ); // Binary TIG of current row
TIG_TYPE* T2 = Tig2.ptr<TIG_TYPE>( y );
TIG_TYPE* T4 = Tig4.ptr<TIG_TYPE>( y );
TIG_TYPE* T8 = Tig8.ptr<TIG_TYPE>( y );
TIG_TYPE* Tu1 = Tig1.ptr<TIG_TYPE>( y - 1 ); // Binary TIG of upper row
TIG_TYPE* Tu2 = Tig2.ptr<TIG_TYPE>( y - 1 );
TIG_TYPE* Tu4 = Tig4.ptr<TIG_TYPE>( y - 1 );
TIG_TYPE* Tu8 = Tig8.ptr<TIG_TYPE>( y - 1 );
BYTE* R1 = Row1.ptr<BYTE>( y );
BYTE* R2 = Row2.ptr<BYTE>( y );
BYTE* R4 = Row4.ptr<BYTE>( y );

@ -1,3 +1,4 @@
set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE)
set(the_description "SFM algorithms")
@ -39,7 +40,7 @@ endif()
### LIBMV LIGHT DEFINITIONS ###
set(LIBMV_LIGHT_INCLUDES
src/libmv_light
"${CMAKE_CURRENT_LIST_DIR}/src/libmv_light"
"${OpenCV_SOURCE_DIR}/include/opencv"
"${GLOG_INCLUDE_DIRS}"
"${GFLAGS_INCLUDE_DIRS}"
@ -113,7 +114,7 @@ if(NOT CMAKE_VERSION VERSION_LESS 2.8.11) # See ocv_target_include_directories()
endif()
endif()
include_directories(${OCV_TARGET_INCLUDE_DIRS_${the_module}})
add_subdirectory(src/libmv_light)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/src/libmv_light" "${CMAKE_CURRENT_BINARY_DIR}/src/libmv")
ocv_target_link_libraries(${the_module} ${LIBMV_LIGHT_LIBS})

@ -44,11 +44,11 @@
* The interface contains the main methods for computing the matching between the left and right images *
* *
\******************************************************************************************************************/
#include <stdint.h>
#ifndef _OPENCV_MATCHING_HPP_
#define _OPENCV_MATCHING_HPP_
#ifdef __cplusplus
#include <stdint.h>
#include "opencv2/core.hpp"
namespace cv
{
@ -423,7 +423,6 @@ namespace cv
//preprocessing the cost volume in order to get it ready for aggregation
void costGathering(const Mat &hammingDistanceCost, Mat &cost)
{
CV_Assert(hammingDistanceCost.rows == hammingDistanceCost.rows);
CV_Assert(hammingDistanceCost.type() == CV_16S);
CV_Assert(cost.type() == CV_16S);
int maxDisp = maxDisparity;
@ -620,5 +619,4 @@ namespace cv
}
}
#endif
#endif
/*End of file*/

@ -53,8 +53,8 @@ typedef perf::TestBaseWithParam<s_bm_test_t> s_bm;
PERF_TEST_P( s_bm, sgm_perf,
testing::Combine(
testing::Values( cv::Size(512, 283), cv::Size(320, 240)),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8UC1,CV_8U,CV_16S )
testing::Values( CV_8U ),
testing::Values( CV_8U,CV_16S )
)
)
{
@ -80,8 +80,8 @@ PERF_TEST_P( s_bm, sgm_perf,
PERF_TEST_P( s_bm, bm_perf,
testing::Combine(
testing::Values( cv::Size(512, 383), cv::Size(320, 240) ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8UC1,CV_8U )
testing::Values( CV_8U ),
testing::Values( CV_8U )
)
)
{

@ -52,7 +52,7 @@ typedef perf::TestBaseWithParam<descript_params_t> descript_params;
PERF_TEST_P( descript_params, census_sparse_descriptor,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)
@ -74,7 +74,7 @@ PERF_TEST_P( descript_params, census_sparse_descriptor,
PERF_TEST_P( descript_params, star_census_transform,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)
@ -96,7 +96,7 @@ PERF_TEST_P( descript_params, star_census_transform,
PERF_TEST_P( descript_params, modified_census_transform,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)
@ -120,7 +120,7 @@ PERF_TEST_P( descript_params, modified_census_transform,
PERF_TEST_P( descript_params, center_symetric_census,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)

@ -83,13 +83,9 @@ static double errorLevel(const Mat &ideal, Mat &actual)
void CV_BlockMatchingTest::run(int )
{
Mat image1, image2, gt;
//some test images can be found in the test data folder
//in order for the tests to build succesfully please replace
//ts->get_data_path() + "testdata/imL2l.bmp with the path from your disk
//for example if your images are on D:\\ , please write D:\\testdata\\imL2l.bmp
image1 = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1);
image2 = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1);
gt = imread(ts->get_data_path() + "testdata/groundtruth.bmp", CV_8UC1);
image1 = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/im2.png", IMREAD_GRAYSCALE);
image2 = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/im6.png", IMREAD_GRAYSCALE);
gt = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/disp2.png", IMREAD_GRAYSCALE);
if(image1.empty() || image2.empty() || gt.empty())
{
@ -97,7 +93,7 @@ void CV_BlockMatchingTest::run(int )
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != gt.cols || gt.rows != gt.rows)
if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != image1.cols || gt.rows != image1.rows)
{
ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
@ -169,10 +165,9 @@ CV_SGBlockMatchingTest::~CV_SGBlockMatchingTest(){}
void CV_SGBlockMatchingTest::run(int )
{
Mat image1, image2, gt;
//some test images can be found in the test data folder
image1 = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1);
image2 = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1);
gt = imread(ts->get_data_path() + "testdata/groundtruth.bmp", CV_8UC1);
image1 = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/im2.png", IMREAD_GRAYSCALE);
image2 = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/im6.png", IMREAD_GRAYSCALE);
gt = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/disp2.png", IMREAD_GRAYSCALE);
if(image1.empty() || image2.empty() || gt.empty())
@ -181,7 +176,7 @@ void CV_SGBlockMatchingTest::run(int )
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != gt.cols || gt.rows != gt.rows)
if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != image1.cols || gt.rows != image1.rows)
{
ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);

@ -115,12 +115,8 @@ CV_DescriptorBaseTest::~CV_DescriptorBaseTest()
CV_DescriptorBaseTest::CV_DescriptorBaseTest()
{
//read 2 images from file
//some test images can be found in the test data folder
//in order for the tests to build succesfully please replace
//ts->get_data_path() + "testdata/imL2l.bmp with the path from your disk
//for example if your images are on D:\\ , please write D:\\testdata\\imL2l.bmp
left = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1);
right = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1);
left = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/im2.png", IMREAD_GRAYSCALE);
right = imread(ts->get_data_path() + "stereomatching/datasets/tsukuba/im6.png", IMREAD_GRAYSCALE);
if(left.empty() || right.empty())
{
@ -463,7 +459,7 @@ void CV_DescriptorBaseTest::run(int )
}
}
TEST(census_transform_testing, accuracy) { CV_CensusTransformTest test; test.safe_run(); }
TEST(symetric_census_testing, accuracy) { CV_SymetricCensusTest test; test.safe_run(); }
TEST(modified_census_testing, accuracy) { CV_ModifiedCensusTransformTest test; test.safe_run(); }
TEST(star_kernel_testing, accuracy) { CV_StarKernelCensusTest test; test.safe_run(); }
TEST(DISABLED_census_transform_testing, accuracy) { CV_CensusTransformTest test; test.safe_run(); }
TEST(DISABLED_symetric_census_testing, accuracy) { CV_SymetricCensusTest test; test.safe_run(); }
TEST(DISABLED_Dmodified_census_testing, accuracy) { CV_ModifiedCensusTransformTest test; test.safe_run(); }
TEST(DISABLED_Dstar_kernel_testing, accuracy) { CV_StarKernelCensusTest test; test.safe_run(); }

@ -78,7 +78,7 @@ class CV_EXPORTS_W StructuredLightPattern : public virtual Algorithm
@note All the images must be at the same resolution.
*/
CV_WRAP
virtual bool decode( InputArrayOfArrays patternImages, OutputArray disparityMap,
virtual bool decode( const std::vector< std::vector<Mat> >& patternImages, OutputArray disparityMap,
InputArrayOfArrays blackImages = noArray(),
InputArrayOfArrays whiteImages = noArray(),
int flags = DECODE_3D_UNDERWORLD ) const = 0;

@ -56,7 +56,7 @@ class CV_EXPORTS_W GrayCodePattern_Impl : public GrayCodePattern
bool generate( OutputArrayOfArrays patternImages );
// Decodes the gray code pattern, computing the disparity map
bool decode( InputArrayOfArrays patternImages, OutputArray disparityMap, InputArrayOfArrays blackImages = noArray(),
bool decode( const std::vector< std::vector<Mat> >& patternImages, OutputArray disparityMap, InputArrayOfArrays blackImages = noArray(),
InputArrayOfArrays whiteImages = noArray(), int flags = DECODE_3D_UNDERWORLD ) const;
// Returns the number of pattern images for the graycode pattern
@ -209,10 +209,10 @@ bool GrayCodePattern_Impl::generate( OutputArrayOfArrays pattern )
return true;
}
bool GrayCodePattern_Impl::decode( InputArrayOfArrays patternImages, OutputArray disparityMap,
bool GrayCodePattern_Impl::decode( const std::vector< std::vector<Mat> >& patternImages, OutputArray disparityMap,
InputArrayOfArrays blackImages, InputArrayOfArrays whitheImages, int flags ) const
{
std::vector<std::vector<Mat> >& acquired_pattern = *( std::vector<std::vector<Mat> >* ) patternImages.getObj();
const std::vector<std::vector<Mat> >& acquired_pattern = patternImages;
if( flags == DECODE_3D_UNDERWORLD )
{

@ -56,7 +56,7 @@ public:
// Generate sinusoidal patterns
bool generate( OutputArrayOfArrays patternImages );
bool decode( InputArrayOfArrays patternImages, OutputArray disparityMap,
bool decode( const std::vector< std::vector<Mat> >& patternImages, OutputArray disparityMap,
InputArrayOfArrays blackImages = noArray(), InputArrayOfArrays whiteImages =
noArray(), int flags = 0 ) const;
@ -258,7 +258,7 @@ bool SinusoidalPatternProfilometry_Impl::generate( OutputArrayOfArrays pattern )
return true;
}
bool SinusoidalPatternProfilometry_Impl::decode( InputArrayOfArrays patternImages,
bool SinusoidalPatternProfilometry_Impl::decode(const std::vector< std::vector<Mat> >& patternImages,
OutputArray disparityMap,
InputArrayOfArrays blackImages,
InputArrayOfArrays whiteImages, int flags ) const

@ -1,21 +1,19 @@
/*
* webcam-demo.cpp
*
* A demo program of End-to-end Scene Text Detection and Recognition.
* A demo program of End-to-end Scene Text Detection and Recognition using webcam or video.
*
* Created on: Jul 31, 2014
* Author: Lluis Gomez i Bigorda <lgomez AT cvc.uab.es>
*/
#include "opencv2/text.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::text;
@ -32,7 +30,7 @@ private:
public:
Parallel_extractCSER(vector<Mat> &_channels, vector< vector<ERStat> > &_regions,
vector<Ptr<ERFilter> >_er_filter1, vector<Ptr<ERFilter> >_er_filter2)
: channels(_channels),regions(_regions),er_filter1(_er_filter1),er_filter2(_er_filter2){}
: channels(_channels),regions(_regions),er_filter1(_er_filter1),er_filter2(_er_filter2) {}
virtual void operator()( const cv::Range &r ) const
{
@ -75,34 +73,81 @@ public:
Parallel_OCR & operator=(const Parallel_OCR &a);
};
//Discard wrongly recognised strings
bool isRepetitive(const string& s);
//Draw ER's in an image via floodFill
void er_draw(vector<Mat> &channels, vector<vector<ERStat> > &regions, vector<Vec2i> group, Mat& segmentation);
//Perform text detection and recognition from webcam
const char* keys =
{
"{@input | 0 | camera index or video file name}"
"{ image i | | specify input image}"
};
//Perform text detection and recognition from webcam or video
int main(int argc, char* argv[])
{
cout << endl << argv[0] << endl << endl;
cout << "A demo program of End-to-end Scene Text Detection and Recognition using webcam." << endl << endl;
cout << " Usage: " << argv[0] << " [camera_index]" << endl << endl;
CommandLineParser parser(argc, argv, keys);
cout << "A demo program of End-to-end Scene Text Detection and Recognition using webcam or video." << endl << endl;
cout << " Keys: " << endl;
cout << " Press 'r' to switch between MSER/CSER regions." << endl;
cout << " Press 'g' to switch between Horizontal and Arbitrary oriented grouping." << endl;
cout << " Press 'o' to switch between OCRTesseract/OCRHMMDecoder recognition." << endl;
cout << " Press 's' to scale down frame size to 320x240." << endl;
cout << " Press 'ESC' to exit." << endl << endl;
parser.printMessage();
VideoCapture cap;
Mat frame, image, gray, out_img;
String input = parser.get<String>("@input");
String image_file_name = parser.get<String>("image");
if (image_file_name != "")
{
image = imread(image_file_name);
if (image.empty())
{
cout << "\nunable to open " << image_file_name << "\nprogram terminated!\n";
return 1;
}
else
{
cout << "\nimage " << image_file_name << " loaded!\n";
frame = image.clone();
}
}
else
{
cout << "\nInitializing capturing... ";
if (input.size() == 1 && isdigit(input[0]))
cap.open(input[0] - '0');
else
cap.open(input);
if (!cap.isOpened())
{
cout << "\nCould not initialize capturing!\n";
return 1;
}
cout << " Done!" << endl;
cap.read(frame);
}
namedWindow("recognition",WINDOW_NORMAL);
imshow("recognition", frame);
waitKey(1);
bool downsize = false;
int REGION_TYPE = 1;
int GROUPING_ALGORITHM = 0;
int RECOGNITION = 0;
char *region_types_str[2] = {const_cast<char *>("ERStats"), const_cast<char *>("MSER")};
char *grouping_algorithms_str[2] = {const_cast<char *>("exhaustive_search"), const_cast<char *>("multioriented")};
char *recognitions_str[2] = {const_cast<char *>("Tesseract"), const_cast<char *>("NM_chain_features + KNN")};
Mat frame,grey,orig_grey,out_img;
String region_types_str[2] = {"ERStats", "MSER"};
String grouping_algorithms_str[2] = {"exhaustive_search", "multioriented"};
String recognitions_str[2] = {"Tesseract", "NM_chain_features + KNN"};
vector<Mat> channels;
vector<vector<ERStat> > regions(2); //two channels
@ -118,15 +163,13 @@ int main(int argc, char* argv[])
er_filters2.push_back(er_filter2);
}
//double t_r = getTickCount();
//Initialize OCR engine (we initialize 10 instances in order to work several recognitions in parallel)
cout << "Initializing OCR engines ..." << endl;
cout << "Initializing OCR engines ... ";
int num_ocrs = 10;
vector< Ptr<OCRTesseract> > ocrs;
for (int o=0; o<num_ocrs; o++)
{
ocrs.push_back(OCRTesseract::create());
ocrs.push_back(OCRTesseract::create());
}
Mat transition_p;
@ -140,26 +183,12 @@ int main(int argc, char* argv[])
vector< Ptr<OCRHMMDecoder> > decoders;
for (int o=0; o<num_ocrs; o++)
{
decoders.push_back(OCRHMMDecoder::create(loadOCRHMMClassifierNM("OCRHMM_knn_model_data.xml.gz"),
voc, transition_p, emission_p));
decoders.push_back(OCRHMMDecoder::create(loadOCRHMMClassifierNM("OCRHMM_knn_model_data.xml.gz"),
voc, transition_p, emission_p));
}
cout << " Done!" << endl;
//cout << "TIME_OCR_INITIALIZATION_ALT = "<< ((double)getTickCount() - t_r)*1000/getTickFrequency() << endl;
int cam_idx = 0;
if (argc > 1)
cam_idx = atoi(argv[1]);
VideoCapture cap(cam_idx);
if(!cap.isOpened())
{
cout << "ERROR: Cannot open default camera (0)." << endl;
return -1;
}
while (cap.read(frame))
while ( true )
{
double t_all = (double)getTickCount();
@ -167,93 +196,65 @@ int main(int argc, char* argv[])
resize(frame,frame,Size(320,240));
/*Text Detection*/
cvtColor(frame,grey,COLOR_RGB2GRAY);
grey.copyTo(orig_grey);
cvtColor(frame,gray,COLOR_BGR2GRAY);
// Extract channels to be processed individually
channels.clear();
channels.push_back(grey);
channels.push_back(255-grey);
channels.push_back(gray);
channels.push_back(255-gray);
regions[0].clear();
regions[1].clear();
//double t_d = (double)getTickCount();
switch (REGION_TYPE)
{
case 0:
{
parallel_for_(cv::Range(0,(int)channels.size()), Parallel_extractCSER(channels,regions,er_filters1,er_filters2));
case 0: // ERStats
parallel_for_(cv::Range(0, (int)channels.size()), Parallel_extractCSER(channels, regions, er_filters1, er_filters2));
break;
}
case 1:
{
//Extract MSER
case 1: // MSER
vector<vector<Point> > contours;
vector<Rect> bboxes;
Ptr<MSER> mser = MSER::create(21,(int)(0.00002*grey.cols*grey.rows),(int)(0.05*grey.cols*grey.rows),1,0.7);
mser->detectRegions(grey, contours, bboxes);
Ptr<MSER> mser = MSER::create(21, (int)(0.00002*gray.cols*gray.rows), (int)(0.05*gray.cols*gray.rows), 1, 0.7);
mser->detectRegions(gray, contours, bboxes);
//Convert the output of MSER to suitable input for the grouping/recognition algorithms
if (contours.size() > 0)
MSERsToERStats(grey, contours, regions);
MSERsToERStats(gray, contours, regions);
break;
}
case 2:
{
break;
}
}
//cout << "TIME_REGION_DETECTION_ALT = " << ((double)getTickCount() - t_d)*1000/getTickFrequency() << endl;
// Detect character groups
//double t_g = getTickCount();
vector< vector<Vec2i> > nm_region_groups;
vector<Rect> nm_boxes;
switch (GROUPING_ALGORITHM)
{
case 0:
{
case 0: // exhaustive_search
erGrouping(frame, channels, regions, nm_region_groups, nm_boxes, ERGROUPING_ORIENTATION_HORIZ);
break;
}
case 1:
{
case 1: //multioriented
erGrouping(frame, channels, regions, nm_region_groups, nm_boxes, ERGROUPING_ORIENTATION_ANY, "./trained_classifier_erGrouping.xml", 0.5);
break;
}
}
//cout << "TIME_GROUPING_ALT = " << ((double)getTickCount() - t_g)*1000/getTickFrequency() << endl;
/*Text Recognition (OCR)*/
frame.copyTo(out_img);
int scale = downsize ? 2 : 1;
float scale_img = (float)((600.f/frame.rows)/scale);
float scale_font = (float)(2-scale_img)/1.4f;
int bottom_bar_height= out_img.rows/7 ;
copyMakeBorder(frame, out_img, 0, bottom_bar_height, 0, 0, BORDER_CONSTANT, Scalar(150, 150, 150));
float scale_font = (float)(bottom_bar_height /85.0);
vector<string> words_detection;
float min_confidence1 = 0.f, min_confidence2 = 0.f;
if (RECOGNITION == 0)
{
min_confidence1 = 51.f; min_confidence2 = 60.f;
min_confidence1 = 51.f;
min_confidence2 = 60.f;
}
vector<Mat> detections;
//t_r = getTickCount();
for (int i=0; i<(int)nm_boxes.size(); i++)
{
rectangle(out_img, nm_boxes[i].tl(), nm_boxes[i].br(), Scalar(255,255,0),3);
Mat group_img = Mat::zeros(frame.rows+2, frame.cols+2, CV_8UC1);
er_draw(channels, regions, nm_region_groups[i], group_img);
group_img(nm_boxes[i]).copyTo(group_img);
@ -268,27 +269,25 @@ int main(int argc, char* argv[])
// parallel process detections in batches of ocrs.size() (== num_ocrs)
for (int i=0; i<(int)detections.size(); i=i+(int)num_ocrs)
{
Range r;
if (i+(int)num_ocrs <= (int)detections.size())
r = Range(i,i+(int)num_ocrs);
else
r = Range(i,(int)detections.size());
switch(RECOGNITION)
{
case 0:
parallel_for_(r, Parallel_OCR<OCRTesseract>(detections, outputs, boxes, words, confidences, ocrs));
break;
case 1:
parallel_for_(r, Parallel_OCR<OCRHMMDecoder>(detections, outputs, boxes, words, confidences, decoders));
break;
}
}
Range r;
if (i+(int)num_ocrs <= (int)detections.size())
r = Range(i,i+(int)num_ocrs);
else
r = Range(i,(int)detections.size());
switch(RECOGNITION)
{
case 0: // Tesseract
parallel_for_(r, Parallel_OCR<OCRTesseract>(detections, outputs, boxes, words, confidences, ocrs));
break;
case 1: // NM_chain_features + KNN
parallel_for_(r, Parallel_OCR<OCRHMMDecoder>(detections, outputs, boxes, words, confidences, decoders));
break;
}
}
for (int i=0; i<(int)detections.size(); i++)
{
outputs[i].erase(remove(outputs[i].begin(), outputs[i].end(), '\n'), outputs[i].end());
//cout << "OCR output = \"" << outputs[i] << "\" length = " << outputs[i].size() << endl;
if (outputs[i].size() < 3)
@ -311,56 +310,57 @@ int main(int argc, char* argv[])
rectangle(out_img, boxes[i][j].tl()-Point(3,word_size.height+3), boxes[i][j].tl()+Point(word_size.width,0), Scalar(255,0,255),-1);
putText(out_img, words[i][j], boxes[i][j].tl()-Point(1,1), FONT_HERSHEY_SIMPLEX, scale_font, Scalar(255,255,255),(int)(3*scale_font));
}
}
//cout << "TIME_OCR_ALT = " << ((double)getTickCount() - t_r)*1000/getTickFrequency() << endl;
t_all = ((double)getTickCount() - t_all)*1000/getTickFrequency();
char buff[100];
sprintf(buff, "%2.1f Fps. @ %dx%d", (float)(1000/t_all), out_img.cols, out_img.rows);
string fps_info = buff;
rectangle(out_img, Point( out_img.rows-(160/scale),out_img.rows-(70/scale) ), Point(out_img.cols,out_img.rows), Scalar(255,255,255),-1);
putText(out_img, fps_info, Point( 10,out_img.rows-(10/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0));
putText(out_img, region_types_str[REGION_TYPE], Point( out_img.rows-(150/scale),out_img.rows-(50/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0));
putText(out_img, grouping_algorithms_str[GROUPING_ALGORITHM], Point( out_img.rows-(150/scale),out_img.rows-(30/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0));
putText(out_img, recognitions_str[RECOGNITION], Point( out_img.rows-(150/scale),out_img.rows-(10/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0));
int text_thickness = 1+(out_img.rows/500);
string fps_info = format("%2.1f Fps. %dx%d", (float)(1000 / t_all), frame.cols, frame.rows);
putText(out_img, fps_info, Point( 10,out_img.rows-5 ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0), text_thickness);
putText(out_img, region_types_str[REGION_TYPE], Point((int)(out_img.cols*0.5), out_img.rows - (int)(bottom_bar_height / 1.5)), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0), text_thickness);
putText(out_img, grouping_algorithms_str[GROUPING_ALGORITHM], Point((int)(out_img.cols*0.5),out_img.rows-((int)(bottom_bar_height /3)+4) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0), text_thickness);
putText(out_img, recognitions_str[RECOGNITION], Point((int)(out_img.cols*0.5),out_img.rows-5 ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0), text_thickness);
imshow("recognition", out_img);
//imwrite("recognition_alt.jpg", out_img);
int key = waitKey(30);
if (key == 27) //wait for key
if ((image_file_name == "") && !cap.read(frame))
{
cout << "esc key pressed" << endl;
break;
cout << "Capturing ended! press any key to exit." << endl;
waitKey();
return 0;
}
else
int key = waitKey(30); //wait for a key press
switch (key)
{
switch (key)
case 27: //ESC
cout << "ESC key pressed and exited." << endl;
return 0;
case 32: //SPACE
imwrite("recognition_alt.jpg", out_img);
break;
case 103: //'g'
GROUPING_ALGORITHM = (GROUPING_ALGORITHM+1)%2;
cout << "Grouping switched to " << grouping_algorithms_str[GROUPING_ALGORITHM] << endl;
break;
case 111: //'o'
RECOGNITION = (RECOGNITION+1)%2;
cout << "OCR switched to " << recognitions_str[RECOGNITION] << endl;
break;
case 114: //'r'
REGION_TYPE = (REGION_TYPE+1)%2;
cout << "Regions switched to " << region_types_str[REGION_TYPE] << endl;
break;
case 115: //'s'
downsize = !downsize;
if (!image.empty())
{
case 103: //g
GROUPING_ALGORITHM = (GROUPING_ALGORITHM+1)%2;
cout << "Grouping switched to " << grouping_algorithms_str[GROUPING_ALGORITHM] << endl;
break;
case 111: //o
RECOGNITION = (RECOGNITION+1)%2;
cout << "OCR switched to " << recognitions_str[RECOGNITION] << endl;
break;
case 114: //r
REGION_TYPE = (REGION_TYPE+1)%2;
cout << "Regions switched to " << region_types_str[REGION_TYPE] << endl;
break;
case 115: //s
downsize = !downsize;
break;
default:
break;
frame = image.clone();
}
break;
default:
break;
}
}
return 0;
@ -389,11 +389,9 @@ bool isRepetitive(const string& s)
return true;
}
return false;
}
void er_draw(vector<Mat> &channels, vector<vector<ERStat> > &regions, vector<Vec2i> group, Mat& segmentation)
{
for (int r=0; r<(int)group.size(); r++)

@ -0,0 +1,116 @@
Tesseract (master) installation by using git-bash (version>=2.14.1) and cmake (version >=3.9.1){#tutorial_install_tesseract}
===============================================================
-# We assume you installed opencv and opencv_contrib in c:/lib using [this tutorials](http://docs.opencv.org/master/d3/d52/tutorial_windows_install.html#tutorial_windows_gitbash_build]
-# You must download [png lib](https://sourceforge.net/projects/libpng/files/libpng16/1.6.32/lpng1632.zip/download) and [zlib](https://sourceforge.net/projects/libpng/files/zlib/1.2.11/zlib1211.zip/download).
Uncompress lpngx.y.zz in folder lpng and zlib in folder zlib. lpng and zlib must be in same folder as opencv and opencv_contrib.
save this script with name installpngzlib.sh in c:/lib
@code{.bash}
#!/bin/bash
myRepo=$(pwd)
CMAKE_CONFIG_GENERATOR="Visual Studio 14 2015 Win64"
RepoSource=zlib
mkdir Build/$RepoSource
pushd Build/$RepoSource
cmake . -G"Visual Studio 14 2015 Win64" \
-DCMAKE_INSTALL_PREFIX:PATH="$myRepo"/install/zlib -DINSTALL_BIN_DIR:PATH="$myRepo"/install/zlib/bin \
-DINSTALL_INC_DIR:PATH="$myRepo"/install/zlib/include -DINSTALL_LIB_DIR:PATH="$myRepo"/install/zlib/lib "$myRepo"/"$RepoSource"
cmake --build . --config release
cmake --build . --target install --config release
cmake --build . --config debug
cmake --build . --target install --config debug
popd
RepoSource=lpng
mkdir Build/$RepoSource
pushd Build/$RepoSource
cp "$myRepo"/"$RepoSource"/scripts/pnglibconf.h.prebuilt "$myRepo"/"$RepoSource"/pnglibconf.h
cmake . -G"Visual Studio 14 2015 Win64" \
-DZLIB_INCLUDE_DIR:PATH="$myRepo"/install/zlib/include -DZLIB_LIBRARY_DEBUG:FILE="$myRepo"/install/zlib/lib/zlibstaticd.lib \
-Dld-version-script:BOOL=OFF -DPNG_TESTS:BOOL=OFF -DAWK:STRING= \
-DZLIB_LIBRARY_RELEASE:FILE="$myRepo"/install/zlib/lib/zlibstatic.lib -DCMAKE_INSTALL_PREFIX="$myRepo"/Install/"$RepoSource" \
"$myRepo"/"$RepoSource"
cmake --build . --config release
cmake --build . --target install --config release
cmake --build . --config debug
cmake --build . --target install --config debug
popd
@endcode
-# In git command line enter the following command :
@code{.bash}
./installpngzlib.sh
@endcode
-# save this script with name installTesseract.sh in c:/lib
@code{.bash}
#!/bin/bash
function MAJGitRepo
{
if [ ! -d "$myRepo/$1" ]; then
echo "clonning ${1}"
git clone $2
mkdir Build/$1
else
echo "update $1"
cd $1
git pull --rebase
cd ..
fi
}
echo "Installing leptonica and tesseract"
myRepo=$(pwd)
CMAKE_CONFIG_GENERATOR="Visual Studio 14 2015 Win64"
MAJGitRepo leptonica https://github.com/DanBloomberg/leptonica.git
RepoSource=leptonica
pushd Build/$RepoSource
cmake -G"$CMAKE_CONFIG_GENERATOR" -DCMAKE_INSTALL_PREFIX="$myRepo"/Install/leptonica "$myRepo/$RepoSource"
echo "************************* $Source_DIR -->debug"
cmake --build . --config release
cmake --build $RepoSource --target install --config release
popd
RepoSource=tesseract
MAJGitRepo $RepoSource https://github.com/tesseract-ocr/tesseract.git
pushd Build/$RepoSource
cmake -G"$CMAKE_CONFIG_GENERATOR" -DBUILD_TRAINING_TOOLS:BOOL=OFF -DCMAKE_INSTALL_PREFIX="$myRepo"/Install/tesseract -DLeptonica_DIR:PATH="$myRepo"/Install/leptonica/cmake -DPKG_CONFIG_EXECUTABLE:BOOL=OFF "$myRepo"/"$RepoSource"
echo "************************* $Source_DIR -->release"
cmake --build . --config release
cmake --build . --target install --config release
popd
RepoSource=opencv
pushd Build/$RepoSource
CMAKE_OPTIONS='-DBUILD_PERF_TESTS:BOOL=OFF -DBUILD_TESTS:BOOL=OFF -DBUILD_DOCS:BOOL=OFF -DWITH_CUDA:BOOL=OFF'
cmake -G"$CMAKE_CONFIG_GENERATOR" \
-DTesseract_INCLUDE_DIR:PATH="${myRepo}"/Install/tesseract/include -DTesseract_LIBRARY="${myRepo}"/Install/tesseract/lib/tesseract400.lib -DLept_LIBRARY="${myRepo}"/Install/leptonica/lib/leptonica-1.74.4.lib \
$CMAKE_OPTIONS -DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
-DINSTALL_CREATE_DISTRIB=ON -DCMAKE_INSTALL_PREFIX="$myRepo"/install/"$RepoSource" "$myRepo/$RepoSource"
echo "************************* $Source_DIR -->devenv debug"
cmake --build . --config debug
echo "************************* $Source_DIR -->devenv release"
cmake --build . --config release
cmake --build . --target install --config release
cmake --build . --target install --config debug
popd
@endcode
In this script I suppose you use VS 2015 in 64 bits
@code{.bash}
CMAKE_CONFIG_GENERATOR="Visual Studio 14 2015 Win64"
@endcode
and leptonica, tesseract will be installed in c:/lib/install
@code{.bash}
-DCMAKE_INSTALL_PREFIX="$myRepo"/install/"$RepoSource" "$myRepo/$RepoSource"
@endcode
with no Perf tests, no tests, no doc, no CUDA and no example
@code{.bash}
CMAKE_OPTIONS='-DBUILD_PERF_TESTS:BOOL=OFF -DBUILD_TESTS:BOOL=OFF -DBUILD_DOCS:BOOL=OFF -DWITH_CUDA:BOOL=OFF -DBUILD_EXAMPLES:BOOL=OFF'
@endcode
-# In git command line enter the following command :
@code{.bash}
./installTesseract.sh
@endcode
-# now we need the language files from tesseract. either clone https://github.com/tesseract-ocr/tessdata, or copy only those language files you need to a folder (example c:\\lib\\install\\tesseract\\tessdata). If you don't want to add a new folder you must copy language file in same folder than your executable
-# if you created a new folder, then you must add a new variable, TESSDATA_PREFIX with the value c:\\lib\\install\\tessdata to your system's environment
-# add c:\\Lib\\install\\leptonica\\bin and c:\\Lib\\install\\tesseract\\bin to your PATH environment. If you don't want to modify the PATH then copy tesseract400.dll and leptonica-1.74.4.dll to the same folder than your exe file.

@ -0,0 +1,10 @@
Text module {#tutorial_table_of_content_text}
=====================
- @subpage tutorial_install_tesseract
*Compatibility:* \> OpenCV 3.4
*Author:* Laurent Berger
Instructions in order to properly setup tesseract on windows for the text module.

@ -1200,7 +1200,7 @@ class CV_EXPORTS_W TrackerTLD : public Tracker
/** @brief KCF is a novel tracking framework that utilizes properties of circulant matrix to enhance the processing speed.
* This tracking method is an implementation of @cite KCF_ECCV which is extended to KFC with color-names features (@cite KCF_CN).
* The original paper of KCF is available at <http://home.isr.uc.pt/~henriques/circulant/index.html>
* The original paper of KCF is available at <http://www.robots.ox.ac.uk/~joao/publications/henriques_tpami2015.pdf>
* as well as the matlab implementation. For more information about KCF with color-names features, please refer to
* <http://www.cvl.isy.liu.se/research/objrec/visualtracking/colvistrack/index.html>.
*/

@ -62,13 +62,13 @@ int main( int argc, char** argv ){
//! [selectmulti]
//quit when the tracked object(s) is not provided
if(objects.size()<1)
if(ROIs.size()<1)
return 0;
// initialize the tracker
//! [init]
std::vector<Ptr<Tracker> > algorithms;
for (size_t i = 0; i < objects.size(); i++)
for (size_t i = 0; i < ROIs.size(); i++)
{
algorithms.push_back(createTrackerByName(trackingAlg));
objects.push_back(ROIs[i]);

@ -110,23 +110,7 @@ bool TrackerGOTURNImpl::initImpl(const Mat& image, const Rect2d& boundingBox)
//Load GOTURN architecture from *.prototxt and pretrained weights from *.caffemodel
String modelTxt = "goturn.prototxt";
String modelBin = "goturn.caffemodel";
Ptr<dnn::Importer> importer;
try //Import GOTURN model
{
importer = dnn::createCaffeImporter(modelTxt, modelBin);
}
catch (const cv::Exception &err) //Importer can throw errors, we will catch them
{
std::cerr << err.msg << std::endl;
}
if (!importer)
{
cvError(CV_StsError, "cv::gtr::InitImpl", "GOTURN network loading error...", "gtrTracker.cpp", 117);
}
importer->populateNet(net);
importer.release(); //We don't need importer anymore
net = dnn::readNetFromCaffe(modelTxt, modelBin);
return true;
}
@ -169,11 +153,11 @@ bool TrackerGOTURNImpl::updateImpl(const Mat& image, Rect2d& boundingBox)
searchPatch = searchPatch - 128;
//Convert to Float type
Mat targetBlob = dnn::blobFromImage(targetPatch);
Mat searchBlob = dnn::blobFromImage(searchPatch);
Mat targetBlob = dnn::blobFromImage(targetPatch, 1.0f, Size(), Scalar(), false);
Mat searchBlob = dnn::blobFromImage(searchPatch, 1.0f, Size(), Scalar(), false);
net.setInput(targetBlob, ".data1");
net.setInput(searchBlob, ".data2");
net.setInput(targetBlob, "data1");
net.setInput(searchBlob, "data2");
Mat resMat = net.forward("scale").reshape(1, 1);

@ -119,7 +119,14 @@ bool TrackerTLDImpl::initImpl(const Mat& image, const Rect2d& boundingBox)
bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox)
{
Mat image_gray, image_blurred, imageForDetector;
cvtColor( image, image_gray, COLOR_BGR2GRAY );
if(image.channels() > 1)
{
cvtColor( image, image_gray, COLOR_BGR2GRAY );
}
else
{
image_gray = image.clone();
}
double scale = data->getScale();
if( scale > 1.0 )
resize(image_gray, imageForDetector, Size(cvRound(image.cols*scale), cvRound(image.rows*scale)), 0, 0, DOWNSCALE_MODE);

@ -47,7 +47,7 @@
|---------------------------*/
namespace cv{
/**
* \brief Implementation of TrackerModel for MIL algorithm
* \brief Implementation of TrackerModel for KCF algorithm
*/
class TrackerKCFModel : public TrackerModel{
public:
@ -827,7 +827,7 @@ namespace cv{
TrackerKCF::Params::Params(){
detect_thresh = 0.5;
sigma=0.2;
lambda=0.01;
lambda=0.0001;
interp_factor=0.075;
output_sigma_factor=1.0/16.0;
resize=true;

@ -47,8 +47,6 @@ using namespace cv;
using namespace testing;
using namespace std;
#define PARAM_TEST_CASE(name, ...) struct name : testing::TestWithParam< std::tr1::tuple< __VA_ARGS__ > >
#define GET_PARAM(k) std::tr1::get< k >(GetParam())
#define TESTSET_NAMES testing::Values("david","dudek","faceocc2")
const string TRACKING_DIR = "tracking";
@ -532,7 +530,7 @@ TEST_P(DistanceAndOverlap, DISABLED_Scaled_Data_TLD)
TEST_P(DistanceAndOverlap, DISABLED_GOTURN)
{
TrackerTest test(TrackerGOTURN::create(), dataset, 0, 100, NoTransform);
TrackerTest test(TrackerGOTURN::create(), dataset, 18, .5f, NoTransform);
test.run();
}

@ -40,7 +40,7 @@ PERF_TEST_P(surf, extract, testing::Values(SURF_IMAGES))
Ptr<SURF> detector = SURF::create();
vector<KeyPoint> points;
vector<float> descriptors;
Mat descriptors;
detector->detect(frame, points, mask);
TEST_CYCLE() detector->compute(frame, points, descriptors);
@ -58,7 +58,7 @@ PERF_TEST_P(surf, full, testing::Values(SURF_IMAGES))
declare.in(frame).time(90);
Ptr<SURF> detector = SURF::create();
vector<KeyPoint> points;
vector<float> descriptors;
Mat descriptors;
TEST_CYCLE() detector->detectAndCompute(frame, mask, points, descriptors, false);

@ -21,7 +21,6 @@ protected:
{
public:
std::vector<Mat> layers;
Octave();
Octave(std::vector<Mat> layers);
virtual ~Octave();
std::vector<Mat> getLayers();
@ -33,10 +32,8 @@ protected:
public:
std::vector<Mat> layers;
DOGOctave();
DOGOctave(std::vector<Mat> layers);
virtual ~DOGOctave();
std::vector<Mat> getLayers();
Mat getLayerAt(int i);
};
@ -53,30 +50,21 @@ public:
float sigma0;
int omin;
float step;
Params();
Params(int octavesN, int layersN, float sigma0, int omin);
void clear();
};
Params params;
Pyramid();
Pyramid(const Mat& img, int octavesN, int layersN = 2, float sigma0 = 1, int omin = 0,
bool DOG = false);
Mat getLayer(int octave, int layer);
Mat getDOGLayer(int octave, int layer);
float getSigma(int octave, int layer);
float getSigma(int layer);
virtual ~Pyramid();
Params getParams();
void clear();
bool empty();
};
Pyramid::Pyramid()
{
}
/**
* Pyramid class constructor
* octavesN_: number of octaves
@ -234,15 +222,6 @@ Mat Pyramid::getDOGLayer(int octave, int layer)
return DOG_octaves[octave].getLayerAt(layer);
}
/**
* Return sigma value of indicated octave and layer
*/
float Pyramid::getSigma(int octave, int layer)
{
return powf(2.0f, float(octave)) * powf(params.step, float(layer)) * params.sigma0;
}
/**
* Return sigma value of indicated layer
* sigma value of layer is the same at each octave
@ -271,19 +250,6 @@ void Pyramid::clear()
params.clear();
}
/**
* Empty Pyramid
* @return
*/
bool Pyramid::empty()
{
return octaves.empty();
}
Pyramid::Params::Params()
{
}
/**
* Params for Pyramid class
*
@ -295,14 +261,6 @@ Pyramid::Params::Params(int octavesN_, int layersN_, float sigma0_, int omin_) :
step = powf(2, 1.0f / layersN);
}
/**
* Returns Pyramid's params
*/
Pyramid::Params Pyramid::getParams()
{
return params;
}
/**
* Set to zero all params
*/
@ -328,10 +286,6 @@ std::vector<Mat> Pyramid::Octave::getLayers()
return layers;
}
Pyramid::Octave::Octave()
{
}
/**
* Return the Octave's layer at index i
*/
@ -345,21 +299,12 @@ Pyramid::Octave::~Octave()
{
}
Pyramid::DOGOctave::DOGOctave()
{
}
Pyramid::DOGOctave::DOGOctave(std::vector<Mat> _layers) : layers(_layers) {}
Pyramid::DOGOctave::~DOGOctave()
{
}
std::vector<Mat> Pyramid::DOGOctave::getLayers()
{
return layers;
}
Mat Pyramid::DOGOctave::getLayerAt(int i)
{
CV_Assert(i < (int) layers.size());

@ -875,9 +875,6 @@ inline float linearFilter(
float centerX, float centerY, float win_offset,
float cos_dir, float sin_dir, float y, float x )
{
x -= 0.5f;
y -= 0.5f;
float out = 0.0f;
const int x1 = round(x);
@ -900,6 +897,60 @@ inline float linearFilter(
return out;
}
inline float areaFilter( __PARAM_imgTex__, int img_rows, int img_cols,
float centerX, float centerY, float win_offset,
float cos_dir, float sin_dir, float x, float y, float s)
{
float fsx1 = x * s;
float fsx2 = fsx1 + s;
int sx1 = convert_int_rtp(fsx1);
int sx2 = convert_int_rtn(fsx2);
float fsy1 = y * s;
float fsy2 = fsy1 + s;
int sy1 = convert_int_rtp(fsy1);
int sy2 = convert_int_rtn(fsy2);
float scale = 1.f / (s * s);
float out = 0.f;
for (int dy = sy1; dy < sy2; ++dy)
{
for (int dx = sx1; dx < sx2; ++dx)
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, dy, dx) * scale;
if (sx1 > fsx1)
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, dy, (sx1 -1)) * ((sx1 - fsx1) * scale);
if (sx2 < fsx2)
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, dy, sx2) * ((fsx2 -sx2) * scale);
}
if (sy1 > fsy1)
for (int dx = sx1; dx < sx2; ++dx)
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, (sy1 - 1) , dx) * ((sy1 -fsy1) * scale);
if (sy2 < fsy2)
for (int dx = sx1; dx < sx2; ++dx)
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, sy2, dx) * ((fsy2 -sy2) * scale);
if ((sy1 > fsy1) && (sx1 > fsx1))
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, (sy1 - 1) , (sx1 - 1)) * ((sy1 -fsy1) * (sx1 -fsx1) * scale);
if ((sy1 > fsy1) && (sx2 < fsx2))
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, (sy1 - 1) , sx2) * ((sy1 -fsy1) * (fsx2 -sx2) * scale);
if ((sy2 < fsy2) && (sx2 < fsx2))
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, sy2, sx2) * ((fsy2 -sy2) * (fsx2 -sx2) * scale);
if ((sy2 < fsy2) && (sx1 > fsx1))
out = out + readerGet(centerX, centerY, win_offset, cos_dir, sin_dir, sy2, (sx1 - 1)) * ((fsy2 -sy2) * (sx1 -fsx1) * scale);
return out;
}
void calc_dx_dy(
__PARAM_imgTex__,
int img_rows, int img_cols,
@ -946,9 +997,18 @@ void calc_dx_dy(
const float icoo = ((float)yIndex / (PATCH_SZ + 1)) * win_size;
const float jcoo = ((float)xIndex / (PATCH_SZ + 1)) * win_size;
s_PATCH[get_local_id(1) * 6 + get_local_id(0)] =
linearFilter(__PASS_imgTex__, img_rows, img_cols, centerX, centerY,
win_offset, cos_dir, sin_dir, icoo, jcoo);
if (s > 1)
{
s_PATCH[get_local_id(1) * 6 + get_local_id(0)] =
areaFilter(__PASS_imgTex__, img_rows, img_cols, centerX, centerY,
win_offset, cos_dir, sin_dir, xIndex, yIndex, s);
}
else
{
s_PATCH[get_local_id(1) * 6 + get_local_id(0)] =
linearFilter(__PASS_imgTex__, img_rows, img_cols, centerX, centerY,
win_offset, cos_dir, sin_dir, icoo, jcoo);
}
barrier(CLK_LOCAL_MEM_FENCE);
@ -1075,18 +1135,16 @@ void SURF_computeDescriptors64(
reduce_sum25(sdx, sdy, sdxabs, sdyabs, tid);
barrier(CLK_LOCAL_MEM_FENCE);
if (tid < 25)
if (tid == 0)
{
__global float* descriptors_block = descriptors + descriptors_step * get_group_id(0) + (get_group_id(1) << 2);
// write dx, dy, |dx|, |dy|
if (tid == 0)
{
descriptors_block[0] = sdx[0];
descriptors_block[1] = sdy[0];
descriptors_block[2] = sdxabs[0];
descriptors_block[3] = sdyabs[0];
}
descriptors_block[0] = sdx[0];
descriptors_block[1] = sdy[0];
descriptors_block[2] = sdxabs[0];
descriptors_block[3] = sdyabs[0];
}
}
@ -1102,10 +1160,10 @@ void SURF_computeDescriptors128(
descriptors_step /= sizeof(*descriptors);
keypoints_step /= sizeof(*keypoints);
__global float * featureX = keypoints + X_ROW * keypoints_step;
__global float * featureY = keypoints + Y_ROW * keypoints_step;
__global float* featureSize = keypoints + SIZE_ROW * keypoints_step;
__global float* featureDir = keypoints + ANGLE_ROW * keypoints_step;
__global const float * featureX = keypoints + X_ROW * keypoints_step;
__global const float * featureY = keypoints + Y_ROW * keypoints_step;
__global const float* featureSize = keypoints + SIZE_ROW * keypoints_step;
__global const float* featureDir = keypoints + ANGLE_ROW * keypoints_step;
// 2 floats (dx,dy) for each thread (5x5 sample points in each sub-region)
volatile __local float sdx[25];

@ -378,7 +378,7 @@ static float calcOrientationHist( const Mat& img, Point pt, int radius,
float CV_DECL_ALIGNED(32) w_mul_mag_buf[8];
for ( ; k <= len - 8; k+=8 )
{
__m256i __bin = _mm256_cvtps_epi32(_mm256_round_ps(_mm256_mul_ps(__nd360, _mm256_loadu_ps(&Ori[k])), _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC));
__m256i __bin = _mm256_cvtps_epi32(_mm256_mul_ps(__nd360, _mm256_loadu_ps(&Ori[k])));
__bin = _mm256_sub_epi32(__bin, _mm256_andnot_si256(_mm256_cmpgt_epi32(__n, __bin), __n));
__bin = _mm256_add_epi32(__bin, _mm256_and_si256(__n, _mm256_cmpgt_epi32(_mm256_setzero_si256(), __bin)));
@ -569,92 +569,164 @@ static bool adjustLocalExtrema( const std::vector<Mat>& dog_pyr, KeyPoint& kpt,
}
//
// Detects features at extrema in DoG scale space. Bad features are discarded
// based on contrast and ratio of principal curvatures.
void SIFT_Impl::findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
std::vector<KeyPoint>& keypoints ) const
class findScaleSpaceExtremaComputer : public ParallelLoopBody
{
int nOctaves = (int)gauss_pyr.size()/(nOctaveLayers + 3);
int threshold = cvFloor(0.5 * contrastThreshold / nOctaveLayers * 255 * SIFT_FIXPT_SCALE);
const int n = SIFT_ORI_HIST_BINS;
float hist[n];
KeyPoint kpt;
public:
findScaleSpaceExtremaComputer(
int _o,
int _i,
int _threshold,
int _idx,
int _step,
int _cols,
int _nOctaveLayers,
double _contrastThreshold,
double _edgeThreshold,
double _sigma,
const std::vector<Mat>& _gauss_pyr,
const std::vector<Mat>& _dog_pyr,
TLSData<std::vector<KeyPoint> > &_tls_kpts_struct)
: o(_o),
i(_i),
threshold(_threshold),
idx(_idx),
step(_step),
cols(_cols),
nOctaveLayers(_nOctaveLayers),
contrastThreshold(_contrastThreshold),
edgeThreshold(_edgeThreshold),
sigma(_sigma),
gauss_pyr(_gauss_pyr),
dog_pyr(_dog_pyr),
tls_kpts_struct(_tls_kpts_struct) { }
void operator()( const cv::Range& range ) const
{
const int begin = range.start;
const int end = range.end;
keypoints.clear();
static const int n = SIFT_ORI_HIST_BINS;
float hist[n];
for( int o = 0; o < nOctaves; o++ )
for( int i = 1; i <= nOctaveLayers; i++ )
const Mat& img = dog_pyr[idx];
const Mat& prev = dog_pyr[idx-1];
const Mat& next = dog_pyr[idx+1];
std::vector<KeyPoint> *tls_kpts = tls_kpts_struct.get();
KeyPoint kpt;
for( int r = begin; r < end; r++)
{
int idx = o*(nOctaveLayers+2)+i;
const Mat& img = dog_pyr[idx];
const Mat& prev = dog_pyr[idx-1];
const Mat& next = dog_pyr[idx+1];
int step = (int)img.step1();
int rows = img.rows, cols = img.cols;
const sift_wt* currptr = img.ptr<sift_wt>(r);
const sift_wt* prevptr = prev.ptr<sift_wt>(r);
const sift_wt* nextptr = next.ptr<sift_wt>(r);
for( int r = SIFT_IMG_BORDER; r < rows-SIFT_IMG_BORDER; r++)
for( int c = SIFT_IMG_BORDER; c < cols-SIFT_IMG_BORDER; c++)
{
const sift_wt* currptr = img.ptr<sift_wt>(r);
const sift_wt* prevptr = prev.ptr<sift_wt>(r);
const sift_wt* nextptr = next.ptr<sift_wt>(r);
for( int c = SIFT_IMG_BORDER; c < cols-SIFT_IMG_BORDER; c++)
sift_wt val = currptr[c];
// find local extrema with pixel accuracy
if( std::abs(val) > threshold &&
((val > 0 && val >= currptr[c-1] && val >= currptr[c+1] &&
val >= currptr[c-step-1] && val >= currptr[c-step] && val >= currptr[c-step+1] &&
val >= currptr[c+step-1] && val >= currptr[c+step] && val >= currptr[c+step+1] &&
val >= nextptr[c] && val >= nextptr[c-1] && val >= nextptr[c+1] &&
val >= nextptr[c-step-1] && val >= nextptr[c-step] && val >= nextptr[c-step+1] &&
val >= nextptr[c+step-1] && val >= nextptr[c+step] && val >= nextptr[c+step+1] &&
val >= prevptr[c] && val >= prevptr[c-1] && val >= prevptr[c+1] &&
val >= prevptr[c-step-1] && val >= prevptr[c-step] && val >= prevptr[c-step+1] &&
val >= prevptr[c+step-1] && val >= prevptr[c+step] && val >= prevptr[c+step+1]) ||
(val < 0 && val <= currptr[c-1] && val <= currptr[c+1] &&
val <= currptr[c-step-1] && val <= currptr[c-step] && val <= currptr[c-step+1] &&
val <= currptr[c+step-1] && val <= currptr[c+step] && val <= currptr[c+step+1] &&
val <= nextptr[c] && val <= nextptr[c-1] && val <= nextptr[c+1] &&
val <= nextptr[c-step-1] && val <= nextptr[c-step] && val <= nextptr[c-step+1] &&
val <= nextptr[c+step-1] && val <= nextptr[c+step] && val <= nextptr[c+step+1] &&
val <= prevptr[c] && val <= prevptr[c-1] && val <= prevptr[c+1] &&
val <= prevptr[c-step-1] && val <= prevptr[c-step] && val <= prevptr[c-step+1] &&
val <= prevptr[c+step-1] && val <= prevptr[c+step] && val <= prevptr[c+step+1])))
{
sift_wt val = currptr[c];
// find local extrema with pixel accuracy
if( std::abs(val) > threshold &&
((val > 0 && val >= currptr[c-1] && val >= currptr[c+1] &&
val >= currptr[c-step-1] && val >= currptr[c-step] && val >= currptr[c-step+1] &&
val >= currptr[c+step-1] && val >= currptr[c+step] && val >= currptr[c+step+1] &&
val >= nextptr[c] && val >= nextptr[c-1] && val >= nextptr[c+1] &&
val >= nextptr[c-step-1] && val >= nextptr[c-step] && val >= nextptr[c-step+1] &&
val >= nextptr[c+step-1] && val >= nextptr[c+step] && val >= nextptr[c+step+1] &&
val >= prevptr[c] && val >= prevptr[c-1] && val >= prevptr[c+1] &&
val >= prevptr[c-step-1] && val >= prevptr[c-step] && val >= prevptr[c-step+1] &&
val >= prevptr[c+step-1] && val >= prevptr[c+step] && val >= prevptr[c+step+1]) ||
(val < 0 && val <= currptr[c-1] && val <= currptr[c+1] &&
val <= currptr[c-step-1] && val <= currptr[c-step] && val <= currptr[c-step+1] &&
val <= currptr[c+step-1] && val <= currptr[c+step] && val <= currptr[c+step+1] &&
val <= nextptr[c] && val <= nextptr[c-1] && val <= nextptr[c+1] &&
val <= nextptr[c-step-1] && val <= nextptr[c-step] && val <= nextptr[c-step+1] &&
val <= nextptr[c+step-1] && val <= nextptr[c+step] && val <= nextptr[c+step+1] &&
val <= prevptr[c] && val <= prevptr[c-1] && val <= prevptr[c+1] &&
val <= prevptr[c-step-1] && val <= prevptr[c-step] && val <= prevptr[c-step+1] &&
val <= prevptr[c+step-1] && val <= prevptr[c+step] && val <= prevptr[c+step+1])))
int r1 = r, c1 = c, layer = i;
if( !adjustLocalExtrema(dog_pyr, kpt, o, layer, r1, c1,
nOctaveLayers, (float)contrastThreshold,
(float)edgeThreshold, (float)sigma) )
continue;
float scl_octv = kpt.size*0.5f/(1 << o);
float omax = calcOrientationHist(gauss_pyr[o*(nOctaveLayers+3) + layer],
Point(c1, r1),
cvRound(SIFT_ORI_RADIUS * scl_octv),
SIFT_ORI_SIG_FCTR * scl_octv,
hist, n);
float mag_thr = (float)(omax * SIFT_ORI_PEAK_RATIO);
for( int j = 0; j < n; j++ )
{
int r1 = r, c1 = c, layer = i;
if( !adjustLocalExtrema(dog_pyr, kpt, o, layer, r1, c1,
nOctaveLayers, (float)contrastThreshold,
(float)edgeThreshold, (float)sigma) )
continue;
float scl_octv = kpt.size*0.5f/(1 << o);
float omax = calcOrientationHist(gauss_pyr[o*(nOctaveLayers+3) + layer],
Point(c1, r1),
cvRound(SIFT_ORI_RADIUS * scl_octv),
SIFT_ORI_SIG_FCTR * scl_octv,
hist, n);
float mag_thr = (float)(omax * SIFT_ORI_PEAK_RATIO);
for( int j = 0; j < n; j++ )
{
int l = j > 0 ? j - 1 : n - 1;
int r2 = j < n-1 ? j + 1 : 0;
int l = j > 0 ? j - 1 : n - 1;
int r2 = j < n-1 ? j + 1 : 0;
if( hist[j] > hist[l] && hist[j] > hist[r2] && hist[j] >= mag_thr )
if( hist[j] > hist[l] && hist[j] > hist[r2] && hist[j] >= mag_thr )
{
float bin = j + 0.5f * (hist[l]-hist[r2]) / (hist[l] - 2*hist[j] + hist[r2]);
bin = bin < 0 ? n + bin : bin >= n ? bin - n : bin;
kpt.angle = 360.f - (float)((360.f/n) * bin);
if(std::abs(kpt.angle - 360.f) < FLT_EPSILON)
kpt.angle = 0.f;
{
float bin = j + 0.5f * (hist[l]-hist[r2]) / (hist[l] - 2*hist[j] + hist[r2]);
bin = bin < 0 ? n + bin : bin >= n ? bin - n : bin;
kpt.angle = 360.f - (float)((360.f/n) * bin);
if(std::abs(kpt.angle - 360.f) < FLT_EPSILON)
kpt.angle = 0.f;
keypoints.push_back(kpt);
tls_kpts->push_back(kpt);
}
}
}
}
}
}
}
private:
int o, i;
int threshold;
int idx, step, cols;
int nOctaveLayers;
double contrastThreshold;
double edgeThreshold;
double sigma;
const std::vector<Mat>& gauss_pyr;
const std::vector<Mat>& dog_pyr;
TLSData<std::vector<KeyPoint> > &tls_kpts_struct;
};
//
// Detects features at extrema in DoG scale space. Bad features are discarded
// based on contrast and ratio of principal curvatures.
void SIFT_Impl::findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
std::vector<KeyPoint>& keypoints ) const
{
const int nOctaves = (int)gauss_pyr.size()/(nOctaveLayers + 3);
const int threshold = cvFloor(0.5 * contrastThreshold / nOctaveLayers * 255 * SIFT_FIXPT_SCALE);
keypoints.clear();
TLSData<std::vector<KeyPoint> > tls_kpts_struct;
for( int o = 0; o < nOctaves; o++ )
for( int i = 1; i <= nOctaveLayers; i++ )
{
const int idx = o*(nOctaveLayers+2)+i;
const Mat& img = dog_pyr[idx];
const int step = (int)img.step1();
const int rows = img.rows, cols = img.cols;
parallel_for_(Range(SIFT_IMG_BORDER, rows-SIFT_IMG_BORDER),
findScaleSpaceExtremaComputer(
o, i, threshold, idx, step, cols,
nOctaveLayers,
contrastThreshold,
edgeThreshold,
sigma,
gauss_pyr, dog_pyr, tls_kpts_struct));
}
std::vector<std::vector<KeyPoint>*> kpt_vecs;
tls_kpts_struct.gather(kpt_vecs);
for (size_t i = 0; i < kpt_vecs.size(); ++i) {
keypoints.insert(keypoints.end(), kpt_vecs[i]->begin(), kpt_vecs[i]->end());
}
}
@ -1081,7 +1153,7 @@ void SIFT_Impl::detectAndCompute(InputArray _image, InputArray _mask,
{
//t = (double)getTickCount();
findScaleSpaceExtrema(gpyr, dogpyr, keypoints);
KeyPointsFilter::removeDuplicated( keypoints );
KeyPointsFilter::removeDuplicatedSorted( keypoints );
if( nfeatures > 0 )
KeyPointsFilter::retainBest(keypoints, nfeatures);

@ -893,7 +893,7 @@ void SURF_Impl::detectAndCompute(InputArray _img, InputArray _mask,
CV_Assert(_descriptors.needed() || !useProvidedKeypoints);
#ifdef HAVE_OPENCL
if( ocl::useOpenCL() )
if( ocl::useOpenCL() && _img.isUMat())
{
SURF_OCL ocl_surf;
UMat gpu_kpt;

@ -91,11 +91,13 @@ bool SURF_OCL::init(const SURF_Impl* p)
if(ocl::haveOpenCL())
{
const ocl::Device& dev = ocl::Device::getDefault();
if( dev.type() == ocl::Device::TYPE_CPU || dev.doubleFPConfig() == 0 )
if( dev.type() == ocl::Device::TYPE_CPU )
return false;
haveImageSupport = false;//dev.imageSupport();
kerOpts = haveImageSupport ? "-D HAVE_IMAGE2D -D DOUBLE_SUPPORT" : "";
// status = 1;
haveImageSupport = dev.imageSupport();
kerOpts = format("%s%s",
haveImageSupport ? "-D HAVE_IMAGE2D" : "",
dev.doubleFPConfig() > 0? " -D DOUBLE_SUPPORT": "");
status = 1;
}
}
return status > 0;
@ -243,7 +245,7 @@ bool SURF_OCL::computeDescriptors(const UMat &keypoints, OutputArray _descriptor
}
size_t localThreads[] = {6, 6};
size_t globalThreads[] = {nFeatures*localThreads[0], localThreads[1]};
size_t globalThreads[] = {nFeatures*localThreads[0], 16 * localThreads[1]};
if(haveImageSupport)
{
@ -420,7 +422,7 @@ bool SURF_OCL::findMaximaInLayer(int counterOffset, int octave,
ocl::KernelArg::PtrReadWrite(maxPosBuffer),
ocl::KernelArg::PtrReadWrite(counters),
counterOffset, img_rows, img_cols,
octave, nOctaveLayers,
nOctaveLayers, octave,
layer_rows, layer_cols,
maxCandidates,
(float)params->hessianThreshold).run(2, globalThreads, localThreads, true);

@ -357,9 +357,9 @@ protected:
}
if(imgLoadMode == IMREAD_GRAYSCALE)
image.create( 50, 50, CV_8UC1 );
image.create( 256, 256, CV_8UC1 );
else
image.create( 50, 50, CV_8UC3 );
image.create( 256, 256, CV_8UC3 );
try
{
dextractor->compute( image, keypoints, descriptors );
@ -408,7 +408,18 @@ protected:
Mat calcDescriptors;
double t = (double)getTickCount();
dextractor->compute( img, keypoints, calcDescriptors );
#ifdef HAVE_OPENCL
if(ocl::useOpenCL())
{
cv::UMat uimg;
img.copyTo(uimg);
dextractor->compute(uimg, keypoints, calcDescriptors);
}
else
#endif
{
dextractor->compute(img, keypoints, calcDescriptors);
}
t = getTickCount() - t;
ts->printf(cvtest::TS::LOG, "\nAverage time of computing one descriptor = %g ms.\n", t/((double)getTickFrequency()*1000.)/calcDescriptors.rows );
@ -1027,11 +1038,35 @@ TEST( Features2d_DescriptorExtractor_SIFT, regression )
TEST( Features2d_DescriptorExtractor_SURF, regression )
{
#ifdef HAVE_OPENCL
bool useOCL = ocl::useOpenCL();
ocl::setUseOpenCL(false);
#endif
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-surf", 0.05f,
SURF::create() );
test.safe_run();
#ifdef HAVE_OPENCL
ocl::setUseOpenCL(useOCL);
#endif
}
#ifdef HAVE_OPENCL
TEST( Features2d_DescriptorExtractor_SURF_OCL, regression )
{
bool useOCL = ocl::useOpenCL();
ocl::setUseOpenCL(true);
if(ocl::useOpenCL())
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-surf_ocl", 0.05f,
SURF::create() );
test.safe_run();
}
ocl::setUseOpenCL(useOCL);
}
#endif
TEST( Features2d_DescriptorExtractor_DAISY, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-daisy", 0.05f,
@ -1187,7 +1222,7 @@ TEST(Features2d_BruteForceDescriptorMatcher_knnMatch, regression)
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce");
ASSERT_TRUE(matcher != NULL);
Mat imgT(sz, sz, CV_8U, Scalar(255));
Mat imgT(256, 256, CV_8U, Scalar(255));
line(imgT, Point(20, sz/2), Point(sz-21, sz/2), Scalar(100), 2);
line(imgT, Point(sz/2, 20), Point(sz/2, sz-21), Scalar(100), 2);
vector<KeyPoint> kpT;
@ -1196,7 +1231,7 @@ TEST(Features2d_BruteForceDescriptorMatcher_knnMatch, regression)
Mat descT;
ext->compute(imgT, kpT, descT);
Mat imgQ(sz, sz, CV_8U, Scalar(255));
Mat imgQ(256, 256, CV_8U, Scalar(255));
line(imgQ, Point(30, sz/2), Point(sz-31, sz/2), Scalar(100), 3);
line(imgQ, Point(sz/2, 30), Point(sz/2, sz-31), Scalar(100), 3);
vector<KeyPoint> kpQ;
@ -1253,8 +1288,20 @@ protected:
}
vector<KeyPoint> kpt1, kpt2;
Mat d1, d2;
f2d->detectAndCompute(img1, Mat(), kpt1, d1);
f2d->detectAndCompute(img1, Mat(), kpt2, d2);
#ifdef HAVE_OPENCL
if(ocl::useOpenCL())
{
cv::UMat uimg1;
img1.copyTo(uimg1);
f2d->detectAndCompute(uimg1, Mat(), kpt1, d1);
f2d->detectAndCompute(uimg1, Mat(), kpt2, d2);
}
else
#endif
{
f2d->detectAndCompute(img1, Mat(), kpt1, d1);
f2d->detectAndCompute(img1, Mat(), kpt2, d2);
}
for( size_t i = 0; i < kpt1.size(); i++ )
CV_Assert(kpt1[i].response > 0 );
for( size_t i = 0; i < kpt2.size(); i++ )

@ -21,8 +21,8 @@
#include "opencv2/opencv_modules.hpp"
#include "cvconfig.h"
#ifdef HAVE_OPENCV_OCL
# include "opencv2/ocl.hpp"
#ifdef HAVE_OPENCL
# include "opencv2/core/ocl.hpp"
#endif
#ifdef HAVE_CUDA

@ -168,9 +168,6 @@ void matchKeyPoints(const vector<KeyPoint>& keypoints0, const Mat& H,
const float r0 = 0.5f * keypoints0[i0].size;
for(size_t i1 = 0; i1 < keypoints1.size(); i1++)
{
if(nearestPointIndex >= 0 && usedMask[i1])
continue;
float r1 = 0.5f * keypoints1[i1].size;
float intersectRatio = calcIntersectRatio(points0t.at<Point2f>(i0), r0,
keypoints1[i1].pt, r1);
@ -619,7 +616,7 @@ protected:
TEST(Features2d_RotationInvariance_Detector_SURF, regression)
{
DetectorRotationInvarianceTest test(SURF::create(),
0.44f,
0.65f,
0.76f);
test.safe_run();
}
@ -859,10 +856,21 @@ TEST(Features2d_RotationInvariance2_Detector_SURF, regression)
vector<KeyPoint> keypoints;
surf->detect(cross, keypoints);
// Expect 5 keypoints. One keypoint has coordinates (50.0, 50.0).
// The other 4 keypoints should have the same response.
// The order of the keypoints is indeterminate.
ASSERT_EQ(keypoints.size(), (vector<KeyPoint>::size_type) 5);
ASSERT_LT( fabs(keypoints[1].response - keypoints[2].response), 1e-6);
ASSERT_LT( fabs(keypoints[1].response - keypoints[3].response), 1e-6);
ASSERT_LT( fabs(keypoints[1].response - keypoints[4].response), 1e-6);
int i1 = -1;
for(int i = 0; i < 5; i++)
{
if(keypoints[i].pt.x == 50.0f)
;
else if(i1 == -1)
i1 = i;
else
ASSERT_LT(fabs(keypoints[i1].response - keypoints[i].response) / keypoints[i1].response, 1e-6);
}
}
TEST(DISABLED_Features2d_ScaleInvariance_Descriptor_DAISY, regression)
@ -942,7 +950,7 @@ TEST(Features2d_ScaleInvariance_Descriptor_BoostDesc_LBGM, regression)
DescriptorScaleInvarianceTest test(SURF::create(),
BoostDesc::create(BoostDesc::LBGM, true, 6.25f),
NORM_L1,
0.98f);
0.95f);
test.safe_run();
}

@ -45,11 +45,13 @@
#include "test_precomp.hpp"
#ifdef HAVE_OPENCV_OCL
#ifdef HAVE_OPENCL
namespace cvtest {
namespace ocl {
using namespace std;
using std::tr1::get;
static bool keyPointsEquals(const cv::KeyPoint& p1, const cv::KeyPoint& p2)
{
const double maxPtDif = 0.1;
@ -117,6 +119,7 @@ IMPLEMENT_PARAM_CLASS(Upright, bool)
PARAM_TEST_CASE(SURF, HessianThreshold, Octaves, OctaveLayers, Extended, Upright)
{
bool useOpenCL;
double hessianThreshold;
int nOctaves;
int nOctaveLayers;
@ -125,39 +128,34 @@ PARAM_TEST_CASE(SURF, HessianThreshold, Octaves, OctaveLayers, Extended, Upright
virtual void SetUp()
{
useOpenCL = cv::ocl::useOpenCL();
hessianThreshold = get<0>(GetParam());
nOctaves = get<1>(GetParam());
nOctaveLayers = get<2>(GetParam());
extended = get<3>(GetParam());
upright = get<4>(GetParam());
}
virtual void TearDown()
{
cv::ocl::setUseOpenCL(useOpenCL);
}
};
TEST_P(SURF, DISABLED_Detector)
TEST_P(SURF, Detector)
{
cv::Mat image = cv::imread(string(cvtest::TS::ptr()->get_data_path()) + "shared/fruits.png", cv::IMREAD_GRAYSCALE);
cv::UMat image;
cv::ocl::setUseOpenCL(true);
cv::imread(string(cvtest::TS::ptr()->get_data_path()) + "shared/fruits.png", cv::IMREAD_GRAYSCALE).copyTo(image);
ASSERT_FALSE(image.empty());
cv::ocl::SURF_OCL surf;
surf.hessianThreshold = static_cast<float>(hessianThreshold);
surf.nOctaves = nOctaves;
surf.nOctaveLayers = nOctaveLayers;
surf.extended = extended;
surf.upright = upright;
surf.keypointsRatio = 0.05f;
cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);
std::vector<cv::KeyPoint> keypoints;
surf(cv::ocl::oclMat(image), cv::ocl::oclMat(), keypoints);
cv::SURF surf_gold;
surf_gold.hessianThreshold = hessianThreshold;
surf_gold.nOctaves = nOctaves;
surf_gold.nOctaveLayers = nOctaveLayers;
surf_gold.extended = extended;
surf_gold.upright = upright;
surf->detect(image, keypoints, cv::noArray());
cv::ocl::setUseOpenCL(false);
std::vector<cv::KeyPoint> keypoints_gold;
surf_gold(image, cv::noArray(), keypoints_gold);
surf->detect(image, keypoints_gold, cv::noArray());
ASSERT_EQ(keypoints_gold.size(), keypoints.size());
int matchedCount = getMatchedPointsCount(keypoints_gold, keypoints);
@ -166,38 +164,29 @@ TEST_P(SURF, DISABLED_Detector)
EXPECT_GT(matchedRatio, 0.99);
}
TEST_P(SURF, DISABLED_Descriptor)
TEST_P(SURF, Descriptor)
{
cv::Mat image = cv::imread(string(cvtest::TS::ptr()->get_data_path()) + "shared/fruits.png", cv::IMREAD_GRAYSCALE);
cv::UMat image;
cv::ocl::setUseOpenCL(true);
cv::imread(string(cvtest::TS::ptr()->get_data_path()) + "shared/fruits.png", cv::IMREAD_GRAYSCALE).copyTo(image);
ASSERT_FALSE(image.empty());
cv::ocl::SURF_OCL surf;
surf.hessianThreshold = static_cast<float>(hessianThreshold);
surf.nOctaves = nOctaves;
surf.nOctaveLayers = nOctaveLayers;
surf.extended = extended;
surf.upright = upright;
surf.keypointsRatio = 0.05f;
cv::SURF surf_gold;
surf_gold.hessianThreshold = hessianThreshold;
surf_gold.nOctaves = nOctaves;
surf_gold.nOctaveLayers = nOctaveLayers;
surf_gold.extended = extended;
surf_gold.upright = upright;
cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright);
std::vector<cv::KeyPoint> keypoints;
surf_gold(image, cv::noArray(), keypoints);
surf->detect(image, keypoints, cv::noArray());
cv::ocl::oclMat descriptors;
surf(cv::ocl::oclMat(image), cv::ocl::oclMat(), keypoints, descriptors, true);
cv::UMat descriptors;
surf->detectAndCompute(image, cv::noArray(), keypoints, descriptors, true);
cv::ocl::setUseOpenCL(false);
cv::Mat descriptors_gold;
surf_gold(image, cv::noArray(), keypoints, descriptors_gold, true);
surf->detectAndCompute(image, cv::noArray(), keypoints, descriptors_gold, true);
cv::BFMatcher matcher(surf.defaultNorm());
cv::BFMatcher matcher(surf->defaultNorm());
std::vector<cv::DMatch> matches;
matcher.match(descriptors_gold, cv::Mat(descriptors), matches);
matcher.match(descriptors_gold, descriptors, matches);
int matchedCount = getMatchedPointsCount(keypoints, keypoints, matches);
double matchedRatio = static_cast<double>(matchedCount) / keypoints.size();
@ -212,4 +201,6 @@ INSTANTIATE_TEST_CASE_P(OCL_Features2D, SURF, testing::Combine(
testing::Values(Extended(false), Extended(true)),
testing::Values(Upright(false), Upright(true))));
#endif // HAVE_OPENCV_OCL
} } // namespace cvtest::ocl
#endif // HAVE_OPENCL

@ -12,3 +12,4 @@ Extended Image Processing
- Paillou Filter
- Fast Line Detector
- Deriche Filter
- Pei&Lin Normalization

@ -51,6 +51,7 @@
#include "ximgproc/paillou_filter.hpp"
#include "ximgproc/fast_line_detector.hpp"
#include "ximgproc/deriche_filter.hpp"
#include "ximgproc/peilin.hpp"
/** @defgroup ximgproc Extended Image Processing
@{

@ -0,0 +1,31 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef __OPENCV_PEILIN_HPP__
#define __OPENCV_PEILIN_HPP__
#include <opencv2/core.hpp>
namespace cv
{
//! @addtogroup ximgproc
//! @{
/**
* @brief Calculates an affine transformation that normalize given image using Pei&Lin Normalization.
*
* Assume given image \f$I=T(\bar{I})\f$ where \f$\bar{I}\f$ is a normalized image and \f$T\f$ is an affine transformation distorting this image by translation, rotation, scaling and skew.
* The function returns an affine transformation matrix corresponding to the transformation \f$T^{-1}\f$ described in [PeiLin95].
* For more details about this implementation, please see
* [PeiLin95] Soo-Chang Pei and Chao-Nan Lin. Image normalization for pattern recognition. Image and Vision Computing, Vol. 13, N.10, pp. 711-723, 1995.
*
* @param I Given transformed image.
* @return Transformation matrix corresponding to inversed image transformation
*/
CV_EXPORTS Matx23d PeiLinNormalization ( InputArray I );
/** @overload */
CV_EXPORTS_W void PeiLinNormalization ( InputArray I, OutputArray T );
}
#endif

@ -0,0 +1,59 @@
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/ximgproc.hpp>
#include <iostream>
static void help()
{
std::cout << "\nThis program demonstrates Pei&Lin Normalization\n"
"Usage:\n"
"./peilin [image1_name -- default is ../data/peilin_plane.png] [image2_name -- default is ../data/peilin_shape.png]\n" << std::endl;
}
static inline cv::Mat operator& ( const cv::Mat& lhs, const cv::Matx23d& rhs )
{
cv::Mat ret;
cv::warpAffine ( lhs, ret, rhs, lhs.size(), cv::INTER_LINEAR );
return ret;
}
static inline cv::Mat operator& ( const cv::Matx23d& lhs, const cv::Mat& rhs )
{
cv::Mat ret;
cv::warpAffine ( rhs, ret, lhs, rhs.size(), cv::INTER_LINEAR | cv::WARP_INVERSE_MAP );
return ret;
}
int main(int argc, char** argv)
{
cv::CommandLineParser parser(argc, argv, "{help h | | }{ @input1 | ../data/peilin_plane.png | }{ @input2 | ../data/peilin_plane.png | }");
if (parser.has("help"))
{
help();
return 0;
}
std::string filename1 = parser.get<std::string>("@input1");
std::string filename2 = parser.get<std::string>("@input2");
cv::Mat I = cv::imread(filename1, 0);
if (I.empty())
{
std::cout << "Couldn't open image " << filename1 << std::endl;
return 0;
}
cv::Mat J = cv::imread(filename2, 0);
if (J.empty())
{
std::cout << "Couldn't open image " << filename2 << std::endl;
return 0;
}
cv::Mat N = I & cv::PeiLinNormalization ( I );
cv::Mat D = cv::PeiLinNormalization ( J ) & I;
cv::imshow ( "I", I );
cv::imshow ( "N", N );
cv::imshow ( "J", J );
cv::imshow ( "D", D );
cv::waitKey();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

@ -69,7 +69,7 @@ DTFilterCPU* DTFilterCPU::create_p_(const Mat& guide, double sigmaSpatial, doubl
template<typename GuideVec>
void DTFilterCPU::init_(Mat& guide, double sigmaSpatial_, double sigmaColor_, int mode_, int numIters_)
{
CV_Assert(guide.type() == cv::DataType<GuideVec>::type);
CV_Assert(guide.type() == traits::Type<GuideVec>::value);
this->release();
@ -123,7 +123,7 @@ template <typename SrcVec>
void DTFilterCPU::filter_(const Mat& src, Mat& dst, int dDepth)
{
typedef typename DataType<Vec<WorkType, SrcVec::channels> >::vec_type WorkVec;
CV_Assert( src.type() == SrcVec::type );
CV_Assert( src.type() == traits::Type<SrcVec>::value );
if ( src.cols != w || src.rows != h )
{
CV_Error(Error::StsBadSize, "Size of filtering image must be equal to size of guide image");
@ -139,17 +139,17 @@ void DTFilterCPU::filter_(const Mat& src, Mat& dst, int dDepth)
if (dDepth == -1) dDepth = src.depth();
//small optimization to avoid extra copying of data
bool useDstAsRes = (dDepth == WorkVec::depth && (mode == DTF_NC || mode == DTF_RF));
bool useDstAsRes = (dDepth == traits::Depth<WorkVec>::value && (mode == DTF_NC || mode == DTF_RF));
if (useDstAsRes)
{
dst.create(h, w, WorkVec::type);
dst.create(h, w, traits::Type<WorkVec>::value);
res = dst;
}
if (mode == DTF_NC)
{
Mat resT(src.cols, src.rows, WorkVec::type);
src.convertTo(res, WorkVec::type);
Mat resT(src.cols, src.rows, traits::Type<WorkVec>::value);
src.convertTo(res, traits::Type<WorkVec>::value);
FilterNC_horPass<WorkVec> horParBody(res, idistHor, resT);
FilterNC_horPass<WorkVec> vertParBody(resT, idistVert, res);
@ -180,7 +180,7 @@ void DTFilterCPU::filter_(const Mat& src, Mat& dst, int dDepth)
}
else if (mode == DTF_RF)
{
src.convertTo(res, WorkVec::type);
src.convertTo(res, traits::Type<WorkVec>::value);
for (int iter = 1; iter <= numIters; iter++)
{
@ -237,13 +237,13 @@ void DTFilterCPU::integrateSparseRow(const SrcVec *src, const float *dist, SrcWo
template<typename WorkVec>
void DTFilterCPU::prepareSrcImg_IC(const Mat& src, Mat& dst, Mat& dstT)
{
Mat dstOut(src.rows, src.cols + 2, WorkVec::type);
Mat dstOutT(src.cols, src.rows + 2, WorkVec::type);
Mat dstOut(src.rows, src.cols + 2, traits::Type<WorkVec>::value);
Mat dstOutT(src.cols, src.rows + 2, traits::Type<WorkVec>::value);
dst = dstOut(Range::all(), Range(1, src.cols+1));
dstT = dstOutT(Range::all(), Range(1, src.rows+1));
src.convertTo(dst, WorkVec::type);
src.convertTo(dst, traits::Type<WorkVec>::value);
WorkVec *line;
int ri = dstOut.cols - 1;
@ -270,7 +270,7 @@ template <typename WorkVec>
DTFilterCPU::FilterNC_horPass<WorkVec>::FilterNC_horPass(Mat& src_, Mat& idist_, Mat& dst_)
: src(src_), idist(idist_), dst(dst_), radius(1.0f)
{
CV_DbgAssert(src.type() == WorkVec::type && dst.type() == WorkVec::type && dst.rows == src.cols && dst.cols == src.rows);
CV_DbgAssert(src.type() == traits::Type<WorkVec>::value && dst.type() == traits::Type<WorkVec>::value && dst.rows == src.cols && dst.cols == src.rows);
}
template <typename WorkVec>
@ -324,12 +324,12 @@ template <typename WorkVec>
DTFilterCPU::FilterIC_horPass<WorkVec>::FilterIC_horPass(Mat& src_, Mat& idist_, Mat& dist_, Mat& dst_)
: src(src_), idist(idist_), dist(dist_), dst(dst_), radius(1.0f)
{
CV_DbgAssert(src.type() == WorkVec::type && dst.type() == WorkVec::type && dst.rows == src.cols && dst.cols == src.rows);
CV_DbgAssert(src.type() == traits::Type<WorkVec>::value && dst.type() == traits::Type<WorkVec>::value && dst.rows == src.cols && dst.cols == src.rows);
#ifdef CV_GET_NUM_THREAD_WORKS_PROPERLY
isrcBuf.create(cv::getNumThreads(), src.cols + 1, WorkVec::type);
isrcBuf.create(cv::getNumThreads(), src.cols + 1, traits::Type<WorkVec>::value);
#else
isrcBuf.create(src.rows, src.cols + 1, WorkVec::type);
isrcBuf.create(src.rows, src.cols + 1, traits::Type<WorkVec>::value);
#endif
}
@ -384,8 +384,8 @@ template <typename WorkVec>
DTFilterCPU::FilterRF_horPass<WorkVec>::FilterRF_horPass(Mat& res_, Mat& alphaD_, int iteration_)
: res(res_), alphaD(alphaD_), iteration(iteration_)
{
CV_DbgAssert(res.type() == WorkVec::type);
CV_DbgAssert(res.type() == WorkVec::type && res.size() == res.size());
CV_DbgAssert(res.type() == traits::Type<WorkVec>::value);
CV_DbgAssert(res.type() == traits::Type<WorkVec>::value && res.size() == res.size());
}
@ -421,8 +421,8 @@ template <typename WorkVec>
DTFilterCPU::FilterRF_vertPass<WorkVec>::FilterRF_vertPass(Mat& res_, Mat& alphaD_, int iteration_)
: res(res_), alphaD(alphaD_), iteration(iteration_)
{
CV_DbgAssert(res.type() == WorkVec::type);
CV_DbgAssert(res.type() == WorkVec::type && res.size() == res.size());
CV_DbgAssert(res.type() == traits::Type<WorkVec>::value);
CV_DbgAssert(res.type() == traits::Type<WorkVec>::value && res.size() == res.size());
}
@ -470,7 +470,7 @@ template <typename GuideVec>
DTFilterCPU::ComputeIDTHor_ParBody<GuideVec>::ComputeIDTHor_ParBody(DTFilterCPU& dtf_, Mat& guide_, Mat& dst_)
: dtf(dtf_), guide(guide_), dst(dst_)
{
dst.create(guide.rows, guide.cols + 1, IDistVec::type);
dst.create(guide.rows, guide.cols + 1, traits::Type<IDistVec>::value);
}
template <typename GuideVec>
@ -497,8 +497,8 @@ template <typename GuideVec>
DTFilterCPU::ComputeDTandIDTHor_ParBody<GuideVec>::ComputeDTandIDTHor_ParBody(DTFilterCPU& dtf_, Mat& guide_, Mat& dist_, Mat& idist_)
: dtf(dtf_), guide(guide_), dist(dist_), idist(idist_)
{
dist = getWExtendedMat(guide.rows, guide.cols, IDistVec::type, 1, 1);
idist = getWExtendedMat(guide.rows, guide.cols + 1, IDistVec::type);
dist = getWExtendedMat(guide.rows, guide.cols, traits::Type<IDistVec>::value, 1, 1);
idist = getWExtendedMat(guide.rows, guide.cols + 1, traits::Type<IDistVec>::value);
maxRadius = dtf.getIterRadius(1);
}
@ -535,7 +535,7 @@ template <typename GuideVec>
DTFilterCPU::ComputeA0DTHor_ParBody<GuideVec>::ComputeA0DTHor_ParBody(DTFilterCPU& dtf_, Mat& guide_)
: dtf(dtf_), guide(guide_)
{
dtf.a0distHor.create(guide.rows, guide.cols - 1, DistVec::type);
dtf.a0distHor.create(guide.rows, guide.cols - 1, traits::Type<DistVec>::value);
lna = std::log(dtf.getIterAlpha(1));
}
@ -565,7 +565,7 @@ template <typename GuideVec>
DTFilterCPU::ComputeA0DTVert_ParBody<GuideVec>::ComputeA0DTVert_ParBody(DTFilterCPU& dtf_, Mat& guide_)
: dtf(dtf_), guide(guide_)
{
dtf.a0distVert.create(guide.rows - 1, guide.cols, DistVec::type);
dtf.a0distVert.create(guide.rows - 1, guide.cols, traits::Type<DistVec>::value);
lna = std::log(dtf.getIterAlpha(1));
}

@ -148,16 +148,16 @@ void FastGlobalSmootherFilterImpl::init(InputArray guide,double _lambda,double _
num_iter = _num_iter;
num_stripes = getNumThreads();
int num_levels = 3*256*256;
weights_LUT.create(1,num_levels,WorkVec::type);
weights_LUT.create(1,num_levels,traits::Type<WorkVec>::value);
WorkType* LUT = (WorkType*)weights_LUT.ptr(0);
parallel_for_(Range(0,num_stripes),ComputeLUT_ParBody(*this,LUT,num_stripes,num_levels));
w = guide.cols();
h = guide.rows();
Chor. create(h,w,WorkVec::type);
Cvert. create(h,w,WorkVec::type);
interD.create(h,w,WorkVec::type);
Chor. create(h,w,traits::Type<WorkVec>::value);
Cvert. create(h,w,traits::Type<WorkVec>::value);
interD.create(h,w,traits::Type<WorkVec>::value);
Mat guideMat = guide.getMat();
if(guide.channels() == 1)
@ -201,8 +201,8 @@ void FastGlobalSmootherFilterImpl::filter(InputArray src, OutputArray dst)
{
lambda = lambda_ref;
Mat cur_res = src_channels[i].clone();
if(src.depth()!=WorkVec::type)
cur_res.convertTo(cur_res,WorkVec::type);
if(src.depth()!=traits::Type<WorkVec>::value)
cur_res.convertTo(cur_res,traits::Type<WorkVec>::value);
for(int n=0;n<num_iter;n++)
{
@ -212,7 +212,7 @@ void FastGlobalSmootherFilterImpl::filter(InputArray src, OutputArray dst)
}
Mat dstMat;
if(src.depth()!=WorkVec::type)
if(src.depth()!=traits::Type<WorkVec>::value)
cur_res.convertTo(dstMat,src.depth());
else
dstMat = cur_res;

@ -77,7 +77,7 @@ public:
joint(joint_), src(src_), dst(dst_), radius(radius_), maxk(maxk_),
scaleIndex(scaleIndex_), spaceOfs(spaceOfs_), spaceWeights(spaceWeights_), expLUT(expLUT_)
{
CV_DbgAssert(joint.type() == JointVec::type && src.type() == dst.type() && src.type() == SrcVec::type);
CV_DbgAssert(joint.type() == traits::Type<JointVec>::value && src.type() == dst.type() && src.type() == traits::Type<SrcVec>::value);
CV_DbgAssert(joint.rows == src.rows && src.rows == dst.rows + 2*radius);
CV_DbgAssert(joint.cols == src.cols && src.cols == dst.cols + 2*radius);
}
@ -223,7 +223,7 @@ public:
joint(joint_), src(src_), dst(dst_), radius(radius_), maxk(maxk_),
spaceOfs(spaceOfs_), spaceWeights(spaceWeights_), expLUT(expLUT_)
{
CV_DbgAssert(joint.type() == JointVec::type && src.type() == dst.type() && src.type() == SrcVec::type);
CV_DbgAssert(joint.type() == traits::Type<JointVec>::value && src.type() == dst.type() && src.type() == traits::Type<SrcVec>::value);
CV_DbgAssert(joint.rows == src.rows && src.rows == dst.rows + 2 * radius);
CV_DbgAssert(joint.cols == src.cols && src.cols == dst.cols + 2 * radius);
}

@ -0,0 +1,57 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
namespace cv
{
static inline Moments operator& ( const Moments & lhs, const Matx22d & rhs )
{
return Moments (
lhs.m00,
rhs ( 0, 0 ) * lhs.m10 + rhs ( 0, 1 ) * lhs.m01,
rhs ( 1, 0 ) * lhs.m10 + rhs ( 1, 1 ) * lhs.m01,
rhs ( 0, 0 ) * rhs ( 0, 0 ) * lhs.m20 + rhs ( 0, 1 ) * rhs ( 0, 1 ) * lhs.m02 + 2 * rhs ( 0, 0 ) * rhs ( 0, 1 ) * lhs.m11,
rhs ( 0, 0 ) * rhs ( 1, 0 ) * lhs.m20 + rhs ( 0, 1 ) * rhs ( 1, 1 ) * lhs.m02 + ( rhs ( 0, 0 ) * rhs ( 1, 1 ) + rhs ( 0, 1 ) * rhs ( 1, 0 ) ) * lhs.m11,
rhs ( 1, 0 ) * rhs ( 1, 0 ) * lhs.m20 + rhs ( 1, 1 ) * rhs ( 1, 1 ) * lhs.m02 + 2 * rhs ( 1, 0 ) * rhs ( 1, 1 ) * lhs.m11,
rhs ( 0, 0 ) * rhs ( 0, 0 ) * rhs ( 0, 0 ) * lhs.m30 + 3 * rhs ( 0, 0 ) * rhs ( 0, 0 ) * rhs ( 0, 1 ) * lhs.m21 + 3 * rhs ( 0, 0 ) * rhs ( 0, 1 ) * rhs ( 0, 1 ) * lhs.m12 + rhs ( 0, 1 ) * rhs ( 0, 1 ) * rhs ( 0, 1 ) * lhs.m03,
rhs ( 0, 0 ) * rhs ( 0, 0 ) * rhs ( 1, 0 ) * lhs.m30 + ( rhs ( 0, 0 ) * rhs ( 0, 0 ) * rhs ( 1, 1 ) + 2 * rhs ( 0, 0 ) * rhs ( 0, 1 ) * rhs ( 1, 0 ) ) * lhs.m21 + ( 2 * rhs ( 0, 0 ) * rhs ( 0, 1 ) * rhs ( 1, 1 ) + rhs ( 0, 1 ) * rhs ( 0, 1 ) * rhs ( 1, 0 ) ) * lhs.m12 + rhs ( 0, 1 ) * rhs ( 0, 1 ) * rhs ( 1, 1 ) * lhs.m03,
rhs ( 0, 0 ) * rhs ( 1, 0 ) * rhs ( 1, 0 ) * lhs.m30 + ( rhs ( 1, 0 ) * rhs ( 1, 0 ) * rhs ( 0, 1 ) + 2 * rhs ( 0, 0 ) * rhs ( 1, 0 ) * rhs ( 1, 1 ) ) * lhs.m21 + ( 2 * rhs ( 0, 1 ) * rhs ( 1, 0 ) * rhs ( 1, 1 ) + rhs ( 1, 1 ) * rhs ( 1, 1 ) * rhs ( 0, 0 ) ) * lhs.m12 + rhs ( 0, 1 ) * rhs ( 1, 1 ) * rhs ( 1, 1 ) * lhs.m03,
rhs ( 1, 0 ) * rhs ( 1, 0 ) * rhs ( 1, 0 ) * lhs.m30 + 3 * rhs ( 1, 0 ) * rhs ( 1, 0 ) * rhs ( 1, 1 ) * lhs.m21 + 3 * rhs ( 1, 0 ) * rhs ( 1, 1 ) * rhs ( 1, 1 ) * lhs.m12 + rhs ( 1, 1 ) * rhs ( 1, 1 ) * rhs ( 1, 1 ) * lhs.m03
);
}
static inline Matx23d operator| ( const Matx22d & lhs, const Matx21d & rhs )
{
return Matx23d ( lhs ( 0, 0 ), lhs ( 0, 1 ), rhs ( 0 ), lhs ( 1, 0 ), lhs ( 1, 1 ), rhs ( 1 ) );
}
Matx23d PeiLinNormalization ( InputArray I )
{
const Moments M = moments ( I );
const double l1 = ( M.mu20 / M.m00 + M.mu02 / M.m00 + sqrt ( ( M.mu20 / M.m00 - M.mu02 / M.m00 ) * ( M.mu20 / M.m00 - M.mu02 / M.m00 ) + 4 * M.mu11 / M.m00 * M.mu11 / M.m00 ) ) / 2;
const double l2 = ( M.mu20 / M.m00 + M.mu02 / M.m00 - sqrt ( ( M.mu20 / M.m00 - M.mu02 / M.m00 ) * ( M.mu20 / M.m00 - M.mu02 / M.m00 ) + 4 * M.mu11 / M.m00 * M.mu11 / M.m00 ) ) / 2;
const double ex = ( M.mu11 / M.m00 ) / sqrt ( ( l1 - M.mu20 / M.m00 ) * ( l1 - M.mu20 / M.m00 ) + M.mu11 / M.m00 * M.mu11 / M.m00 );
const double ey = ( l1 - M.mu20 / M.m00 ) / sqrt ( ( l1 - M.mu20 / M.m00 ) * ( l1 - M.mu20 / M.m00 ) + M.mu11 / M.m00 * M.mu11 / M.m00 );
const Matx22d E = Matx22d ( ex, ey, -ey, ex );
const double p = min ( I.size().height, I.size().width ) / 8;
const Matx22d W = Matx22d ( p / sqrt ( l1 ), 0, 0, p / sqrt ( l2 ) );
const Matx21d c = Matx21d ( M.m10 / M.m00, M.m01 / M.m00 );
const Matx21d i = Matx21d ( I.size().width / 2, I.size().height / 2 );
const Moments N = M & W * E;
const double t1 = N.mu12 + N.mu30;
const double t2 = N.mu03 + N.mu21;
const double phi = atan2 ( -t1, t2 );
const double psi = ( -t1 * sin ( phi ) + t2 * cos ( phi ) >= 0 ) ? phi : ( phi + CV_PI );
const Matx22d A = Matx22d ( cos ( psi ), sin ( psi ), -sin ( psi ), cos ( psi ) );
return ( A * W * E ) | ( i - A * W * E * c );
}
void PeiLinNormalization ( InputArray I, OutputArray T )
{
T.assign ( Mat ( PeiLinNormalization ( I ) ) );
}
}

@ -168,7 +168,7 @@ Mat getChessMat1px(Size sz, double whiteIntensity = 255)
{
typedef typename DataType<SrcVec>::channel_type SrcType;
Mat dst(sz, DataType<SrcVec>::type);
Mat dst(sz, traits::Type<SrcVec>::value);
SrcVec black = SrcVec::all(0);
SrcVec white = SrcVec::all((SrcType)whiteIntensity);

@ -113,7 +113,7 @@ template<typename JointVec, typename SrcVec>
void jointBilateralFilterNaive_(InputArray joint_, InputArray src_, OutputArray dst_, int d, double sigmaColor, double sigmaSpace, int borderType)
{
CV_Assert(joint_.size() == src_.size());
CV_Assert(joint_.type() == JointVec::type && src_.type() == SrcVec::type);
CV_Assert(joint_.type() == traits::Type<JointVec>::value && src_.type() == traits::Type<SrcVec>::value);
typedef Vec<float, SrcVec::channels> SrcVecf;
if (sigmaColor <= 0)

@ -22,9 +22,9 @@ TEST(ximpgroc_StructuredEdgeDetection, regression)
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 );
previousResult.convertTo( previousResult, CV_32F, 1/255.0 );
src.convertTo( src, cv::DataType<float>::type, 1/255.0 );
src.convertTo( src, CV_32F, 1/255.0 );
cv::Mat currentResult( src.size(), src.type() );
pDollar->detectEdges( src, currentResult );

Loading…
Cancel
Save