added edgeboxes algorithm (#1215)
samples added fix edgeboxes_demo fix edgeboxes_demo added edgeboxes bib fix edgeboxes_demo small fixes fix edgeboxes_demo fix warnings fix warnings small fixes detectEdges needs rgb image instead bgr image. Removed unnecessary protection small fixespull/1408/head
parent
a44a2ba730
commit
1f8ccc1687
7 changed files with 1313 additions and 0 deletions
@ -0,0 +1,200 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_EDGEBOXES_HPP__ |
||||
#define __OPENCV_EDGEBOXES_HPP__ |
||||
|
||||
#include <opencv2/core.hpp> |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace ximgproc |
||||
{ |
||||
|
||||
//! @addtogroup ximgproc_edgeboxes
|
||||
//! @{
|
||||
|
||||
// bounding box data structures
|
||||
typedef struct
|
||||
{ |
||||
int x, y, w, h; |
||||
float score; |
||||
} Box; |
||||
|
||||
typedef std::vector<Box> Boxes; |
||||
|
||||
/** @brief Class implementing EdgeBoxes algorithm from @cite ZitnickECCV14edgeBoxes :
|
||||
*/ |
||||
class CV_EXPORTS_W EdgeBoxes : public Algorithm |
||||
{ |
||||
|
||||
public: |
||||
|
||||
/** @brief Returns array containing proposal boxes.
|
||||
|
||||
@param edge_map edge image. |
||||
@param orientation_map orientation map. |
||||
@param boxes proposal boxes. |
||||
*/ |
||||
CV_WRAP virtual void getBoundingBoxes(InputArray edge_map, InputArray orientation_map, CV_OUT std::vector<Rect> &boxes) = 0; |
||||
|
||||
/** @brief Returns the step size of sliding window search.
|
||||
*/ |
||||
CV_WRAP virtual float getAlpha() const = 0; |
||||
/** @brief Sets the step size of sliding window search.
|
||||
*/ |
||||
CV_WRAP virtual void setAlpha(float value) = 0; |
||||
|
||||
/** @brief Returns the nms threshold for object proposals.
|
||||
*/ |
||||
CV_WRAP virtual float getBeta() const = 0; |
||||
/** @brief Sets the nms threshold for object proposals.
|
||||
*/ |
||||
CV_WRAP virtual void setBeta(float value) = 0; |
||||
|
||||
/** @brief Returns adaptation rate for nms threshold.
|
||||
*/ |
||||
CV_WRAP virtual float getEta() const = 0; |
||||
/** @brief Sets the adaptation rate for nms threshold.
|
||||
*/ |
||||
CV_WRAP virtual void setEta(float value) = 0; |
||||
|
||||
/** @brief Returns the min score of boxes to detect.
|
||||
*/ |
||||
CV_WRAP virtual float getMinScore() const = 0; |
||||
/** @brief Sets the min score of boxes to detect.
|
||||
*/ |
||||
CV_WRAP virtual void setMinScore(float value) = 0; |
||||
|
||||
/** @brief Returns the max number of boxes to detect.
|
||||
*/ |
||||
CV_WRAP virtual int getMaxBoxes() const = 0; |
||||
/** @brief Sets max number of boxes to detect.
|
||||
*/ |
||||
CV_WRAP virtual void setMaxBoxes(int value) = 0; |
||||
|
||||
/** @brief Returns the edge min magnitude.
|
||||
*/ |
||||
CV_WRAP virtual float getEdgeMinMag() const = 0; |
||||
/** @brief Sets the edge min magnitude.
|
||||
*/ |
||||
CV_WRAP virtual void setEdgeMinMag(float value) = 0; |
||||
|
||||
/** @brief Returns the edge merge threshold.
|
||||
*/ |
||||
CV_WRAP virtual float getEdgeMergeThr() const = 0; |
||||
/** @brief Sets the edge merge threshold.
|
||||
*/ |
||||
CV_WRAP virtual void setEdgeMergeThr(float value) = 0; |
||||
|
||||
/** @brief Returns the cluster min magnitude.
|
||||
*/ |
||||
CV_WRAP virtual float getClusterMinMag() const = 0; |
||||
/** @brief Sets the cluster min magnitude.
|
||||
*/ |
||||
CV_WRAP virtual void setClusterMinMag(float value) = 0; |
||||
|
||||
/** @brief Returns the max aspect ratio of boxes.
|
||||
*/ |
||||
CV_WRAP virtual float getMaxAspectRatio() const = 0; |
||||
/** @brief Sets the max aspect ratio of boxes.
|
||||
*/ |
||||
CV_WRAP virtual void setMaxAspectRatio(float value) = 0; |
||||
|
||||
/** @brief Returns the minimum area of boxes.
|
||||
*/ |
||||
CV_WRAP virtual float getMinBoxArea() const = 0; |
||||
/** @brief Sets the minimum area of boxes.
|
||||
*/ |
||||
CV_WRAP virtual void setMinBoxArea(float value) = 0; |
||||
|
||||
/** @brief Returns the affinity sensitivity.
|
||||
*/ |
||||
CV_WRAP virtual float getGamma() const = 0; |
||||
/** @brief Sets the affinity sensitivity
|
||||
*/ |
||||
CV_WRAP virtual void setGamma(float value) = 0; |
||||
|
||||
/** @brief Returns the scale sensitivity.
|
||||
*/ |
||||
CV_WRAP virtual float getKappa() const = 0; |
||||
/** @brief Sets the scale sensitivity.
|
||||
*/ |
||||
CV_WRAP virtual void setKappa(float value) = 0; |
||||
|
||||
}; |
||||
|
||||
/** @brief Creates a Edgeboxes
|
||||
|
||||
@param alpha step size of sliding window search. |
||||
@param beta nms threshold for object proposals. |
||||
@param eta adaptation rate for nms threshold. |
||||
@param minScore min score of boxes to detect. |
||||
@param maxBoxes max number of boxes to detect. |
||||
@param edgeMinMag edge min magnitude. Increase to trade off accuracy for speed. |
||||
@param edgeMergeThr edge merge threshold. Increase to trade off accuracy for speed. |
||||
@param clusterMinMag cluster min magnitude. Increase to trade off accuracy for speed. |
||||
@param maxAspectRatio max aspect ratio of boxes. |
||||
@param minBoxArea minimum area of boxes. |
||||
@param gamma affinity sensitivity. |
||||
@param kappa scale sensitivity. |
||||
*/ |
||||
CV_EXPORTS_W Ptr<EdgeBoxes> |
||||
createEdgeBoxes(float alpha=0.65f, |
||||
float beta=0.75f, |
||||
float eta=1, |
||||
float minScore=0.01f, |
||||
int maxBoxes=10000, |
||||
float edgeMinMag=0.1f, |
||||
float edgeMergeThr=0.5f, |
||||
float clusterMinMag=0.5f, |
||||
float maxAspectRatio=3, |
||||
float minBoxArea=1000, |
||||
float gamma=2, |
||||
float kappa=1.5f); |
||||
|
||||
//! @}
|
||||
|
||||
} |
||||
} |
||||
|
||||
#endif /* __OPENCV_EDGEBOXES_HPP__ */ |
@ -0,0 +1,94 @@ |
||||
/*
|
||||
By downloading, copying, installing or using the software you agree to this |
||||
license. If you do not agree to this license, do not download, install, |
||||
copy or use the software. |
||||
License Agreement |
||||
For Open Source Computer Vision Library |
||||
(3-clause BSD License) |
||||
Copyright (C) 2013, OpenCV Foundation, all rights reserved. |
||||
Third party copyrights are property of their respective owners. |
||||
Redistribution and use in source and binary forms, with or without modification, |
||||
are permitted provided that the following conditions are met: |
||||
* Redistributions of source code must retain the above copyright notice, |
||||
this list of conditions and the following disclaimer. |
||||
* Redistributions in binary form must reproduce the above copyright notice, |
||||
this list of conditions and the following disclaimer in the documentation |
||||
and/or other materials provided with the distribution. |
||||
* Neither the names of the copyright holders nor the names of the contributors |
||||
may be used to endorse or promote products derived from this software |
||||
without specific prior written permission. |
||||
This software is provided by the copyright holders and contributors "as is" and |
||||
any express or implied warranties, including, but not limited to, the implied |
||||
warranties of merchantability and fitness for a particular purpose are |
||||
disclaimed. In no event shall copyright holders or contributors be liable for |
||||
any direct, indirect, incidental, special, exemplary, or consequential damages |
||||
(including, but not limited to, procurement of substitute goods or services; |
||||
loss of use, data, or profits; or business interruption) however caused |
||||
and on any theory of liability, whether in contract, strict liability, |
||||
or tort (including negligence or otherwise) arising in any way out of |
||||
the use of this software, even if advised of the possibility of such damage. |
||||
*/ |
||||
|
||||
#include "opencv2/ximgproc.hpp" |
||||
#include "opencv2/highgui.hpp" |
||||
#include "opencv2/imgproc.hpp" |
||||
#include <iostream> |
||||
|
||||
using namespace std; |
||||
using namespace cv; |
||||
using namespace cv::ximgproc; |
||||
|
||||
static void help() |
||||
{ |
||||
std::cout << std::endl << |
||||
"This sample demonstrates structured edge detection and edgeboxes." << std::endl << |
||||
"Usage:" << std::endl << |
||||
"./edgeboxes_demo [<model>] [<input_image>]" << std::endl; |
||||
} |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
|
||||
if (argc < 3) |
||||
{ |
||||
help(); |
||||
return -1; |
||||
} |
||||
|
||||
Ptr<StructuredEdgeDetection> pDollar = createStructuredEdgeDetection(argv[1]); |
||||
|
||||
Mat im; |
||||
im = imread(argv[2]); |
||||
|
||||
Mat rgb_im; |
||||
cvtColor(im, rgb_im, COLOR_BGR2RGB); |
||||
rgb_im.convertTo(rgb_im, CV_32F, 1.0 / 255.0f); |
||||
|
||||
Mat edge_im; |
||||
pDollar->detectEdges(rgb_im, edge_im); |
||||
|
||||
// computes orientation from edge map
|
||||
Mat O; |
||||
pDollar->computeOrientation(edge_im, O); |
||||
|
||||
// apply edge nms
|
||||
Mat edge_nms; |
||||
pDollar->edgesNms(edge_im, O, edge_nms, 2, 0, 1, true); |
||||
|
||||
std::vector<Rect> boxes; |
||||
Ptr<EdgeBoxes> edgeboxes = createEdgeBoxes(); |
||||
edgeboxes->setMaxBoxes(30); |
||||
edgeboxes->getBoundingBoxes(edge_nms, O, boxes); |
||||
|
||||
for(int i = 0; i < (int)boxes.size(); i++) |
||||
{ |
||||
Point p1(boxes[i].x, boxes[i].y), p2(boxes[i].x + boxes[i].width, boxes[i].y + boxes[i].height); |
||||
Scalar color(0, 255, 0); |
||||
rectangle(im, p1, p2, color, 1); |
||||
} |
||||
|
||||
imshow("im", im); |
||||
waitKey(0); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,38 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
''' |
||||
This sample demonstrates structured edge detection and edgeboxes. |
||||
Usage: |
||||
edgeboxes_demo.py [<model>] [<input_image>] |
||||
''' |
||||
|
||||
import cv2 |
||||
import numpy as np |
||||
import sys |
||||
|
||||
if __name__ == '__main__': |
||||
print(__doc__) |
||||
|
||||
model = sys.argv[1] |
||||
im = cv2.imread(sys.argv[2]) |
||||
|
||||
edge_detection = cv2.ximgproc.createStructuredEdgeDetection(model) |
||||
rgb_im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) |
||||
edges = edge_detection.detectEdges(np.float32(rgb_im) / 255.0) |
||||
|
||||
orimap = edge_detection.computeOrientation(edges) |
||||
edges = edge_detection.edgesNms(edges, orimap) |
||||
|
||||
edge_boxes = cv2.ximgproc.createEdgeBoxes() |
||||
edge_boxes.setMaxBoxes(30) |
||||
boxes = edge_boxes.getBoundingBoxes(edges, orimap) |
||||
|
||||
for b in boxes: |
||||
x, y, w, h = b |
||||
cv2.rectangle(im, (x, y), (x+w, y+h), (0, 255, 0), 1, cv2.LINE_AA) |
||||
|
||||
cv2.imshow("edges", edges) |
||||
cv2.imshow("edgeboxes", im) |
||||
cv2.waitKey(0) |
||||
cv2.destroyAllWindows() |
@ -0,0 +1,970 @@ |
||||
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
/*
|
||||
Generate Edge Boxes object proposals in given image(s). |
||||
Compute Edge Boxes object proposals as described in: |
||||
C. Lawrence Zitnick and Piotr Dollár |
||||
"Edge Boxes: Locating Object Proposals from Edges", ECCV 2014. |
||||
The proposal boxes are fast to compute and give state-of-the-art recall. |
||||
OpenCV port by: Leonardo Lontra <lhe dot lontra at gmail dot com> |
||||
*/ |
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
inline int clamp(int v, int min, int max) |
||||
{ |
||||
return v < min ? min : v > max ? max : v; |
||||
} |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace ximgproc |
||||
{ |
||||
|
||||
class EdgeBoxesImpl : public EdgeBoxes |
||||
{ |
||||
public: |
||||
|
||||
EdgeBoxesImpl(float alpha, |
||||
float beta, |
||||
float eta, |
||||
float minScore, |
||||
int maxBoxes, |
||||
float edgeMinMag, |
||||
float edgeMergeThr, |
||||
float clusterMinMag, |
||||
float maxAspectRatio, |
||||
float minBoxArea, |
||||
float gamma, |
||||
float kappa); |
||||
|
||||
virtual void getBoundingBoxes(InputArray edge_map, InputArray orientation_map, std::vector<Rect> &boxes); |
||||
|
||||
float getAlpha() const { return _alpha; } |
||||
void setAlpha(float value) |
||||
{ |
||||
_alpha = value; |
||||
_sxStep = sqrt(1 / _alpha); |
||||
_ayStep = (1 + _alpha) / (2 * _alpha); |
||||
_xyStepRatio = (1 - _alpha) / (1 + _alpha); |
||||
} |
||||
|
||||
float getBeta() const { return _beta; } |
||||
void setBeta(float value) { _beta = value; } |
||||
|
||||
float getEta() const { return _eta; } |
||||
void setEta(float value) { _eta = value; } |
||||
|
||||
float getMinScore() const { return _minScore; } |
||||
void setMinScore(float value) { _minScore = value; } |
||||
|
||||
int getMaxBoxes() const { return _maxBoxes; } |
||||
void setMaxBoxes(int value) { _maxBoxes = value; } |
||||
|
||||
float getEdgeMinMag() const { return _edgeMinMag; } |
||||
void setEdgeMinMag(float value) { _edgeMinMag = value; } |
||||
|
||||
float getEdgeMergeThr() const { return _edgeMergeThr; } |
||||
void setEdgeMergeThr(float value) { _edgeMergeThr = value; } |
||||
|
||||
float getClusterMinMag() const { return _clusterMinMag; } |
||||
void setClusterMinMag(float value) { _clusterMinMag = value; } |
||||
|
||||
float getMaxAspectRatio() const { return _maxAspectRatio; } |
||||
void setMaxAspectRatio(float value) { _maxAspectRatio = value; } |
||||
|
||||
float getMinBoxArea() const { return _minBoxArea; } |
||||
void setMinBoxArea(float value) { _minBoxArea = value; } |
||||
|
||||
float getGamma() const { return _gamma; } |
||||
void setGamma(float value) { _gamma = value; } |
||||
|
||||
float getKappa() const { return _kappa; } |
||||
void setKappa(float value) |
||||
{ |
||||
_kappa = value; |
||||
_scaleNorm.resize(10000); |
||||
for (int i = 0; i < 10000; i++) _scaleNorm[i] = pow(1.f / i, _kappa); |
||||
} |
||||
|
||||
//! the destructor
|
||||
virtual ~EdgeBoxesImpl() {} |
||||
|
||||
private: |
||||
float _alpha; |
||||
float _beta; |
||||
float _eta; |
||||
float _minScore; |
||||
int _maxBoxes; |
||||
float _edgeMinMag; |
||||
float _edgeMergeThr; |
||||
float _clusterMinMag; |
||||
float _maxAspectRatio; |
||||
float _minBoxArea; |
||||
float _gamma; |
||||
float _kappa; |
||||
|
||||
// edge segment information (see clusterEdges)
|
||||
int h, w; // image dimensions
|
||||
int _segCnt; // total segment count
|
||||
Mat _segIds; // segment ids (-1/0 means no segment)
|
||||
vector<float> _segMag; // segment edge magnitude sums
|
||||
vector<Point2i> _segP; // segment lower-right pixel
|
||||
vector<vector<float> > _segAff; // segment affinities
|
||||
vector<vector<int> > _segAffIdx; // segment neighbors
|
||||
|
||||
// data structures for efficiency (see prepDataStructs)
|
||||
Mat _segIImg, _magIImg; |
||||
Mat _hIdxImg, _vIdxImg; |
||||
vector<vector<int> > _hIdxs, _vIdxs; |
||||
vector<float> _scaleNorm; |
||||
float _sxStep, _ayStep, _xyStepRatio; |
||||
|
||||
// data structures for efficiency (see scoreBox)
|
||||
Mat _sWts; |
||||
Mat _sDone, _sMap, _sIds; |
||||
int _sId; |
||||
|
||||
// helper routines
|
||||
static bool boxesCompare(const Box &a, const Box &b) { return a.score < b.score; } |
||||
void clusterEdges(Mat &edgeMap, Mat &orientationMap); |
||||
void prepDataStructs(Mat &edgeMap); |
||||
void scoreAllBoxes(Boxes &boxes); |
||||
void scoreBox(Box &box); |
||||
void refineBox(Box &box); |
||||
float boxesOverlap(Box &a, Box &b); |
||||
void boxesNms(Boxes &boxes, float thr, float eta, int maxBoxes); |
||||
}; |
||||
|
||||
|
||||
EdgeBoxesImpl::EdgeBoxesImpl(float alpha, |
||||
float beta, |
||||
float eta, |
||||
float minScore, |
||||
int maxBoxes, |
||||
float edgeMinMag, |
||||
float edgeMergeThr, |
||||
float clusterMinMag, |
||||
float maxAspectRatio, |
||||
float minBoxArea, |
||||
float gamma, |
||||
float kappa) |
||||
: _alpha(alpha), |
||||
_beta(beta), |
||||
_eta(eta), |
||||
_minScore(minScore), |
||||
_maxBoxes(maxBoxes), |
||||
_edgeMinMag(edgeMinMag), |
||||
_edgeMergeThr(edgeMergeThr), |
||||
_clusterMinMag(clusterMinMag), |
||||
_maxAspectRatio(maxAspectRatio), |
||||
_minBoxArea(minBoxArea), |
||||
_gamma(gamma), |
||||
_kappa(kappa) |
||||
|
||||
{ |
||||
// initialize step sizes
|
||||
_sxStep = sqrt(1 / _alpha); |
||||
_ayStep = (1 + _alpha) / (2 * _alpha); |
||||
_xyStepRatio = (1 - _alpha) / (1 + _alpha); |
||||
|
||||
// create _scaleNorm
|
||||
_scaleNorm.resize(10000); |
||||
for (int i = 0; i < 10000; i++) _scaleNorm[i] = pow(1.f / i, _kappa); |
||||
|
||||
} |
||||
|
||||
|
||||
void EdgeBoxesImpl::clusterEdges(Mat &edgeMap, Mat &orientationMap) |
||||
{ |
||||
int x, y, xd, yd, i, j; |
||||
|
||||
// greedily merge connected edge pixels into clusters (create _segIds)
|
||||
_segIds = Mat::zeros(w, h, DataType<int>::type); |
||||
_segCnt = 1; |
||||
for (x = 0; x < w; x++) |
||||
{ |
||||
const float *e_ptr = edgeMap.ptr<float>(x); |
||||
int *s_ptr = _segIds.ptr<int>(x); |
||||
for (y = 0; y < h; y++) |
||||
{ |
||||
if (x == 0 || y == 0 || x == w - 1 || y == h - 1 || e_ptr[y] <= _edgeMinMag) |
||||
{ |
||||
s_ptr[y] = -1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
int *s_ptr = _segIds.ptr<int>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
if (s_ptr[y] != 0) continue; |
||||
float sumv = 0; |
||||
int x0 = x; |
||||
int y0 = y; |
||||
vector<float> vs; |
||||
vector<int> xs, ys; |
||||
|
||||
while (sumv < _edgeMergeThr) |
||||
{ |
||||
_segIds.at<int>(x0, y0) = _segCnt; |
||||
float o0 = orientationMap.at<float>(x0, y0); |
||||
float o1, v; |
||||
bool found; |
||||
for (xd = -1; xd <= 1; xd++) |
||||
{ |
||||
const int *s0_ptr = _segIds.ptr<int>(x0 + xd); |
||||
const float *o_ptr = orientationMap.ptr<float>(x0 + xd); |
||||
for (yd = -1; yd <= 1; yd++) |
||||
{ |
||||
if (s0_ptr[y0 + yd] != 0) continue; |
||||
found = false; |
||||
for (i = 0; i < (int)xs.size(); i++) |
||||
{ |
||||
if (xs[i] == x0 + xd && ys[i] == y0 + yd) |
||||
{ |
||||
found = true; |
||||
break; |
||||
} |
||||
} |
||||
if (found) continue; |
||||
o1 = o_ptr[y0 + yd]; |
||||
v = fabs(o1 - o0) / (float)CV_PI; |
||||
if (v > .5f) v = 1 - v; |
||||
vs.push_back(v); |
||||
xs.push_back(x0 + xd); |
||||
ys.push_back(y0 + yd); |
||||
} |
||||
} |
||||
float minv = 1000; |
||||
j = 0; |
||||
for (i = 0; i < (int)vs.size(); i++) |
||||
{ |
||||
if (vs[i] < minv) |
||||
{ |
||||
minv = vs[i]; |
||||
x0 = xs[i]; |
||||
y0 = ys[i]; |
||||
j = i; |
||||
} |
||||
} |
||||
sumv += minv; |
||||
if (minv < 1000) vs[j] = 1000; |
||||
} |
||||
|
||||
_segCnt++; |
||||
} |
||||
} |
||||
|
||||
// merge or remove small segments
|
||||
_segMag.resize(_segCnt, 0); |
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
const float *e_ptr = edgeMap.ptr<float>(x); |
||||
const int *s_ptr = _segIds.ptr<int>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
j = s_ptr[y]; |
||||
if (j > 0) _segMag[j] += e_ptr[y]; |
||||
} |
||||
} |
||||
|
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
int *s_ptr = _segIds.ptr<int>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
j = s_ptr[y]; |
||||
if (j > 0 && _segMag[j] <= _clusterMinMag) |
||||
s_ptr[y] = 0; |
||||
} |
||||
} |
||||
|
||||
i = 1; |
||||
while (i > 0) |
||||
{ |
||||
i = 0; |
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
int *s0_ptr = _segIds.ptr<int>(x); |
||||
const float *o0_ptr = orientationMap.ptr<float>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
if (s0_ptr[y] != 0) continue; |
||||
float o0 = o0_ptr[y]; |
||||
float o1, v, minv = 1000; |
||||
j = 0; |
||||
|
||||
for (xd = -1; xd <= 1; xd++) |
||||
{ |
||||
const int *s1_ptr = _segIds.ptr<int>(x+xd); |
||||
const float *o1_ptr = orientationMap.ptr<float>(x+xd); |
||||
for (yd = -1; yd <= 1; yd++) |
||||
{ |
||||
if (s1_ptr[y + yd] <= 0) continue; |
||||
o1 = o1_ptr[y + yd]; |
||||
v = fabs(o1 - o0) / (float)CV_PI; |
||||
if (v > .5f) v = 1 - v; |
||||
if (v < minv) |
||||
{ |
||||
minv = v; |
||||
j = s1_ptr[y + yd]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
s0_ptr[y] = j; |
||||
if (j > 0) i++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// compactify representation
|
||||
_segMag.assign(_segCnt, 0); |
||||
vector<int> map(_segCnt, 0); |
||||
_segCnt = 1; |
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
const float *e_ptr = edgeMap.ptr<float>(x); |
||||
const int *s_ptr = _segIds.ptr<int>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
j = s_ptr[y]; |
||||
if (j > 0) _segMag[j] += e_ptr[y]; |
||||
} |
||||
} |
||||
|
||||
for (i = 0; i < (int)_segMag.size(); i++) |
||||
{ |
||||
if (_segMag[i] > 0) map[i] = _segCnt++; |
||||
} |
||||
|
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
int *s_ptr = _segIds.ptr<int>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
j = s_ptr[y]; |
||||
if (j > 0) s_ptr[y] = map[j]; |
||||
} |
||||
} |
||||
|
||||
// compute positional means and recompute _segMag
|
||||
_segMag.assign(_segCnt, 0); |
||||
vector<float> meanX(_segCnt, 0), meanY(_segCnt, 0); |
||||
vector<float> meanOx(_segCnt, 0), meanOy(_segCnt, 0), meanO(_segCnt, 0); |
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
int *s_ptr = _segIds.ptr<int>(x); |
||||
const float *e_ptr = edgeMap.ptr<float>(x); |
||||
const float *o_ptr = orientationMap.ptr<float>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
j = s_ptr[y]; |
||||
if (j <= 0) continue; |
||||
float m = e_ptr[y]; |
||||
float o = o_ptr[y]; |
||||
_segMag[j] += m; |
||||
meanOx[j] += m * cos(2 * o); |
||||
meanOy[j] += m * sin(2 * o); |
||||
meanX[j] += m * x; |
||||
meanY[j] += m * y; |
||||
} |
||||
} |
||||
|
||||
for (i = 0; i < _segCnt; i++) |
||||
{ |
||||
if (_segMag[i] > 0) |
||||
{ |
||||
float m = _segMag[i]; |
||||
meanX[i] /= m; |
||||
meanY[i] /= m; |
||||
meanO[i] = atan2(meanOy[i] / m, meanOx[i] / m) / 2; |
||||
} |
||||
} |
||||
|
||||
// compute segment affinities
|
||||
_segAff.resize(_segCnt); |
||||
_segAffIdx.resize(_segCnt); |
||||
for (i = 0; i < _segCnt; i++) |
||||
{ |
||||
_segAff[i].resize(0); |
||||
_segAffIdx[i].resize(0); |
||||
} |
||||
|
||||
const int rad = 2; |
||||
for (x = rad; x < w - rad; x++) |
||||
{ |
||||
const int *s0_ptr = _segIds.ptr<int>(x); |
||||
for (y = rad; y < h - rad; y++) |
||||
{ |
||||
int s0 = s0_ptr[y]; |
||||
if (s0 <= 0) continue; |
||||
for (xd = -rad; xd <= rad; xd++) |
||||
{ |
||||
const int *s1_ptr = _segIds.ptr<int>(x+xd); |
||||
for (yd = -rad; yd <= rad; yd++) |
||||
{ |
||||
int s1 = s1_ptr[y + yd]; |
||||
if (s1 <= s0) continue; |
||||
bool found = false; |
||||
|
||||
for (i = 0; i < (int)_segAffIdx[s0].size(); i++) |
||||
{ |
||||
if (_segAffIdx[s0][i] == s1) |
||||
{ |
||||
found = true; |
||||
break; |
||||
} |
||||
} |
||||
if (found) continue; |
||||
float o = atan2(meanY[s0] - meanY[s1], meanX[s0] - meanX[s1]) + (float)CV_PI / 2.0f; |
||||
float a = fabs(cos(meanO[s0] - o) * cos(meanO[s1] - o)); |
||||
a = pow(a, _gamma); |
||||
_segAff[s0].push_back(a); |
||||
_segAffIdx[s0].push_back(s1); |
||||
_segAff[s1].push_back(a); |
||||
_segAffIdx[s1].push_back(s0); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// compute _segC and _segR
|
||||
_segP.resize(_segCnt); |
||||
for (x = 1; x < w - 1; x++) |
||||
{ |
||||
const int *s_ptr = _segIds.ptr<int>(x); |
||||
for (y = 1; y < h - 1; y++) |
||||
{ |
||||
j = s_ptr[y]; |
||||
if (j > 0) |
||||
{ |
||||
_segP[j] = Point2i(x, y); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
void EdgeBoxesImpl::prepDataStructs(Mat &edgeMap) |
||||
{ |
||||
int y, x, i; |
||||
|
||||
// create _segIImg
|
||||
Mat E1 = Mat::zeros(w, h, DataType<float>::type); |
||||
|
||||
for (i=0; i < _segCnt; i++) |
||||
{ |
||||
if (_segMag[i] > 0) E1.at<float>(_segP[i].x, _segP[i].y) = _segMag[i]; |
||||
} |
||||
|
||||
_segIImg = Mat::zeros(w+1, h+1, DataType<float>::type); |
||||
_magIImg = Mat::zeros(w+1, h+1, DataType<float>::type); |
||||
|
||||
for (x=1; x < w; x++) |
||||
{ |
||||
const float *e_ptr = edgeMap.ptr<float>(x); |
||||
const float *e1_ptr = E1.ptr<float>(x); |
||||
const float *si0_ptr = _segIImg.ptr<float>(x); |
||||
float *si1_ptr = _segIImg.ptr<float>(x+1); |
||||
const float *mi0_ptr = _magIImg.ptr<float>(x); |
||||
float *mi1_ptr =_magIImg.ptr<float>(x+1); |
||||
for (y=1; y < h; y++) |
||||
{ |
||||
// create _segIImg
|
||||
si1_ptr[y+1] = e1_ptr[y] + si0_ptr[y+1] + si1_ptr[y] - si0_ptr[y]; |
||||
float e = e_ptr[y] > _edgeMinMag ? e_ptr[y] : 0; |
||||
// create _magIImg
|
||||
mi1_ptr[y+1] = e +mi0_ptr[y+1] + mi1_ptr[y] - mi0_ptr[y]; |
||||
} |
||||
} |
||||
|
||||
// create remaining data structures
|
||||
int s = 0; |
||||
int s1; |
||||
|
||||
_hIdxs.resize(h); |
||||
_hIdxImg = Mat::zeros(w, h, DataType<int>::type); |
||||
for (y = 0; y < h; y++) |
||||
{ |
||||
s = 0; |
||||
_hIdxs[y].push_back(s); |
||||
for (x = 0; x < w; x++) |
||||
{ |
||||
s1 = _segIds.at<int>(x, y); |
||||
if (s1 != s) |
||||
{ |
||||
s = s1; |
||||
_hIdxs[y].push_back(s); |
||||
} |
||||
_hIdxImg.at<int>(x, y) = (int)_hIdxs[y].size() - 1; |
||||
} |
||||
} |
||||
|
||||
_vIdxs.resize(w); |
||||
_vIdxImg = Mat::zeros(w, h, DataType<int>::type); |
||||
for (x = 0; x < w; x++) |
||||
{ |
||||
s = 0; |
||||
_vIdxs[x].push_back(s); |
||||
for (y = 0; y < h; y++) |
||||
{ |
||||
s1 = _segIds.at<int>(x, y); |
||||
if (s1 != s) |
||||
{ |
||||
s = s1; |
||||
_vIdxs[x].push_back(s); |
||||
} |
||||
_vIdxImg.at<int>(x, y) = (int)_vIdxs[x].size() - 1; |
||||
} |
||||
} |
||||
|
||||
// initialize scoreBox() data structures
|
||||
int n = _segCnt + 1; |
||||
_sWts = Mat::zeros(n, 1, DataType<float>::type); |
||||
_sDone = Mat::zeros(n, 1, DataType<int>::type); |
||||
_sMap = Mat::zeros(n, 1, DataType<int>::type); |
||||
_sIds = Mat::zeros(n, 1, DataType<int>::type); |
||||
for (i = 0; i < n; i++) _sDone.at<int>(0, i) = -1; |
||||
_sId = 0; |
||||
} |
||||
|
||||
|
||||
void EdgeBoxesImpl::scoreBox(Box &box) |
||||
{ |
||||
int i, j, k, q, bh, bw, y0, x0, y1, x1, y0m, y1m, x0m, x1m; |
||||
float *sWts = (float *)_sWts.data; |
||||
int *sDone = (int *)_sDone.data; |
||||
int *sMap = (int *)_sMap.data; |
||||
int *sIds = (int *)_sIds.data; |
||||
int sId = _sId++; |
||||
|
||||
// add edge count inside box
|
||||
y1 = clamp(box.y + box.h, 0, h - 1); |
||||
y0 = box.y = clamp(box.y, 0, h - 1); |
||||
x1 = clamp(box.x + box.w, 0, w - 1); |
||||
x0 = box.x = clamp(box.x, 0, w - 1); |
||||
bh = box.h = y1 - box.y; |
||||
bh /= 2; |
||||
bw = box.w = x1 - box.x; |
||||
bw /= 2; |
||||
float v = _segIImg.at<float>(x0, y0) + _segIImg.at<float>(x1 + 1, y1 + 1) |
||||
- _segIImg.at<float>(x1 + 1, y0) - _segIImg.at<float>(x0, y1 + 1); |
||||
|
||||
// subtract middle quarter of edges
|
||||
y0m = y0 + bh / 2; |
||||
y1m = y0m + bh; |
||||
x0m = x0 + bw / 2; |
||||
x1m = x0m + bw; |
||||
v -= _magIImg.at<float>(x0m, y0m) + _magIImg.at<float>(x1m + 1, y1m + 1) |
||||
- _magIImg.at<float>(x1m + 1, y0m) - _magIImg.at<float>(x0m, y1m + 1); |
||||
|
||||
// short circuit computation if impossible to score highly
|
||||
float norm = _scaleNorm[bw + bh]; |
||||
box.score = v * norm; |
||||
if (box.score < _minScore) |
||||
{ |
||||
box.score = 0; |
||||
return; |
||||
} |
||||
|
||||
// find interesecting segments along four boundaries
|
||||
int cs, ce, rs, re, n = 0; |
||||
cs = _hIdxImg.at<int>(x0, y0); |
||||
ce = _hIdxImg.at<int>(x1, y0); // top
|
||||
for (i = cs; i <= ce; i++) |
||||
{ |
||||
j = _hIdxs[y0][i]; |
||||
if (j > 0 && sDone[j] != sId) |
||||
{ |
||||
sIds[n] = j; |
||||
sWts[n] = 1; |
||||
sDone[j] = sId; |
||||
sMap[j] = n++; |
||||
} |
||||
} |
||||
|
||||
cs = _hIdxImg.at<int>(x0, y1); |
||||
ce = _hIdxImg.at<int>(x1, y1); // bottom
|
||||
for (i = cs; i <= ce; i++) |
||||
{ |
||||
j = _hIdxs[y1][i]; |
||||
if (j > 0 && sDone[j] != sId) |
||||
{ |
||||
sIds[n] = j; |
||||
sWts[n] = 1; |
||||
sDone[j] = sId; |
||||
sMap[j] = n++; |
||||
} |
||||
} |
||||
|
||||
rs = _vIdxImg.at<int>(x0, y0); |
||||
re = _vIdxImg.at<int>(x0, y1); // left
|
||||
for (i = rs; i <= re; i++) |
||||
{ |
||||
j = _vIdxs[x0][i]; |
||||
if (j > 0 && sDone[j] != sId) |
||||
{ |
||||
sIds[n] = j; |
||||
sWts[n] = 1; |
||||
sDone[j] = sId; |
||||
sMap[j] = n++; |
||||
} |
||||
} |
||||
|
||||
rs = _vIdxImg.at<int>(x1, y0); |
||||
re = _vIdxImg.at<int>(x1, y1); // right
|
||||
for (i = rs; i <= re; i++) |
||||
{ |
||||
j = _vIdxs[x1][i]; |
||||
if (j > 0 && sDone[j] != sId) |
||||
{ |
||||
sIds[n] = j; |
||||
sWts[n] = 1; |
||||
sDone[j] = sId; |
||||
sMap[j] = n++; |
||||
} |
||||
} |
||||
|
||||
// follow connected paths and set weights accordingly (ws=1 means remove)
|
||||
for (i = 0; i < n; i++) |
||||
{ |
||||
float ws = sWts[i]; |
||||
j = sIds[i]; |
||||
for (k = 0; k < (int)_segAffIdx[j].size(); k++) |
||||
{ |
||||
q = _segAffIdx[j][k]; |
||||
float wq = ws * _segAff[j][k]; |
||||
if (wq < .05f) continue; // short circuit for efficiency
|
||||
if (sDone[q] == sId) |
||||
{ |
||||
if (wq > sWts[sMap[q]]) |
||||
{ |
||||
sWts[sMap[q]] = wq; |
||||
i = min(i, sMap[q] - 1); |
||||
} |
||||
} |
||||
else if (_segP[q].x >= x0 && _segP[q].x <= x1 && _segP[q].y >= y0 && _segP[q].y <= y1) |
||||
{ |
||||
sIds[n] = q; |
||||
sWts[n] = wq; |
||||
sDone[q] = sId; |
||||
sMap[q] = n++; |
||||
} |
||||
} |
||||
} |
||||
// finally remove segments connected to boundaries
|
||||
for (i = 0; i < n; i++) |
||||
{ |
||||
k = sIds[i]; |
||||
if (_segP[k].x >= x0 && _segP[k].x <= x1 && _segP[k].y >= y0 && _segP[k].y <= y1) v -= sWts[i] * _segMag[k]; |
||||
} |
||||
|
||||
v *= norm; |
||||
if (v < _minScore) v = 0; |
||||
box.score = v; |
||||
} |
||||
|
||||
|
||||
void EdgeBoxesImpl::refineBox(Box &box) |
||||
{ |
||||
int yStep = (int)(box.h * _xyStepRatio); |
||||
int xStep = (int)(box.w * _xyStepRatio); |
||||
while (1) |
||||
{ |
||||
// prepare for iteration
|
||||
yStep /= 2; |
||||
xStep /= 2; |
||||
if (yStep <= 2 && xStep <= 2) break; |
||||
yStep = max(1, yStep); |
||||
xStep = max(1, xStep); |
||||
Box B; |
||||
// search over y start
|
||||
B = box; |
||||
B.y = box.y - yStep; |
||||
B.h = B.h + yStep; |
||||
scoreBox(B); |
||||
|
||||
if (B.score <= box.score) |
||||
{ |
||||
B = box; |
||||
B.y = box.y + yStep; |
||||
B.h = B.h - yStep; |
||||
scoreBox(B); |
||||
} |
||||
if (B.score > box.score) box = B; |
||||
// search over y end
|
||||
B = box; |
||||
B.h = B.h + yStep; |
||||
scoreBox(B); |
||||
|
||||
if (B.score <= box.score) |
||||
{ |
||||
B = box; |
||||
B.h = B.h - yStep; |
||||
scoreBox(B); |
||||
} |
||||
if (B.score > box.score) box = B; |
||||
// search over x start
|
||||
B = box; |
||||
B.x = box.x - xStep; |
||||
B.w = B.w + xStep; |
||||
scoreBox(B); |
||||
|
||||
if (B.score <= box.score) |
||||
{ |
||||
B = box; |
||||
B.x = box.x + xStep; |
||||
B.w = B.w - xStep; |
||||
scoreBox(B); |
||||
} |
||||
|
||||
if (B.score > box.score) box = B; |
||||
// search over x end
|
||||
B = box; |
||||
B.w = B.w + xStep; |
||||
scoreBox(B); |
||||
|
||||
if (B.score <= box.score) |
||||
{ |
||||
B = box; |
||||
B.w = B.w - xStep; |
||||
scoreBox(B); |
||||
} |
||||
if (B.score > box.score) box = B; |
||||
} |
||||
} |
||||
|
||||
void EdgeBoxesImpl::scoreAllBoxes(Boxes &boxes) |
||||
{ |
||||
// get list of all boxes roughly distributed in grid
|
||||
boxes.resize(0); |
||||
int ayRad, sxNum; |
||||
float minSize = sqrt(_minBoxArea); |
||||
ayRad = (int)(log(_maxAspectRatio) / log(_ayStep * _ayStep)); |
||||
sxNum = (int)(ceil(log(max(w, h) / minSize) / log(_sxStep))); |
||||
|
||||
for (int s = 0; s < sxNum; s++) |
||||
{ |
||||
int a, y, x, bh, bw, ky, kx = -1; |
||||
float ay, sx; |
||||
for (a = 0; a < 2 * ayRad + 1; a++) |
||||
{ |
||||
ay = pow(_ayStep, float(a - ayRad)); |
||||
sx = minSize * pow(_sxStep, float(s)); |
||||
bh = (int)(sx / ay); |
||||
ky = max(2, (int)(bh * _xyStepRatio)); |
||||
bw = (int)(sx * ay); |
||||
kx = max(2, (int)(bw * _xyStepRatio)); |
||||
for (x = 0; x < w - bw + kx; x += kx) |
||||
{ |
||||
for (y = 0; y < h - bh + ky; y += ky) |
||||
{ |
||||
Box b; |
||||
b.y = y; |
||||
b.x = x; |
||||
b.h = bh; |
||||
b.w = bw; |
||||
boxes.push_back(b); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// score all boxes, refine top candidates
|
||||
int i, k = 0, m = (int)boxes.size(); |
||||
for (i = 0; i < m; i++) |
||||
{ |
||||
scoreBox(boxes[i]); |
||||
if (!boxes[i].score) continue; |
||||
k++; |
||||
refineBox(boxes[i]); |
||||
} |
||||
sort(boxes.rbegin(), boxes.rend(), boxesCompare); |
||||
boxes.resize(k); |
||||
} |
||||
|
||||
|
||||
float EdgeBoxesImpl::boxesOverlap(Box &a, Box &b) |
||||
{ |
||||
float areai, areaj, areaij; |
||||
int y0, y1, x0, x1, y1i, x1i, y1j, x1j; |
||||
y1i = a.y + a.h; |
||||
x1i = a.x + a.w; |
||||
if (a.y >= y1i || a.x >= x1i) return 0; |
||||
|
||||
y1j = b.y + b.h; |
||||
x1j = b.x + b.w; |
||||
if (a.y >= y1j || a.x >= x1j) return 0; |
||||
|
||||
areai = (float) a.w * a.h; |
||||
y0 = max(a.y, b.y); |
||||
y1 = min(y1i, y1j); |
||||
areaj = (float) b.w * b.h; |
||||
x0 = max(a.x, b.x); |
||||
x1 = min(x1i, x1j); |
||||
areaij = (float) max(0, y1 - y0) * max(0, x1 - x0); |
||||
return areaij / (areai + areaj - areaij); |
||||
} |
||||
|
||||
|
||||
void EdgeBoxesImpl::boxesNms(Boxes &boxes, float thr, float eta, int maxBoxes) |
||||
{ |
||||
sort(boxes.rbegin(), boxes.rend(), boxesCompare); |
||||
if (thr > .99f) return; |
||||
|
||||
const int nBin = 10000; |
||||
const float step = 1 / thr; |
||||
const float lstep = log(step); |
||||
|
||||
vector<Boxes> kept; |
||||
kept.resize(nBin + 1); |
||||
int n = (int) boxes.size(); |
||||
int i = 0; |
||||
int j, k, b; |
||||
int m = 0; |
||||
int d = 1; |
||||
|
||||
while (i < n && m < maxBoxes) |
||||
{ |
||||
b = boxes[i].w * boxes[i].h; |
||||
|
||||
bool keep = 1; |
||||
b = clamp((int)(ceil(log(float(b)) / lstep)), d, nBin - d); |
||||
for (j = b - d; j <= b + d; j++) |
||||
{ |
||||
for (k = 0; k < (int)kept[j].size(); k++) |
||||
{ |
||||
if (keep) |
||||
keep = boxesOverlap(boxes[i], kept[j][k]) <= thr; |
||||
} |
||||
} |
||||
|
||||
if (keep) |
||||
{ |
||||
kept[b].push_back(boxes[i]); |
||||
m++; |
||||
} |
||||
|
||||
i++; |
||||
if (keep && eta < 1.0f && thr > .5f) |
||||
{ |
||||
thr *= eta; |
||||
d = (int)ceil(log(1.0f / thr) / lstep); |
||||
} |
||||
} |
||||
|
||||
boxes.resize(m); |
||||
i = 0; |
||||
for (j = 0; j < nBin; j++) |
||||
{ |
||||
for (k = 0; k < (int)kept[j].size(); k++) |
||||
{ |
||||
boxes[i++] = kept[j][k]; |
||||
} |
||||
} |
||||
sort(boxes.rbegin(), boxes.rend(), boxesCompare); |
||||
} |
||||
|
||||
|
||||
void EdgeBoxesImpl::getBoundingBoxes(InputArray edge_map, InputArray orientation_map, std::vector<Rect> &boxes) |
||||
{ |
||||
CV_Assert(edge_map.depth() == CV_32F); |
||||
CV_Assert(orientation_map.depth() == CV_32F); |
||||
|
||||
Mat E = edge_map.getMat().t(); |
||||
Mat O = orientation_map.getMat().t(); |
||||
|
||||
h = E.cols; |
||||
w = E.rows; |
||||
|
||||
clusterEdges(E, O); |
||||
prepDataStructs(E); |
||||
|
||||
Boxes b; |
||||
scoreAllBoxes(b); |
||||
boxesNms(b, _beta, _eta, _maxBoxes); |
||||
|
||||
// create output boxes
|
||||
int n = (int) b.size(); |
||||
boxes.resize(n); |
||||
for(int i=0; i < n; i++) |
||||
{ |
||||
boxes[i] = Rect((int)b[i].x + 1, (int)b[i].y + 1, (int)b[i].w, (int)b[i].h); |
||||
} |
||||
} |
||||
|
||||
|
||||
Ptr<EdgeBoxes> createEdgeBoxes(float alpha, |
||||
float beta, |
||||
float eta, |
||||
float minScore, |
||||
int maxBoxes, |
||||
float edgeMinMag, |
||||
float edgeMergeThr, |
||||
float clusterMinMag, |
||||
float maxAspectRatio, |
||||
float minBoxArea, |
||||
float gamma, |
||||
float kappa) |
||||
{ |
||||
return makePtr<EdgeBoxesImpl>(alpha, |
||||
beta, |
||||
eta, |
||||
minScore, |
||||
maxBoxes, |
||||
edgeMinMag, |
||||
edgeMergeThr, |
||||
clusterMinMag, |
||||
maxAspectRatio, |
||||
minBoxArea, |
||||
gamma, |
||||
kappa); |
||||
} |
||||
|
||||
} |
||||
} |
Loading…
Reference in new issue