mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-18 00:01:17 +08:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -27,9 +27,15 @@ endif()
|
||||
if(NOT DEFINED GFLAGS_INCLUDE_DIRS AND DEFINED GFLAGS_INCLUDE_DIR)
|
||||
set(GFLAGS_INCLUDE_DIRS "${GFLAGS_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(NOT GFLAGS_LIBRARIES AND TARGET gflags::gflags)
|
||||
set(GFLAGS_LIBRARIES gflags::gflags)
|
||||
endif()
|
||||
if(NOT DEFINED GLOG_INCLUDE_DIRS AND DEFINED GLOG_INCLUDE_DIR)
|
||||
set(GLOG_INCLUDE_DIRS "${GLOG_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(NOT GLOG_LIBRARIES AND TARGET glog::glog)
|
||||
set(GLOG_LIBRARIES glog::glog)
|
||||
endif()
|
||||
|
||||
if((gflags_FOUND OR Gflags_FOUND OR GFLAGS_FOUND OR GFLAGS_INCLUDE_DIRS) AND (glog_FOUND OR Glog_FOUND OR GLOG_FOUND OR GLOG_INCLUDE_DIRS))
|
||||
set(__cache_key "${GLOG_INCLUDE_DIRS} ~ ${GFLAGS_INCLUDE_DIRS} ~ ${GLOG_LIBRARIES} ~ ${GFLAGS_LIBRARIES}")
|
||||
|
@@ -8,7 +8,7 @@ FILE(GLOB CORRESPONDENCE_HDRS *.h)
|
||||
|
||||
ADD_LIBRARY(correspondence STATIC ${CORRESPONDENCE_SRC} ${CORRESPONDENCE_HDRS})
|
||||
|
||||
TARGET_LINK_LIBRARIES(correspondence LINK_PRIVATE ${GLOG_LIBRARY} multiview)
|
||||
TARGET_LINK_LIBRARIES(correspondence LINK_PRIVATE ${GLOG_LIBRARIES} multiview)
|
||||
IF(TARGET Eigen3::Eigen)
|
||||
TARGET_LINK_LIBRARIES(correspondence LINK_PUBLIC Eigen3::Eigen)
|
||||
ENDIF()
|
||||
|
@@ -17,7 +17,7 @@ SET(MULTIVIEW_SRC conditioning.cc
|
||||
FILE(GLOB MULTIVIEW_HDRS *.h)
|
||||
|
||||
ADD_LIBRARY(multiview STATIC ${MULTIVIEW_SRC} ${MULTIVIEW_HDRS})
|
||||
TARGET_LINK_LIBRARIES(multiview LINK_PRIVATE ${GLOG_LIBRARY} numeric)
|
||||
TARGET_LINK_LIBRARIES(multiview LINK_PRIVATE ${GLOG_LIBRARIES} numeric)
|
||||
IF(TARGET Eigen3::Eigen)
|
||||
TARGET_LINK_LIBRARIES(multiview LINK_PUBLIC Eigen3::Eigen)
|
||||
ENDIF()
|
||||
|
@@ -81,6 +81,17 @@ i.e. algorithms which somehow takes into account pixel affinities in natural ima
|
||||
|
||||
@defgroup ximgproc_edge_drawing EdgeDrawing
|
||||
|
||||
EDGE DRAWING LIBRARY FOR GEOMETRIC FEATURE EXTRACTION AND VALIDATION
|
||||
|
||||
Edge Drawing (ED) algorithm is an proactive approach on edge detection problem. In contrast to many other existing edge detection algorithms which follow a subtractive
|
||||
approach (i.e. after applying gradient filters onto an image eliminating pixels w.r.t. several rules, e.g. non-maximal suppression and hysteresis in Canny), ED algorithm
|
||||
works via an additive strategy, i.e. it picks edge pixels one by one, hence the name Edge Drawing. Then we process those random shaped edge segments to extract higher level
|
||||
edge features, i.e. lines, circles, ellipses, etc. The popular method of extraction edge pixels from the thresholded gradient magnitudes is non-maximal supression that tests
|
||||
every pixel whether it has the maximum gradient response along its gradient direction and eliminates if it does not. However, this method does not check status of the
|
||||
neighboring pixels, and therefore might result low quality (in terms of edge continuity, smoothness, thinness, localization) edge segments. Instead of non-maximal supression,
|
||||
ED points a set of edge pixels and join them by maximizing the total gradient response of edge segments. Therefore it can extract high quality edge segments without need for
|
||||
an additional hysteresis step.
|
||||
|
||||
@defgroup ximgproc_fourier Fourier descriptors
|
||||
|
||||
@defgroup ximgproc_run_length_morphology Binary morphology on run-length encoded image
|
||||
|
@@ -16,17 +16,6 @@ namespace ximgproc
|
||||
//! @{
|
||||
|
||||
/** @brief Class implementing the ED (EdgeDrawing) @cite topal2012edge, EDLines @cite akinlar2011edlines, EDPF @cite akinlar2012edpf and EDCircles @cite akinlar2013edcircles algorithms
|
||||
|
||||
EDGE DRAWING LIBRARY FOR GEOMETRIC FEATURE EXTRACTION AND VALIDATION
|
||||
|
||||
Edge Drawing (ED) algorithm is an proactive approach on edge detection problem. In contrast to many other existing edge detection algorithms which follow a subtractive
|
||||
approach (i.e. after applying gradient filters onto an image eliminating pixels w.r.t. several rules, e.g. non-maximal suppression and hysteresis in Canny), ED algorithm
|
||||
works via an additive strategy, i.e. it picks edge pixels one by one, hence the name Edge Drawing. Then we process those random shaped edge segments to extract higher level
|
||||
edge features, i.e. lines, circles, ellipses, etc. The popular method of extraction edge pixels from the thresholded gradient magnitudes is non-maximal supressiun that tests
|
||||
every pixel whether it has the maximum gradient response along its gradient direction and eliminates if it does not. However, this method does not check status of the
|
||||
neighboring pixels, and therefore might result low quality (in terms of edge continuity, smoothness, thinness, localization) edge segments. Instead of non-maximal supression,
|
||||
ED points a set of edge pixels and join them by maximizing the total gradient response of edge segments. Therefore it can extract high quality edge segments without need for
|
||||
an additional hysteresis step.
|
||||
*/
|
||||
|
||||
class CV_EXPORTS_W EdgeDrawing : public Algorithm
|
||||
|
@@ -12,6 +12,86 @@ namespace cv
|
||||
namespace ximgproc
|
||||
{
|
||||
|
||||
struct ComputeGradientBody : ParallelLoopBody
|
||||
{
|
||||
void operator() (const Range& range) const CV_OVERRIDE;
|
||||
|
||||
Mat_<uchar> src;
|
||||
mutable Mat_<ushort> gradImage;
|
||||
mutable Mat_<uchar> dirImage;
|
||||
int gradThresh;
|
||||
int op;
|
||||
bool SumFlag;
|
||||
int* grads;
|
||||
bool PFmode;
|
||||
};
|
||||
|
||||
void ComputeGradientBody::operator() (const Range& range) const
|
||||
{
|
||||
const int last_col = src.cols - 1;
|
||||
int gx = 0;
|
||||
int gy = 0;
|
||||
int sum;
|
||||
|
||||
for (int y = range.start; y < range.end; ++y)
|
||||
{
|
||||
const uchar* srcPrevRow = src[y - 1];
|
||||
const uchar* srcCurRow = src[y];
|
||||
const uchar* srcNextRow = src[y + 1];
|
||||
|
||||
ushort* gradRow = gradImage[y];
|
||||
uchar* dirRow = dirImage[y];
|
||||
|
||||
for (int x = 1; x < last_col; ++x)
|
||||
{
|
||||
int com1 = srcNextRow[x + 1] - srcPrevRow[x - 1];
|
||||
int com2 = srcPrevRow[x + 1] - srcNextRow[x - 1];
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case EdgeDrawing::PREWITT:
|
||||
gx = abs(com1 + com2 + srcCurRow[x + 1] - srcCurRow[x - 1]);
|
||||
gy = abs(com1 - com2 + srcNextRow[x] - srcPrevRow[x]);
|
||||
break;
|
||||
case EdgeDrawing::SOBEL:
|
||||
gx = abs(com1 + com2 + 2 * (srcCurRow[x + 1] - srcCurRow[x - 1]));
|
||||
gy = abs(com1 - com2 + 2 * (srcNextRow[x] - srcPrevRow[x]));
|
||||
break;
|
||||
case EdgeDrawing::SCHARR:
|
||||
gx = abs(3 * (com1 + com2) + 10 * (srcCurRow[x + 1] - srcCurRow[x - 1]));
|
||||
gy = abs(3 * (com1 - com2) + 10 * (srcNextRow[x] - srcPrevRow[x]));
|
||||
break;
|
||||
case EdgeDrawing::LSD:
|
||||
// com1 and com2 differs from previous operators, because LSD has 2x2 kernel
|
||||
com1 = srcNextRow[x + 1] - srcCurRow[x];
|
||||
com2 = srcCurRow[x + 1] - srcNextRow[x];
|
||||
|
||||
gx = abs(com1 + com2);
|
||||
gy = abs(com1 - com2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (SumFlag)
|
||||
sum = gx + gy;
|
||||
else
|
||||
sum = (int)sqrt((double)gx * gx + gy * gy);
|
||||
|
||||
gradRow[x] = (ushort)sum;
|
||||
|
||||
if (PFmode)
|
||||
grads[sum]++;
|
||||
|
||||
if (sum >= gradThresh)
|
||||
{
|
||||
if (gx >= gy)
|
||||
dirRow[x] = EDGE_VERTICAL;
|
||||
else
|
||||
dirRow[x] = EDGE_HORIZONTAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EdgeDrawingImpl : public EdgeDrawing
|
||||
{
|
||||
public:
|
||||
@@ -23,6 +103,7 @@ public:
|
||||
};
|
||||
|
||||
EdgeDrawingImpl();
|
||||
~EdgeDrawingImpl();
|
||||
void detectEdges(InputArray src) CV_OVERRIDE;
|
||||
void getEdgeImage(OutputArray dst) CV_OVERRIDE;
|
||||
void getGradientImage(OutputArray dst) CV_OVERRIDE;
|
||||
@@ -47,6 +128,7 @@ protected:
|
||||
|
||||
double divForTestSegment;
|
||||
double* dH;
|
||||
int* grads;
|
||||
int np;
|
||||
|
||||
private:
|
||||
@@ -64,9 +146,9 @@ private:
|
||||
|
||||
Mat edgeImage;
|
||||
Mat gradImage;
|
||||
|
||||
Mat dirImage;
|
||||
uchar *dirImg; // pointer to direction image data
|
||||
short *gradImg; // pointer to gradient image data
|
||||
ushort *gradImg; // pointer to gradient image data
|
||||
|
||||
int op; // edge detection operator
|
||||
int gradThresh; // gradient threshold
|
||||
@@ -251,6 +333,16 @@ void EdgeDrawingImpl::write(cv::FileStorage& fs) const
|
||||
EdgeDrawingImpl::EdgeDrawingImpl()
|
||||
{
|
||||
params = EdgeDrawing::Params();
|
||||
nfa = new NFALUT(1, 1/2, 1, 1);
|
||||
dH = new double[MAX_GRAD_VALUE];
|
||||
grads = new int[MAX_GRAD_VALUE];
|
||||
}
|
||||
|
||||
EdgeDrawingImpl::~EdgeDrawingImpl()
|
||||
{
|
||||
delete nfa;
|
||||
delete[] dH;
|
||||
delete[] grads;
|
||||
}
|
||||
|
||||
void EdgeDrawingImpl::detectEdges(InputArray src)
|
||||
@@ -259,13 +351,6 @@ void EdgeDrawingImpl::detectEdges(InputArray src)
|
||||
anchorThresh = params.AnchorThresholdValue;
|
||||
op = params.EdgeDetectionOperator;
|
||||
|
||||
if (params.PFmode)
|
||||
{
|
||||
op = PREWITT;
|
||||
gradThresh = 11;
|
||||
anchorThresh = 3;
|
||||
}
|
||||
|
||||
// Check parameters for sanity
|
||||
if (op < 0 || op > 3)
|
||||
op = 0;
|
||||
@@ -289,7 +374,8 @@ void EdgeDrawingImpl::detectEdges(InputArray src)
|
||||
width = srcImage.cols;
|
||||
|
||||
edgeImage = Mat(height, width, CV_8UC1, Scalar(0)); // initialize edge Image
|
||||
gradImage = Mat(height, width, CV_16SC1); // gradImage contains short values
|
||||
gradImage = Mat(height, width, CV_16UC1); // gradImage contains short values
|
||||
dirImage = Mat(height, width, CV_8UC1);
|
||||
|
||||
if (params.Sigma < 1.0)
|
||||
smoothImage = srcImage;
|
||||
@@ -300,11 +386,15 @@ void EdgeDrawingImpl::detectEdges(InputArray src)
|
||||
|
||||
// Assign Pointers from Mat's data
|
||||
smoothImg = smoothImage.data;
|
||||
gradImg = (short*)gradImage.data;
|
||||
gradImg = (ushort*)gradImage.data;
|
||||
edgeImg = edgeImage.data;
|
||||
dirImg = dirImage.data;
|
||||
|
||||
Mat _dirImg = Mat(height, width, CV_8UC1);
|
||||
dirImg = _dirImg.data;
|
||||
if (params.PFmode)
|
||||
{
|
||||
memset(dH, 0, sizeof(double) * MAX_GRAD_VALUE);
|
||||
memset(grads, 0, sizeof(int) * MAX_GRAD_VALUE);
|
||||
}
|
||||
|
||||
ComputeGradient(); // COMPUTE GRADIENT & EDGE DIRECTION MAPS
|
||||
ComputeAnchorPoints(); // COMPUTE ANCHORS
|
||||
@@ -312,6 +402,15 @@ void EdgeDrawingImpl::detectEdges(InputArray src)
|
||||
|
||||
if (params.PFmode)
|
||||
{
|
||||
// Compute probability function H
|
||||
int size = (width - 2) * (height - 2);
|
||||
|
||||
for (int i = MAX_GRAD_VALUE - 1; i > 0; i--)
|
||||
grads[i - 1] += grads[i];
|
||||
|
||||
for (int i = 0; i < MAX_GRAD_VALUE; i++)
|
||||
dH[i] = (double)grads[i] / ((double)size);
|
||||
|
||||
divForTestSegment = 2.25; // Some magic number :-)
|
||||
memset(edgeImg, 0, width * height); // clear edge image
|
||||
np = 0;
|
||||
@@ -335,14 +434,12 @@ void EdgeDrawingImpl::getEdgeImage(OutputArray _dst)
|
||||
edgeImage.copyTo(_dst);
|
||||
}
|
||||
|
||||
|
||||
void EdgeDrawingImpl::getGradientImage(OutputArray _dst)
|
||||
{
|
||||
if (!gradImage.empty())
|
||||
convertScaleAbs(gradImage, _dst);
|
||||
gradImage.copyTo(_dst);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::vector<Point> > EdgeDrawingImpl::getSegments()
|
||||
{
|
||||
return segmentPoints;
|
||||
@@ -350,90 +447,27 @@ std::vector<std::vector<Point> > EdgeDrawingImpl::getSegments()
|
||||
|
||||
void EdgeDrawingImpl::ComputeGradient()
|
||||
{
|
||||
#define MAX_GRAD_VALUE 128*256
|
||||
dH = new double[MAX_GRAD_VALUE];
|
||||
memset(dH, 0, sizeof(double) * MAX_GRAD_VALUE);
|
||||
|
||||
int* grads = new int[MAX_GRAD_VALUE];
|
||||
memset(grads, 0, sizeof(int) * MAX_GRAD_VALUE);
|
||||
|
||||
// Initialize gradient image for row = 0, row = height-1, column=0, column=width-1
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
gradImg[j] = gradImg[(height - 1) * width + j] = (short)gradThresh - 1;
|
||||
gradImg[j] = gradImg[(height - 1) * width + j] = (ushort)gradThresh - 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < height - 1; i++)
|
||||
{
|
||||
gradImg[i * width] = gradImg[(i + 1) * width - 1] = (short)gradThresh - 1;
|
||||
gradImg[i * width] = gradImg[(i + 1) * width - 1] = (ushort)gradThresh - 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < height - 1; i++)
|
||||
{
|
||||
for (int j = 1; j < width - 1; j++)
|
||||
{
|
||||
int com1 = smoothImg[(i + 1) * width + j + 1] - smoothImg[(i - 1) * width + j - 1];
|
||||
int com2 = smoothImg[(i - 1) * width + j + 1] - smoothImg[(i + 1) * width + j - 1];
|
||||
ComputeGradientBody body;
|
||||
body.src = smoothImage;
|
||||
body.gradImage = gradImage;
|
||||
body.dirImage = dirImage;
|
||||
body.gradThresh = gradThresh;
|
||||
body.SumFlag = params.SumFlag;
|
||||
body.op = op;
|
||||
body.grads = grads;
|
||||
body.PFmode = params.PFmode;
|
||||
|
||||
int gx(0);
|
||||
int gy(0);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case PREWITT:
|
||||
gx = abs(com1 + com2 + (smoothImg[i * width + j + 1] - smoothImg[i * width + j - 1]));
|
||||
gy = abs(com1 - com2 + (smoothImg[(i + 1) * width + j] - smoothImg[(i - 1) * width + j]));
|
||||
break;
|
||||
case SOBEL:
|
||||
gx = abs(com1 + com2 + 2 * (smoothImg[i * width + j + 1] - smoothImg[i * width + j - 1]));
|
||||
gy = abs(com1 - com2 + 2 * (smoothImg[(i + 1) * width + j] - smoothImg[(i - 1) * width + j]));
|
||||
break;
|
||||
case SCHARR:
|
||||
gx = abs(3 * (com1 + com2) + 10 * (smoothImg[i * width + j + 1] - smoothImg[i * width + j - 1]));
|
||||
gy = abs(3 * (com1 - com2) + 10 * (smoothImg[(i + 1) * width + j] - smoothImg[(i - 1) * width + j]));
|
||||
break;
|
||||
case LSD:
|
||||
// com1 and com2 differs from previous operators, because LSD has 2x2 kernel
|
||||
com1 = smoothImg[(i + 1) * width + j + 1] - smoothImg[i * width + j];
|
||||
com2 = smoothImg[i * width + j + 1] - smoothImg[(i + 1) * width + j];
|
||||
|
||||
gx = abs(com1 + com2);
|
||||
gy = abs(com1 - com2);
|
||||
break;
|
||||
}
|
||||
|
||||
int sum;
|
||||
|
||||
if (params.SumFlag)
|
||||
sum = gx + gy;
|
||||
else
|
||||
sum = (int)sqrt((double)gx * gx + gy * gy);
|
||||
|
||||
int index = i * width + j;
|
||||
gradImg[index] = (short)sum;
|
||||
|
||||
grads[(int)sum]++;
|
||||
|
||||
if (sum >= gradThresh)
|
||||
{
|
||||
if (gx >= gy)
|
||||
dirImg[index] = EDGE_VERTICAL;
|
||||
else
|
||||
dirImg[index] = EDGE_HORIZONTAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute probability function H
|
||||
int size = (width - 2) * (height - 2);
|
||||
|
||||
for (int i = MAX_GRAD_VALUE - 1; i > 0; i--)
|
||||
grads[i - 1] += grads[i];
|
||||
|
||||
for (int i = 0; i < MAX_GRAD_VALUE; i++)
|
||||
dH[i] = (double)grads[i] / ((double)size);
|
||||
|
||||
#undef MAX_GRAD_VALUE
|
||||
parallel_for_(Range(1, smoothImage.rows - 1), body);
|
||||
}
|
||||
|
||||
void EdgeDrawingImpl::ComputeAnchorPoints()
|
||||
@@ -526,7 +560,6 @@ void EdgeDrawingImpl::JoinAnchorPointsUsingSortedAnchors()
|
||||
stack[top].c = j;
|
||||
stack[top].dir = UP;
|
||||
stack[top].parent = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1273,12 +1306,12 @@ void EdgeDrawingImpl::detectLines(OutputArray _lines)
|
||||
|
||||
#define PRECISON_ANGLE 22.5
|
||||
precision = (PRECISON_ANGLE / 180) * CV_PI;
|
||||
double prob = 0.125;
|
||||
#undef PRECISON_ANGLE
|
||||
|
||||
if (params.NFAValidation)
|
||||
if (nfa->LUTSize == 1 && params.NFAValidation)
|
||||
{
|
||||
int lutSize = (width + height) / 8;
|
||||
double prob = 1.0 / 8; // probability of alignment
|
||||
nfa = new NFALUT(lutSize, prob, width, height);
|
||||
ValidateLineSegments();
|
||||
}
|
||||
@@ -2787,7 +2820,6 @@ void EdgeDrawingImpl::GenerateCandidateCircles()
|
||||
|
||||
void EdgeDrawingImpl::DetectArcs()
|
||||
{
|
||||
|
||||
double maxLineLengthThreshold = MAX(width, height) / 5;
|
||||
|
||||
double MIN_ANGLE = CV_PI / 30; // 6 degrees
|
||||
@@ -3155,8 +3187,6 @@ void EdgeDrawingImpl::DetectArcs()
|
||||
void EdgeDrawingImpl::ValidateCircles(bool validate)
|
||||
{
|
||||
precision = CV_PI / 16; // Alignment precision
|
||||
double prob = 1.0 / 8; // probability of alignment
|
||||
|
||||
double max = width;
|
||||
if (height > max)
|
||||
max = height;
|
||||
@@ -3167,8 +3197,12 @@ void EdgeDrawingImpl::ValidateCircles(bool validate)
|
||||
double* px = new double[8 * (width + height)];
|
||||
double* py = new double[8 * (width + height)];
|
||||
|
||||
int lutSize = (width + height) / 8;
|
||||
nfa = new NFALUT(lutSize, prob, width, height); // create look up table
|
||||
if (nfa->LUTSize == 1 && params.NFAValidation)
|
||||
{
|
||||
int lutSize = (width + height) / 8;
|
||||
double prob = 1.0 / 8; // probability of alignment
|
||||
nfa = new NFALUT(lutSize, prob, width, height); // create look up table
|
||||
}
|
||||
|
||||
// Validate circles & ellipses
|
||||
bool validateAgain;
|
||||
@@ -3412,7 +3446,6 @@ void EdgeDrawingImpl::ValidateCircles(bool validate)
|
||||
|
||||
delete[] px;
|
||||
delete[] py;
|
||||
delete nfa;
|
||||
}
|
||||
|
||||
void EdgeDrawingImpl::JoinCircles()
|
||||
|
@@ -37,6 +37,7 @@
|
||||
// Ellipse thresholds
|
||||
#define CANDIDATE_ELLIPSE_RATIO 0.50 // 50% -- If 50% of the ellipse is detected, it may be candidate for validation
|
||||
#define ELLIPSE_ERROR 1.50 // Used for ellipses. (used to be 1.65 for what reason?)
|
||||
#define MAX_GRAD_VALUE 128*256
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
@@ -64,7 +65,7 @@ private:
|
||||
|
||||
NFALUT::NFALUT(int size, double _prob, int _w, int _h)
|
||||
{
|
||||
LUTSize = size;
|
||||
LUTSize = size > 60 ? 60 : size;
|
||||
LUT = new int[LUTSize];
|
||||
w = _w;
|
||||
h = _h;
|
||||
|
Reference in New Issue
Block a user