1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge remote-tracking branch 'upstream/3.4' into merge-3.4

This commit is contained in:
Alexander Alekhin
2020-06-04 17:55:00 +00:00
35 changed files with 1061 additions and 236 deletions
+4 -1
View File
@@ -2458,7 +2458,10 @@ be floating-point (single or double precision).
@param points2 Array of the second image points of the same size and format as points1 .
@param cameraMatrix Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$ .
Note that this function assumes that points1 and points2 are feature points from cameras with the
same camera matrix.
same camera matrix. If this assumption does not hold for your use case, use
`undistortPoints()` with `P = cv::NoArray()` for both cameras to transform image points
to normalized image coordinates, which are valid for the identity camera matrix. When
passing these coordinates, pass the identity matrix for this parameter.
@param method Method for computing an essential matrix.
- **RANSAC** for the RANSAC algorithm.
- **LMEDS** for the LMedS algorithm.
+7 -2
View File
@@ -45,9 +45,14 @@
#ifndef OPENCV_CORE_EIGEN_HPP
#define OPENCV_CORE_EIGEN_HPP
#ifndef EIGEN_WORLD_VERSION
#error "Wrong usage of OpenCV's Eigen utility header. Include Eigen's headers first. See https://github.com/opencv/opencv/issues/17366"
#endif
#include "opencv2/core.hpp"
#if EIGEN_WORLD_VERSION == 3 && EIGEN_MAJOR_VERSION >= 3
#if EIGEN_WORLD_VERSION == 3 && EIGEN_MAJOR_VERSION >= 3 \
&& defined(CV_CXX11) && defined(CV_CXX_STD_ARRAY)
#include <unsupported/Eigen/CXX11/Tensor>
#define OPENCV_EIGEN_TENSOR_SUPPORT
#endif // EIGEN_WORLD_VERSION == 3 && EIGEN_MAJOR_VERSION >= 3
@@ -157,7 +162,7 @@ Eigen::TensorMap<Eigen::Tensor<float, 3, Eigen::RowMajor>> a_tensormap = cv2eige
\endcode
*/
template <typename _Tp> static inline
Eigen::TensorMap<Eigen::Tensor<_Tp, 3, Eigen::RowMajor>> cv2eigen_tensormap(const cv::InputArray &src)
Eigen::TensorMap<Eigen::Tensor<_Tp, 3, Eigen::RowMajor>> cv2eigen_tensormap(InputArray src)
{
Mat mat = src.getMat();
CV_CheckTypeEQ(mat.type(), CV_MAKETYPE(traits::Type<_Tp>::value, mat.channels()), "");
@@ -436,12 +436,20 @@ public:
*/
CV_WRAP void writeComment(const String& comment, bool append = false);
void startWriteStruct(const String& name, int flags, const String& typeName);
void endWriteStruct();
/** @brief Starts to write a nested structure (sequence or a mapping).
@param name name of the structure (if it's a member of parent mapping, otherwise it should be empty
@param flags type of the structure (FileNode::MAP or FileNode::SEQ (both with optional FileNode::FLOW)).
@param typeName usually an empty string
*/
CV_WRAP void startWriteStruct(const String& name, int flags, const String& typeName=String());
/** @brief Finishes writing nested structure (should pair startWriteStruct())
*/
CV_WRAP void endWriteStruct();
/** @brief Returns the normalized object name for the specified name of a file.
@param filename Name of a file
@returns The normalized object name.
@param filename Name of a file
@returns The normalized object name.
*/
static String getDefaultObjectName(const String& filename);
@@ -62,6 +62,12 @@ static bool ipp_countNonZero( Mat &src, int &res )
{
CV_INSTRUMENT_REGION_IPP();
#if defined __APPLE__ || (defined _MSC_VER && defined _M_IX86)
// see https://github.com/opencv/opencv/issues/17453
if (src.dims <= 2 && src.step > 520000)
return false;
#endif
#if IPP_VERSION_X100 < 201801
// Poor performance of SSE42
if(cv::ipp::getIppTopFeatures() == ippCPUID_SSE42)
+19
View File
@@ -276,4 +276,23 @@ INSTANTIATE_TEST_CASE_P(Core, CountNonZeroND,
)
);
typedef testing::TestWithParam<tuple<int, cv::Size> > CountNonZeroBig;
TEST_P(CountNonZeroBig, /**/)
{
const int type = get<0>(GetParam());
const Size sz = get<1>(GetParam());
EXPECT_EQ(0, cv::countNonZero(cv::Mat::zeros(sz, type)));
EXPECT_EQ(sz.area(), cv::countNonZero(cv::Mat::ones(sz, type)));
}
INSTANTIATE_TEST_CASE_P(Core, CountNonZeroBig,
testing::Combine(
testing::Values(CV_8UC1, CV_32FC1),
testing::Values(Size(1, 524190), Size(524190, 1), Size(3840, 2160))
)
);
}} // namespace
+7
View File
@@ -658,6 +658,8 @@ namespace cv {
if (pad)
padding = kernel_size / 2;
// Cannot divide 0
CV_Assert(stride > 0);
CV_Assert(kernel_size > 0 && filters > 0);
CV_Assert(tensor_shape[0] > 0);
CV_Assert(tensor_shape[0] % groups == 0);
@@ -690,6 +692,9 @@ namespace cv {
int kernel_size = getParam<int>(layer_params, "size", 2);
int stride = getParam<int>(layer_params, "stride", 2);
int padding = getParam<int>(layer_params, "padding", kernel_size - 1);
// Cannot divide 0
CV_Assert(stride > 0);
setParams.setMaxpool(kernel_size, padding, stride);
tensor_shape[1] = (tensor_shape[1] - kernel_size + padding) / stride + 1;
@@ -732,6 +737,8 @@ namespace cv {
else if (layer_type == "reorg")
{
int stride = getParam<int>(layer_params, "stride", 2);
// Cannot divide 0
CV_Assert(stride > 0);
tensor_shape[0] = tensor_shape[0] * (stride * stride);
tensor_shape[1] = tensor_shape[1] / stride;
tensor_shape[2] = tensor_shape[2] / stride;
+59 -22
View File
@@ -3508,6 +3508,7 @@ Net Net::Impl::createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork& ieNe
for (auto& it : ieNet.getOutputsInfo())
{
CV_TRACE_REGION("output");
const auto& outputName = it.first;
LayerParams lp;
int lid = cvNet.addLayer(it.first, "", lp);
@@ -3517,37 +3518,60 @@ Net Net::Impl::createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork& ieNe
#ifdef HAVE_DNN_NGRAPH
if (DNN_BACKEND_INFERENCE_ENGINE_NGRAPH == getInferenceEngineBackendTypeParam())
{
const auto& outputName = it.first;
Ptr<Layer> cvLayer(new NgraphBackendLayer(ieNet));
cvLayer->name = outputName;
cvLayer->type = "_unknown_";
if (ngraphFunction)
auto process_layer = [&](const std::string& name) -> bool
{
CV_TRACE_REGION("ngraph_function");
bool found = false;
for (const auto& op : ngraphOperations)
if (ngraphFunction)
{
CV_Assert(op);
if (op->get_friendly_name() == outputName)
CV_TRACE_REGION("ngraph_function");
for (const auto& op : ngraphOperations)
{
const std::string typeName = op->get_type_info().name;
cvLayer->type = typeName;
found = true;
break;
CV_Assert(op);
if (op->get_friendly_name() == name)
{
const std::string typeName = op->get_type_info().name;
cvLayer->type = typeName;
return true;
}
}
return false;
}
else
{
CV_TRACE_REGION("legacy_cnn_layer");
try
{
InferenceEngine::CNNLayerPtr ieLayer = ieNet.getLayerByName(name.c_str());
CV_Assert(ieLayer);
cvLayer->type = ieLayer->type;
return true;
}
catch (const std::exception& e)
{
CV_UNUSED(e);
CV_LOG_DEBUG(NULL, "IE layer extraction failure: '" << name << "' - " << e.what());
return false;
}
}
if (!found)
CV_LOG_WARNING(NULL, "DNN/IE: Can't determine output layer type: '" << outputName << "'");
}
else
{
CV_TRACE_REGION("legacy_cnn_layer");
InferenceEngine::CNNLayerPtr ieLayer = ieNet.getLayerByName(it.first.c_str());
CV_Assert(ieLayer);
};
cvLayer->type = ieLayer->type;
bool found = process_layer(outputName);
if (!found)
{
auto pos = outputName.rfind('.'); // cut port number: ".0"
if (pos != std::string::npos)
{
std::string layerName = outputName.substr(0, pos);
found = process_layer(layerName);
}
}
if (!found)
CV_LOG_WARNING(NULL, "DNN/IE: Can't determine output layer type: '" << outputName << "'");
ld.layerInstance = cvLayer;
ld.backendNodes[DNN_BACKEND_INFERENCE_ENGINE_NGRAPH] = backendNode;
}
@@ -3557,10 +3581,23 @@ Net Net::Impl::createNetworkFromModelOptimizer(InferenceEngine::CNNNetwork& ieNe
#ifdef HAVE_DNN_IE_NN_BUILDER_2019
Ptr<Layer> cvLayer(new InfEngineBackendLayer(ieNet));
InferenceEngine::CNNLayerPtr ieLayer = ieNet.getLayerByName(it.first.c_str());
InferenceEngine::CNNLayerPtr ieLayer;
try
{
ieLayer = ieNet.getLayerByName(outputName.c_str());
}
catch (...)
{
auto pos = outputName.rfind('.'); // cut port number: ".0"
if (pos != std::string::npos)
{
std::string layerName = outputName.substr(0, pos);
ieLayer = ieNet.getLayerByName(layerName.c_str());
}
}
CV_Assert(ieLayer);
cvLayer->name = it.first;
cvLayer->name = outputName;
cvLayer->type = ieLayer->type;
ld.layerInstance = cvLayer;
+4
View File
@@ -806,6 +806,10 @@ void ONNXImporter::populateNet(Net dstNet)
{
layerParams.type = "ELU";
}
else if (layer_type == "Tanh")
{
layerParams.type = "TanH";
}
else if (layer_type == "PRelu")
{
layerParams.type = "PReLU";
+1 -1
View File
@@ -1220,7 +1220,7 @@ TEST_P(Test_TensorFlow_nets, EfficientDet)
}
checkBackend();
std::string proto = findDataFile("dnn/efficientdet-d0.pbtxt");
std::string model = findDataFile("dnn/efficientdet-d0.pb");
std::string model = findDataFile("dnn/efficientdet-d0.pb", false);
Net net = readNetFromTensorflow(model, proto);
Mat img = imread(findDataFile("dnn/dog416.png"));
@@ -12,6 +12,7 @@ import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.DMatch;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.BFMatcher;
import org.opencv.core.KeyPoint;
import org.opencv.test.OpenCVTestCase;
import org.opencv.test.OpenCVTestRunner;
@@ -93,6 +94,15 @@ public class BruteForceDescriptorMatcherTest extends OpenCVTestCase {
};
}
// https://github.com/opencv/opencv/issues/11268
public void testConstructor()
{
BFMatcher self_created_matcher = new BFMatcher();
Mat train = new Mat(1, 1, CvType.CV_8U, new Scalar(123));
self_created_matcher.add(Arrays.asList(train));
assertTrue(!self_created_matcher.empty());
}
public void testAdd() {
matcher.add(Arrays.asList(new Mat()));
assertFalse(matcher.empty());
@@ -12,6 +12,7 @@ import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.DMatch;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.FlannBasedMatcher;
import org.opencv.core.KeyPoint;
import org.opencv.test.OpenCVTestCase;
import org.opencv.test.OpenCVTestRunner;
@@ -168,6 +169,15 @@ public class FlannBasedDescriptorMatcherTest extends OpenCVTestCase {
};
}
// https://github.com/opencv/opencv/issues/11268
public void testConstructor()
{
FlannBasedMatcher self_created_matcher = new FlannBasedMatcher();
Mat train = new Mat(1, 1, CvType.CV_8U, new Scalar(123));
self_created_matcher.add(Arrays.asList(train));
assertTrue(!self_created_matcher.empty());
}
public void testAdd() {
matcher.add(Arrays.asList(new Mat()));
assertFalse(matcher.empty());
@@ -797,9 +797,13 @@ public class ImgprocTest extends OpenCVTestCase {
rrect = Imgproc.fitEllipse(points);
assertPointEquals(new Point(0, 0), rrect.center, EPS);
assertEquals(2.828, rrect.size.width, EPS);
assertEquals(2.828, rrect.size.height, EPS);
double FIT_ELLIPSE_CENTER_EPS = 0.01;
double FIT_ELLIPSE_SIZE_EPS = 0.4;
assertEquals(0.0, rrect.center.x, FIT_ELLIPSE_CENTER_EPS);
assertEquals(0.0, rrect.center.y, FIT_ELLIPSE_CENTER_EPS);
assertEquals(2.828, rrect.size.width, FIT_ELLIPSE_SIZE_EPS);
assertEquals(2.828, rrect.size.height, FIT_ELLIPSE_SIZE_EPS);
}
public void testFitLine() {
+173 -83
View File
@@ -337,8 +337,15 @@ double cv::contourArea( InputArray _contour, bool oriented )
return a00;
}
namespace cv
{
cv::RotatedRect cv::fitEllipse( InputArray _points )
static inline Point2f getOfs(int i, float eps)
{
return Point2f(((i & 1)*2 - 1)*eps, ((i & 2) - 1)*eps);
}
static RotatedRect fitEllipseNoDirect( InputArray _points )
{
CV_INSTRUMENT_REGION();
@@ -354,42 +361,84 @@ cv::RotatedRect cv::fitEllipse( InputArray _points )
// New fitellipse algorithm, contributed by Dr. Daniel Weiss
Point2f c(0,0);
double gfp[5] = {0}, rp[5] = {0}, t;
double gfp[5] = {0}, rp[5] = {0}, t, vd[25]={0}, wd[5]={0};
const double min_eps = 1e-8;
bool is_float = depth == CV_32F;
const Point* ptsi = points.ptr<Point>();
const Point2f* ptsf = points.ptr<Point2f>();
AutoBuffer<double> _Ad(n*5), _bd(n);
double *Ad = _Ad.data(), *bd = _bd.data();
AutoBuffer<double> _Ad(n*12+n);
double *Ad = _Ad.data(), *ud = Ad + n*5, *bd = ud + n*5;
Point2f* ptsf_copy = (Point2f*)(bd + n);
// first fit for parameters A - E
Mat A( n, 5, CV_64F, Ad );
Mat b( n, 1, CV_64F, bd );
Mat x( 5, 1, CV_64F, gfp );
Mat u( n, 1, CV_64F, ud );
Mat vt( 5, 5, CV_64F, vd );
Mat w( 5, 1, CV_64F, wd );
{
const Point* ptsi = points.ptr<Point>();
const Point2f* ptsf = points.ptr<Point2f>();
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
ptsf_copy[i] = p;
c += p;
}
}
c.x /= n;
c.y /= n;
double s = 0;
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
Point2f p = ptsf_copy[i];
p -= c;
s += fabs(p.x) + fabs(p.y);
}
double scale = 100./(s > FLT_EPSILON ? s : FLT_EPSILON);
for( i = 0; i < n; i++ )
{
Point2f p = ptsf_copy[i];
p -= c;
double px = p.x*scale;
double py = p.y*scale;
bd[i] = 10000.0; // 1.0?
Ad[i*5] = -(double)p.x * p.x; // A - C signs inverted as proposed by APP
Ad[i*5 + 1] = -(double)p.y * p.y;
Ad[i*5 + 2] = -(double)p.x * p.y;
Ad[i*5 + 3] = p.x;
Ad[i*5 + 4] = p.y;
Ad[i*5] = -px * px; // A - C signs inverted as proposed by APP
Ad[i*5 + 1] = -py * py;
Ad[i*5 + 2] = -px * py;
Ad[i*5 + 3] = px;
Ad[i*5 + 4] = py;
}
solve(A, b, x, DECOMP_SVD);
SVDecomp(A, w, u, vt);
if(wd[0]*FLT_EPSILON > wd[4]) {
float eps = (float)(s/(n*2)*1e-3);
for( i = 0; i < n; i++ )
{
Point2f p = ptsf_copy[i] + getOfs(i, eps);
ptsf_copy[i] = p;
}
for( i = 0; i < n; i++ )
{
Point2f p = ptsf_copy[i];
p -= c;
double px = p.x*scale;
double py = p.y*scale;
bd[i] = 10000.0; // 1.0?
Ad[i*5] = -px * px; // A - C signs inverted as proposed by APP
Ad[i*5 + 1] = -py * py;
Ad[i*5 + 2] = -px * py;
Ad[i*5 + 3] = px;
Ad[i*5 + 4] = py;
}
SVDecomp(A, w, u, vt);
}
SVBackSubst(w, u, vt, b, x);
// now use general-form parameters A - E to find the ellipse center:
// differentiate general form wrt x/y to get two equations for cx and cy
@@ -409,12 +458,14 @@ cv::RotatedRect cv::fitEllipse( InputArray _points )
x = Mat( 3, 1, CV_64F, gfp );
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
Point2f p = ptsf_copy[i];
p -= c;
double px = p.x*scale;
double py = p.y*scale;
bd[i] = 1.0;
Ad[i * 3] = (p.x - rp[0]) * (p.x - rp[0]);
Ad[i * 3 + 1] = (p.y - rp[1]) * (p.y - rp[1]);
Ad[i * 3 + 2] = (p.x - rp[0]) * (p.y - rp[1]);
Ad[i * 3] = (px - rp[0]) * (px - rp[0]);
Ad[i * 3 + 1] = (py - rp[1]) * (py - rp[1]);
Ad[i * 3 + 2] = (px - rp[0]) * (py - rp[1]);
}
solve(A, b, x, DECOMP_SVD);
@@ -431,10 +482,10 @@ cv::RotatedRect cv::fitEllipse( InputArray _points )
if( rp[3] > min_eps )
rp[3] = std::sqrt(2.0 / rp[3]);
box.center.x = (float)rp[0] + c.x;
box.center.y = (float)rp[1] + c.y;
box.size.width = (float)(rp[2]*2);
box.size.height = (float)(rp[3]*2);
box.center.x = (float)(rp[0]/scale) + c.x;
box.center.y = (float)(rp[1]/scale) + c.y;
box.size.width = (float)(rp[2]*2/scale);
box.size.height = (float)(rp[3]*2/scale);
if( box.size.width > box.size.height )
{
float tmp;
@@ -448,6 +499,16 @@ cv::RotatedRect cv::fitEllipse( InputArray _points )
return box;
}
}
cv::RotatedRect cv::fitEllipse( InputArray _points )
{
CV_INSTRUMENT_REGION();
Mat points = _points.getMat();
int n = points.checkVector(2);
return n == 5 ? fitEllipseDirect(points) : fitEllipseNoDirect(points);
}
cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
{
@@ -483,16 +544,24 @@ cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
c.x /= (float)n;
c.y /= (float)n;
double s = 0;
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
p -= c;
s += fabs(p.x - c.x) + fabs(p.y - c.y);
}
double scale = 100./(s > FLT_EPSILON ? s : (double)FLT_EPSILON);
A.at<double>(i,0) = (double)(p.x)*(p.x);
A.at<double>(i,1) = (double)(p.x)*(p.y);
A.at<double>(i,2) = (double)(p.y)*(p.y);
A.at<double>(i,3) = (double)p.x;
A.at<double>(i,4) = (double)p.y;
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
double px = (p.x - c.x)*scale, py = (p.y - c.y)*scale;
A.at<double>(i,0) = px*px;
A.at<double>(i,1) = px*py;
A.at<double>(i,2) = py*py;
A.at<double>(i,3) = px;
A.at<double>(i,4) = py;
A.at<double>(i,5) = 1.0;
}
cv::mulTransposed( A, DM, true, noArray(), 1.0, -1 );
@@ -587,10 +656,10 @@ cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
double p1 = 2.0*pVec(2) *pVec(3) - pVec(1) *pVec(4) ;
double p2 = 2.0*pVec(0) *pVec(4) -(pVec(1) *pVec(3) );
x0 = p1/l3 + c.x;
y0 = p2/l3 + c.y;
a = std::sqrt(2.)*sqrt((u1 - 4.0*u2)/((l1 - l2)*l3));
b = std::sqrt(2.)*sqrt(-1.0*((u1 - 4.0*u2)/((l1 + l2)*l3)));
x0 = p1/l3/scale + c.x;
y0 = p2/l3/scale + c.y;
a = std::sqrt(2.)*sqrt((u1 - 4.0*u2)/((l1 - l2)*l3))/scale;
b = std::sqrt(2.)*sqrt(-1.0*((u1 - 4.0*u2)/((l1 + l2)*l3)))/scale;
if (pVec(1) == 0) {
if (pVec(0) < pVec(2) ) {
theta = 0;
@@ -601,8 +670,8 @@ cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
theta = CV_PI/2. + 0.5*std::atan2(pVec(1) , (pVec(0) - pVec(2) ));
}
box.center.x = (float)x0; // +c.x;
box.center.y = (float)y0; // +c.y;
box.center.x = (float)x0;
box.center.y = (float)y0;
box.size.width = (float)(2.0*a);
box.size.height = (float)(2.0*b);
if( box.size.width > box.size.height )
@@ -619,7 +688,7 @@ cv::RotatedRect cv::fitEllipseAMS( InputArray _points )
box = cv::fitEllipseDirect( points );
}
} else {
box = cv::fitEllipse( points );
box = cv::fitEllipseNoDirect( points );
}
return box;
@@ -630,6 +699,7 @@ cv::RotatedRect cv::fitEllipseDirect( InputArray _points )
Mat points = _points.getMat();
int i, n = points.checkVector(2);
int depth = points.depth();
float eps = 0;
CV_Assert( n >= 0 && (depth == CV_32F || depth == CV_32S));
RotatedRect box;
@@ -637,7 +707,7 @@ cv::RotatedRect cv::fitEllipseDirect( InputArray _points )
if( n < 5 )
CV_Error( CV_StsBadSize, "There should be at least 5 points to fit the ellipse" );
Point2f c(0,0);
Point2d c(0., 0.);
bool is_float = (depth == CV_32F);
const Point* ptsi = points.ptr<Point>();
@@ -649,63 +719,83 @@ cv::RotatedRect cv::fitEllipseDirect( InputArray _points )
Matx<double, 3, 1> pVec;
double x0, y0, a, b, theta, Ts;
double s = 0;
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
c += p;
c.x += p.x;
c.y += p.y;
}
c.x /= (float)n;
c.y /= (float)n;
c.x /= n;
c.y /= n;
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
p -= c;
A.at<double>(i,0) = (double)(p.x)*(p.x);
A.at<double>(i,1) = (double)(p.x)*(p.y);
A.at<double>(i,2) = (double)(p.y)*(p.y);
A.at<double>(i,3) = (double)p.x;
A.at<double>(i,4) = (double)p.y;
A.at<double>(i,5) = 1.0;
s += fabs(p.x - c.x) + fabs(p.y - c.y);
}
cv::mulTransposed( A, DM, true, noArray(), 1.0, -1 );
DM *= (1.0/n);
double scale = 100./(s > FLT_EPSILON ? s : (double)FLT_EPSILON);
TM(0,0) = DM(0,5)*DM(3,5)*DM(4,4) - DM(0,5)*DM(3,4)*DM(4,5) - DM(0,4)*DM(3,5)*DM(5,4) + \
DM(0,3)*DM(4,5)*DM(5,4) + DM(0,4)*DM(3,4)*DM(5,5) - DM(0,3)*DM(4,4)*DM(5,5);
TM(0,1) = DM(1,5)*DM(3,5)*DM(4,4) - DM(1,5)*DM(3,4)*DM(4,5) - DM(1,4)*DM(3,5)*DM(5,4) + \
DM(1,3)*DM(4,5)*DM(5,4) + DM(1,4)*DM(3,4)*DM(5,5) - DM(1,3)*DM(4,4)*DM(5,5);
TM(0,2) = DM(2,5)*DM(3,5)*DM(4,4) - DM(2,5)*DM(3,4)*DM(4,5) - DM(2,4)*DM(3,5)*DM(5,4) + \
DM(2,3)*DM(4,5)*DM(5,4) + DM(2,4)*DM(3,4)*DM(5,5) - DM(2,3)*DM(4,4)*DM(5,5);
TM(1,0) = DM(0,5)*DM(3,3)*DM(4,5) - DM(0,5)*DM(3,5)*DM(4,3) + DM(0,4)*DM(3,5)*DM(5,3) - \
DM(0,3)*DM(4,5)*DM(5,3) - DM(0,4)*DM(3,3)*DM(5,5) + DM(0,3)*DM(4,3)*DM(5,5);
TM(1,1) = DM(1,5)*DM(3,3)*DM(4,5) - DM(1,5)*DM(3,5)*DM(4,3) + DM(1,4)*DM(3,5)*DM(5,3) - \
DM(1,3)*DM(4,5)*DM(5,3) - DM(1,4)*DM(3,3)*DM(5,5) + DM(1,3)*DM(4,3)*DM(5,5);
TM(1,2) = DM(2,5)*DM(3,3)*DM(4,5) - DM(2,5)*DM(3,5)*DM(4,3) + DM(2,4)*DM(3,5)*DM(5,3) - \
DM(2,3)*DM(4,5)*DM(5,3) - DM(2,4)*DM(3,3)*DM(5,5) + DM(2,3)*DM(4,3)*DM(5,5);
TM(2,0) = DM(0,5)*DM(3,4)*DM(4,3) - DM(0,5)*DM(3,3)*DM(4,4) - DM(0,4)*DM(3,4)*DM(5,3) + \
DM(0,3)*DM(4,4)*DM(5,3) + DM(0,4)*DM(3,3)*DM(5,4) - DM(0,3)*DM(4,3)*DM(5,4);
TM(2,1) = DM(1,5)*DM(3,4)*DM(4,3) - DM(1,5)*DM(3,3)*DM(4,4) - DM(1,4)*DM(3,4)*DM(5,3) + \
DM(1,3)*DM(4,4)*DM(5,3) + DM(1,4)*DM(3,3)*DM(5,4) - DM(1,3)*DM(4,3)*DM(5,4);
TM(2,2) = DM(2,5)*DM(3,4)*DM(4,3) - DM(2,5)*DM(3,3)*DM(4,4) - DM(2,4)*DM(3,4)*DM(5,3) + \
DM(2,3)*DM(4,4)*DM(5,3) + DM(2,4)*DM(3,3)*DM(5,4) - DM(2,3)*DM(4,3)*DM(5,4);
// first, try the original pointset.
// if it's singular, try to shift the points a bit
int iter = 0;
for( iter = 0; iter < 2; iter++ ) {
for( i = 0; i < n; i++ )
{
Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
Point2f delta = getOfs(i, eps);
double px = (p.x + delta.x - c.x)*scale, py = (p.y + delta.y - c.y)*scale;
Ts=(-(DM(3,5)*DM(4,4)*DM(5,3)) + DM(3,4)*DM(4,5)*DM(5,3) + DM(3,5)*DM(4,3)*DM(5,4) - \
DM(3,3)*DM(4,5)*DM(5,4) - DM(3,4)*DM(4,3)*DM(5,5) + DM(3,3)*DM(4,4)*DM(5,5));
A.at<double>(i,0) = px*px;
A.at<double>(i,1) = px*py;
A.at<double>(i,2) = py*py;
A.at<double>(i,3) = px;
A.at<double>(i,4) = py;
A.at<double>(i,5) = 1.0;
}
cv::mulTransposed( A, DM, true, noArray(), 1.0, -1 );
DM *= (1.0/n);
M(0,0) = (DM(2,0) + (DM(2,3)*TM(0,0) + DM(2,4)*TM(1,0) + DM(2,5)*TM(2,0))/Ts)/2.;
M(0,1) = (DM(2,1) + (DM(2,3)*TM(0,1) + DM(2,4)*TM(1,1) + DM(2,5)*TM(2,1))/Ts)/2.;
M(0,2) = (DM(2,2) + (DM(2,3)*TM(0,2) + DM(2,4)*TM(1,2) + DM(2,5)*TM(2,2))/Ts)/2.;
M(1,0) = -DM(1,0) - (DM(1,3)*TM(0,0) + DM(1,4)*TM(1,0) + DM(1,5)*TM(2,0))/Ts;
M(1,1) = -DM(1,1) - (DM(1,3)*TM(0,1) + DM(1,4)*TM(1,1) + DM(1,5)*TM(2,1))/Ts;
M(1,2) = -DM(1,2) - (DM(1,3)*TM(0,2) + DM(1,4)*TM(1,2) + DM(1,5)*TM(2,2))/Ts;
M(2,0) = (DM(0,0) + (DM(0,3)*TM(0,0) + DM(0,4)*TM(1,0) + DM(0,5)*TM(2,0))/Ts)/2.;
M(2,1) = (DM(0,1) + (DM(0,3)*TM(0,1) + DM(0,4)*TM(1,1) + DM(0,5)*TM(2,1))/Ts)/2.;
M(2,2) = (DM(0,2) + (DM(0,3)*TM(0,2) + DM(0,4)*TM(1,2) + DM(0,5)*TM(2,2))/Ts)/2.;
TM(0,0) = DM(0,5)*DM(3,5)*DM(4,4) - DM(0,5)*DM(3,4)*DM(4,5) - DM(0,4)*DM(3,5)*DM(5,4) + \
DM(0,3)*DM(4,5)*DM(5,4) + DM(0,4)*DM(3,4)*DM(5,5) - DM(0,3)*DM(4,4)*DM(5,5);
TM(0,1) = DM(1,5)*DM(3,5)*DM(4,4) - DM(1,5)*DM(3,4)*DM(4,5) - DM(1,4)*DM(3,5)*DM(5,4) + \
DM(1,3)*DM(4,5)*DM(5,4) + DM(1,4)*DM(3,4)*DM(5,5) - DM(1,3)*DM(4,4)*DM(5,5);
TM(0,2) = DM(2,5)*DM(3,5)*DM(4,4) - DM(2,5)*DM(3,4)*DM(4,5) - DM(2,4)*DM(3,5)*DM(5,4) + \
DM(2,3)*DM(4,5)*DM(5,4) + DM(2,4)*DM(3,4)*DM(5,5) - DM(2,3)*DM(4,4)*DM(5,5);
TM(1,0) = DM(0,5)*DM(3,3)*DM(4,5) - DM(0,5)*DM(3,5)*DM(4,3) + DM(0,4)*DM(3,5)*DM(5,3) - \
DM(0,3)*DM(4,5)*DM(5,3) - DM(0,4)*DM(3,3)*DM(5,5) + DM(0,3)*DM(4,3)*DM(5,5);
TM(1,1) = DM(1,5)*DM(3,3)*DM(4,5) - DM(1,5)*DM(3,5)*DM(4,3) + DM(1,4)*DM(3,5)*DM(5,3) - \
DM(1,3)*DM(4,5)*DM(5,3) - DM(1,4)*DM(3,3)*DM(5,5) + DM(1,3)*DM(4,3)*DM(5,5);
TM(1,2) = DM(2,5)*DM(3,3)*DM(4,5) - DM(2,5)*DM(3,5)*DM(4,3) + DM(2,4)*DM(3,5)*DM(5,3) - \
DM(2,3)*DM(4,5)*DM(5,3) - DM(2,4)*DM(3,3)*DM(5,5) + DM(2,3)*DM(4,3)*DM(5,5);
TM(2,0) = DM(0,5)*DM(3,4)*DM(4,3) - DM(0,5)*DM(3,3)*DM(4,4) - DM(0,4)*DM(3,4)*DM(5,3) + \
DM(0,3)*DM(4,4)*DM(5,3) + DM(0,4)*DM(3,3)*DM(5,4) - DM(0,3)*DM(4,3)*DM(5,4);
TM(2,1) = DM(1,5)*DM(3,4)*DM(4,3) - DM(1,5)*DM(3,3)*DM(4,4) - DM(1,4)*DM(3,4)*DM(5,3) + \
DM(1,3)*DM(4,4)*DM(5,3) + DM(1,4)*DM(3,3)*DM(5,4) - DM(1,3)*DM(4,3)*DM(5,4);
TM(2,2) = DM(2,5)*DM(3,4)*DM(4,3) - DM(2,5)*DM(3,3)*DM(4,4) - DM(2,4)*DM(3,4)*DM(5,3) + \
DM(2,3)*DM(4,4)*DM(5,3) + DM(2,4)*DM(3,3)*DM(5,4) - DM(2,3)*DM(4,3)*DM(5,4);
if (fabs(cv::determinant(M)) > 1.0e-10) {
Ts=(-(DM(3,5)*DM(4,4)*DM(5,3)) + DM(3,4)*DM(4,5)*DM(5,3) + DM(3,5)*DM(4,3)*DM(5,4) - \
DM(3,3)*DM(4,5)*DM(5,4) - DM(3,4)*DM(4,3)*DM(5,5) + DM(3,3)*DM(4,4)*DM(5,5));
M(0,0) = (DM(2,0) + (DM(2,3)*TM(0,0) + DM(2,4)*TM(1,0) + DM(2,5)*TM(2,0))/Ts)/2.;
M(0,1) = (DM(2,1) + (DM(2,3)*TM(0,1) + DM(2,4)*TM(1,1) + DM(2,5)*TM(2,1))/Ts)/2.;
M(0,2) = (DM(2,2) + (DM(2,3)*TM(0,2) + DM(2,4)*TM(1,2) + DM(2,5)*TM(2,2))/Ts)/2.;
M(1,0) = -DM(1,0) - (DM(1,3)*TM(0,0) + DM(1,4)*TM(1,0) + DM(1,5)*TM(2,0))/Ts;
M(1,1) = -DM(1,1) - (DM(1,3)*TM(0,1) + DM(1,4)*TM(1,1) + DM(1,5)*TM(2,1))/Ts;
M(1,2) = -DM(1,2) - (DM(1,3)*TM(0,2) + DM(1,4)*TM(1,2) + DM(1,5)*TM(2,2))/Ts;
M(2,0) = (DM(0,0) + (DM(0,3)*TM(0,0) + DM(0,4)*TM(1,0) + DM(0,5)*TM(2,0))/Ts)/2.;
M(2,1) = (DM(0,1) + (DM(0,3)*TM(0,1) + DM(0,4)*TM(1,1) + DM(0,5)*TM(2,1))/Ts)/2.;
M(2,2) = (DM(0,2) + (DM(0,3)*TM(0,2) + DM(0,4)*TM(1,2) + DM(0,5)*TM(2,2))/Ts)/2.;
double det = fabs(cv::determinant(M));
if (fabs(det) > 1.0e-10)
break;
eps = (float)(s/(n*2)*1e-2);
}
if( iter < 2 ) {
Mat eVal, eVec;
eigenNonSymmetric(M, eVal, eVec);
@@ -740,10 +830,10 @@ cv::RotatedRect cv::fitEllipseDirect( InputArray _points )
double p1 = 2*pVec(2)*Q(0,0) - pVec(1)*Q(0,1);
double p2 = 2*pVec(0)*Q(0,1) - pVec(1)*Q(0,0);
x0 = p1/l3 + c.x;
y0 = p2/l3 + c.y;
a = sqrt(2.)*sqrt((u1 - 4.0*u2)/((l1 - l2)*l3));
b = sqrt(2.)*sqrt(-1.0*((u1 - 4.0*u2)/((l1 + l2)*l3)));
x0 = (p1/l3/scale) + c.x;
y0 = (p2/l3/scale) + c.y;
a = sqrt(2.)*sqrt((u1 - 4.0*u2)/((l1 - l2)*l3))/scale;
b = sqrt(2.)*sqrt(-1.0*((u1 - 4.0*u2)/((l1 + l2)*l3)))/scale;
if (pVec(1) == 0) {
if (pVec(0) < pVec(2) ) {
theta = 0;
@@ -767,7 +857,7 @@ cv::RotatedRect cv::fitEllipseDirect( InputArray _points )
box.angle = (float)(fmod(theta*180/CV_PI,180.0));
};
} else {
box = cv::fitEllipse( points );
box = cv::fitEllipseNoDirect( points );
}
return box;
}
+36
View File
@@ -66,4 +66,40 @@ TEST(Imgproc_FitEllipse_Issue_6544, accuracy) {
EXPECT_TRUE(fit_and_check_ellipse(pts));
}
TEST(Imgproc_FitEllipse_Issue_10270, accuracy) {
vector<Point2f> pts;
float scale = 1;
Point2f shift(0, 0);
pts.push_back(Point2f(0, 1)*scale+shift);
pts.push_back(Point2f(0, 2)*scale+shift);
pts.push_back(Point2f(0, 3)*scale+shift);
pts.push_back(Point2f(2, 3)*scale+shift);
pts.push_back(Point2f(0, 4)*scale+shift);
// check that we get almost vertical ellipse centered around (1, 3)
RotatedRect e = fitEllipse(pts);
EXPECT_LT(std::min(fabs(e.angle-180), fabs(e.angle)), 10.);
EXPECT_NEAR(e.center.x, 1, 1);
EXPECT_NEAR(e.center.y, 3, 1);
EXPECT_LT(e.size.width*3, e.size.height);
}
TEST(Imgproc_FitEllipse_JavaCase, accuracy) {
vector<Point2f> pts;
float scale = 1;
Point2f shift(0, 0);
pts.push_back(Point2f(0, 0)*scale+shift);
pts.push_back(Point2f(1, 1)*scale+shift);
pts.push_back(Point2f(-1, 1)*scale+shift);
pts.push_back(Point2f(-1, -1)*scale+shift);
pts.push_back(Point2f(1, -1)*scale+shift);
// check that we get almost vertical ellipse centered around (1, 3)
RotatedRect e = fitEllipse(pts);
EXPECT_NEAR(e.center.x, 0, 0.01);
EXPECT_NEAR(e.center.y, 0, 0.01);
EXPECT_NEAR(e.size.width, sqrt(2.)*2, 0.4);
EXPECT_NEAR(e.size.height, sqrt(2.)*2, 0.4);
}
}} // namespace
+10 -3
View File
@@ -895,7 +895,10 @@ class JavaWrapperGenerator(object):
ret = ""
default = ""
elif not fi.ctype: # c-tor
ret = "return (jlong) _retval_;"
if self.isSmartClass(ci):
ret = "return (jlong)(new Ptr<%(ctype)s>(_retval_));" % { 'ctype': fi.fullClass(isCPP=True) }
else:
ret = "return (jlong) _retval_;"
elif "v_type" in type_dict[fi.ctype]: # c-tor
if type_dict[fi.ctype]["v_type"] in ("Mat", "vector_Mat"):
ret = "return (jlong) _retval_;"
@@ -940,8 +943,12 @@ class JavaWrapperGenerator(object):
c_epilogue.append("return " + fi.ctype + "_to_List(env, _ret_val_vector_);")
if fi.classname:
if not fi.ctype: # c-tor
retval = fi.fullClass(isCPP=True) + "* _retval_ = "
cvname = "new " + fi.fullClass(isCPP=True)
if self.isSmartClass(ci):
retval = self.smartWrap(ci, fi.fullClass(isCPP=True)) + " _retval_ = "
cvname = "makePtr<" + fi.fullClass(isCPP=True) +">"
else:
retval = fi.fullClass(isCPP=True) + "* _retval_ = "
cvname = "new " + fi.fullClass(isCPP=True)
elif fi.static:
cvname = fi.fullName(isCPP=True)
else:
+11 -2
View File
@@ -49,8 +49,17 @@
postRun: [] ,
onRuntimeInitialized: function() {
console.log("Emscripten runtime is ready, launching QUnit tests...");
//console.log(cv.getBuildInformation());
QUnit.start();
if (window.cv instanceof Promise) {
window.cv.then((target) => {
window.cv = target;
//console.log(cv.getBuildInformation());
QUnit.start();
})
} else {
// for backward compatible
// console.log(cv.getBuildInformation());
QUnit.start();
}
},
print: (function() {
var element = document.getElementById('output');
@@ -197,8 +197,8 @@ bool convert(const FileNode& oldroot, FileStorage& newfs)
newfs << "cascade" << "{:opencv-cascade-classifier"
<< "stageType" << "BOOST"
<< "featureType" << "HAAR"
<< "height" << cascadesize.width
<< "width" << cascadesize.height
<< "width" << cascadesize.width
<< "height" << cascadesize.height
<< "stageParams" << "{"
<< "maxWeakCount" << (int)maxWeakCount
<< "}"
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env python
"""Algorithm serialization test."""
from __future__ import print_function
import tempfile
import os
import cv2 as cv
import numpy as np
from tests_common import NewOpenCVTests
class MyData:
def __init__(self):
self.A = 97
self.X = np.pi
self.name = 'mydata1234'
def write(self, fs, name):
fs.startWriteStruct(name, cv.FileNode_MAP|cv.FileNode_FLOW)
fs.write('A', self.A)
fs.write('X', self.X)
fs.write('name', self.name)
fs.endWriteStruct()
def read(self, node):
if (not node.empty()):
self.A = int(node.getNode('A').real())
self.X = node.getNode('X').real()
self.name = node.getNode('name').string()
else:
self.A = self.X = 0
self.name = ''
class filestorage_io_test(NewOpenCVTests):
strings_data = ['image1.jpg', 'Awesomeness', '../data/baboon.jpg']
R0 = np.eye(3,3)
T0 = np.zeros((3,1))
def write_data(self, fname):
fs = cv.FileStorage(fname, cv.FileStorage_WRITE)
R = self.R0
T = self.T0
m = MyData()
fs.write('iterationNr', 100)
fs.startWriteStruct('strings', cv.FileNode_SEQ)
for elem in self.strings_data:
fs.write('', elem)
fs.endWriteStruct()
fs.startWriteStruct('Mapping', cv.FileNode_MAP)
fs.write('One', 1)
fs.write('Two', 2)
fs.endWriteStruct()
fs.write('R_MAT', R)
fs.write('T_MAT', T)
m.write(fs, 'MyData')
fs.release()
def read_data_and_check(self, fname):
fs = cv.FileStorage(fname, cv.FileStorage_READ)
n = fs.getNode('iterationNr')
itNr = int(n.real())
self.assertEqual(itNr, 100)
n = fs.getNode('strings')
self.assertTrue(n.isSeq())
self.assertEqual(n.size(), len(self.strings_data))
for i in range(n.size()):
self.assertEqual(n.at(i).string(), self.strings_data[i])
n = fs.getNode('Mapping')
self.assertEqual(int(n.getNode('Two').real()), 2)
self.assertEqual(int(n.getNode('One').real()), 1)
R = fs.getNode('R_MAT').mat()
T = fs.getNode('T_MAT').mat()
self.assertEqual(cv.norm(R, self.R0, cv.NORM_INF), 0)
self.assertEqual(cv.norm(T, self.T0, cv.NORM_INF), 0)
m0 = MyData()
m = MyData()
m.read(fs.getNode('MyData'))
self.assertEqual(m.A, m0.A)
self.assertEqual(m.X, m0.X)
self.assertEqual(m.name, m0.name)
n = fs.getNode('NonExisting')
self.assertTrue(n.isNone())
fs.release()
def run_fs_test(self, ext):
fd, fname = tempfile.mkstemp(prefix="opencv_python_sample_filestorage", suffix=ext)
os.close(fd)
self.write_data(fname)
self.read_data_and_check(fname)
os.remove(fname)
def test_xml(self):
self.run_fs_test(".xml")
def test_yml(self):
self.run_fs_test(".yml")
def test_json(self):
self.run_fs_test(".json")
if __name__ == '__main__':
NewOpenCVTests.bootstrap()
+1 -1
View File
@@ -873,7 +873,7 @@ public:
VideoWriter::fourcc('P','I','M','1') is a MPEG-1 codec, VideoWriter::fourcc('M','J','P','G') is a
motion-jpeg codec etc. List of codes can be obtained at [Video Codecs by
FOURCC](http://www.fourcc.org/codecs.php) page. FFMPEG backend with MP4 container natively uses
other values as fourcc code: see [ObjectType](http://www.mp4ra.org/codecs.html),
other values as fourcc code: see [ObjectType](http://mp4ra.org/#/codecs),
so you may receive a warning message from OpenCV about fourcc code conversion.
@param fps Framerate of the created video stream.
@param frameSize Size of the video frames.
@@ -419,7 +419,7 @@ Simply call it with 4 chars fourcc code like `CV_FOURCC('I', 'Y', 'U', 'V')`
List of codes can be obtained at [Video Codecs by FOURCC](http://www.fourcc.org/codecs.php) page.
FFMPEG backend with MP4 container natively uses other values as fourcc code:
see [ObjectType](http://www.mp4ra.org/codecs.html).
see [ObjectType](http://mp4ra.org/#/codecs).
*/
CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4)
{
+13 -2
View File
@@ -1208,9 +1208,20 @@ bool CvCapture_FFMPEG::grabFrame()
#endif
int ret = av_read_frame(ic, &packet);
if (ret == AVERROR(EAGAIN)) continue;
/* else if (ret < 0) break; */
if (ret == AVERROR(EAGAIN))
continue;
if (ret == AVERROR_EOF)
{
if (rawMode)
break;
// flush cached frames from video decoder
packet.data = NULL;
packet.size = 0;
packet.stream_index = video_stream;
}
if( packet.stream_index != video_stream )
{