zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true;
zero_R = (cvtest::randInt(rng)%2) == 0 ? false : true;
- if (useCPlus)
+ return code;
+}
+
+void CV_InitInverseRectificationMapTest::prepare_to_validation(int/* test_case_idx*/)
+{
+ // Configure Parameters
+ Mat _a0 = test_mat[INPUT][0];
+ Mat _d0 = zero_distortion ? cv::Mat() : test_mat[INPUT][1];
+ Mat _R0 = zero_R ? cv::Mat() : test_mat[INPUT][2];
+ Mat _new_cam0 = zero_new_cam ? test_mat[INPUT][0] : test_mat[INPUT][3];
+ Mat _mapx(img_size, CV_32F), _mapy(img_size, CV_32F);
+
+ double a[9], d[5]={0., 0., 0., 0. , 0.}, R[9]={1., 0., 0., 0., 1., 0., 0., 0., 1.}, a1[9];
+ Mat _a(3, 3, CV_64F, a), _a1(3, 3, CV_64F, a1);
+ Mat _d(_d0.rows,_d0.cols, CV_MAKETYPE(CV_64F,_d0.channels()),d);
+ Mat _R(3, 3, CV_64F, R);
+ double fx, fy, cx, cy, ifx, ify, cxn, cyn;
+
+ // Camera matrix
+ CV_Assert(_a0.size() == Size(3, 3));
+ _a0.convertTo(_a, CV_64F);
+ if( !_new_cam0.empty() )
{
- camera_mat = test_mat[INPUT][1];
- distortion_coeffs = test_mat[INPUT][2];
- R = test_mat[INPUT][3];
- new_camera_mat = test_mat[INPUT][4];
+ CV_Assert(_new_cam0.size() == Size(3, 3));
+ _new_cam0.convertTo(_a1, CV_64F);
+ }
+ else
+ {
+ _a.copyTo(_a1);
}
- return code;
+ // Distortion
+ CV_Assert(_d0.empty() ||
+ _d0.size() == Size(5, 1) ||
+ _d0.size() == Size(1, 5) ||
+ _d0.size() == Size(4, 1) ||
+ _d0.size() == Size(1, 4));
+ if( !_d0.empty() )
+ _d0.convertTo(_d, CV_64F);
+
+ // Rotation
+ if( !_R0.empty() )
+ {
+ CV_Assert(_R0.size() == Size(3, 3));
+ Mat tmp;
+ _R0.convertTo(_R, CV_64F);
+ }
+
+ // Copy camera matrix
+ fx = a[0]; fy = a[4]; cx = a[2]; cy = a[5];
+
+ // Copy new camera matrix
+ ifx = a1[0]; ify = a1[4]; cxn = a1[2]; cyn = a1[5];
+
+ // Undistort
+ for( int v = 0; v < img_size.height; v++ )
+ {
+ for( int u = 0; u < img_size.width; u++ )
+ {
+ // Convert from image to pin-hole coordinates
+ double x = (u - cx)/fx;
+ double y = (v - cy)/fy;
+
+ // Undistort
+ double x2 = x*x, y2 = y*y;
+ double r2 = x2 + y2;
+ double cdist = 1./(1. + (d[0] + (d[1] + d[4]*r2)*r2)*r2); // (1. + (d[5] + (d[6] + d[7]*r2)*r2)*r2) == 1 as d[5-7]=0;
+ double x_ = (x - (d[2]*2.*x*y + d[3]*(r2 + 2.*x2)))*cdist;
+ double y_ = (y - (d[3]*2.*x*y + d[2]*(r2 + 2.*y2)))*cdist;
+
+ // Rectify
+ double X = R[0]*x_ + R[1]*y_ + R[2];
+ double Y = R[3]*x_ + R[4]*y_ + R[5];
+ double Z = R[6]*x_ + R[7]*y_ + R[8];
+ double x__ = X/Z;
+ double y__ = Y/Z;
+
+ // Convert from pin-hole to image coordinates
+ _mapy.at<float>(v, u) = (float)(y__*ify + cyn);
+ _mapx.at<float>(v, u) = (float)(x__*ifx + cxn);
+ }
+ }
+
+ // Convert
+ _mapx.convertTo(test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type());
+ _mapy.convertTo(test_mat[REF_OUTPUT][1], test_mat[REF_OUTPUT][0].type());
}
-void CV_InitUndistortRectifyMapTest::prepare_to_validation(int/* test_case_idx*/)
+void CV_InitInverseRectificationMapTest::run_func()
{
-#if 0
- int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
- double cam[9] = {0,0,0,0,0,0,0,0,1};
- double rot[9] = {1,0,0,0,1,0,0,0,1};
- vector<double> dist(dist_size);
- vector<double> new_cam(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
- vector<Point2d> points(N_POINTS);
- vector<Point2d> r_points(N_POINTS);
- //Run reference calculations
- Mat ref_points(test_mat[INPUT][0].size(),CV_64FC2,&r_points[0]);
- Mat _camera(3,3,CV_64F,cam);
- Mat _rot(3,3,CV_64F,rot);
- Mat _distort(test_mat[INPUT][2].size(),CV_64F,&dist[0]);
- Mat _new_cam(test_mat[INPUT][4].size(),CV_64F,&new_cam[0]);
- Mat _points(test_mat[INPUT][0].size(),CV_64FC2,&points[0]);
-
- cvtest::convert(test_mat[INPUT][1],_camera,_camera.type());
- cvtest::convert(test_mat[INPUT][2],_distort,_distort.type());
- cvtest::convert(test_mat[INPUT][3],_rot,_rot.type());
- cvtest::convert(test_mat[INPUT][4],_new_cam,_new_cam.type());
-
- //Applying precalculated undistort rectify map
- if (!useCPlus)
+ cv::Mat camera_mat = test_mat[INPUT][0];
+ cv::Mat dist = zero_distortion ? cv::Mat() : test_mat[INPUT][1];
+ cv::Mat R = zero_R ? cv::Mat() : test_mat[INPUT][2];
+ cv::Mat new_cam = zero_new_cam ? cv::Mat() : test_mat[INPUT][3];
+ cv::Mat& mapx = test_mat[OUTPUT][0], &mapy = test_mat[OUTPUT][1];
+ cv::initInverseRectificationMap(camera_mat,dist,R,new_cam,img_size,map_type,mapx,mapy);
+}
+
+double CV_InitInverseRectificationMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
+{
+ return 8;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+TEST(Calib3d_DefaultNewCameraMatrix, accuracy) { CV_DefaultNewCameraMatrixTest test; test.safe_run(); }
+TEST(Calib3d_UndistortPoints, accuracy) { CV_UndistortPointsTest test; test.safe_run(); }
+TEST(Calib3d_InitUndistortRectifyMap, accuracy) { CV_InitUndistortRectifyMapTest test; test.safe_run(); }
+TEST(DISABLED_Calib3d_InitInverseRectificationMap, accuracy) { CV_InitInverseRectificationMapTest test; test.safe_run(); }
+
+////////////////////////////// undistort /////////////////////////////////
+
+static void test_remap( const Mat& src, Mat& dst, const Mat& mapx, const Mat& mapy,
+ Mat* mask=0, int interpolation=CV_INTER_LINEAR )
+{
+ int x, y, k;
+ int drows = dst.rows, dcols = dst.cols;
+ int srows = src.rows, scols = src.cols;
+ const uchar* sptr0 = src.ptr();
+ int depth = src.depth(), cn = src.channels();
+ int elem_size = (int)src.elemSize();
+ int step = (int)(src.step / CV_ELEM_SIZE(depth));
+ int delta;
+
+ if( interpolation != CV_INTER_CUBIC )
{
- mapx = cv::Mat(_mapx);
- mapy = cv::Mat(_mapy);
+ delta = 0;
+ scols -= 1; srows -= 1;
}
- cv::Mat map1,map2;
- cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
- CvMat _map1 = map1;
- CvMat _map2 = map2;
- const Point2d* sptr = (const Point2d*)test_mat[INPUT][0].data;
- for( int i = 0;i < N_POINTS; i++ )
+ else
{
- int u = saturate_cast<int>(sptr[i].x);
- int v = saturate_cast<int>(sptr[i].y);
- points[i].x = _map1.data.fl[v*_map1.cols + u];
- points[i].y = _map2.data.fl[v*_map2.cols + u];
+ delta = 1;
+ scols = MAX(scols - 3, 0);
+ srows = MAX(srows - 3, 0);
}
- //---
+ int scols1 = MAX(scols - 2, 0);
+ int srows1 = MAX(srows - 2, 0);
- cv::undistortPoints(_points, ref_points, _camera,
- zero_distortion ? Mat() : _distort,
- zero_R ? Mat::eye(3,3,CV_64F) : _rot,
- zero_new_cam ? _camera : _new_cam);
- //cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
- cvtest::convert(ref_points, test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type());
- cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
+ if( mask )
+ *mask = Scalar::all(0);
- cvReleaseMat(&_mapx);
- cvReleaseMat(&_mapy);
-#else
- int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
- double cam[9] = {0,0,0,0,0,0,0,0,1};
- double rot[9] = {1,0,0,0,1,0,0,0,1};
- double* dist = new double[dist_size ];
- double* new_cam = new double[test_mat[INPUT][4].cols * test_mat[INPUT][4].rows];
- double* points = new double[N_POINTS*2];
- double* r_points = new double[N_POINTS*2];
- //Run reference calculations
- CvMat ref_points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,r_points);
- CvMat _camera = cvMat(3,3,CV_64F,cam);
- CvMat _rot = cvMat(3,3,CV_64F,rot);
- CvMat _distort = cvMat(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,dist);
- CvMat _new_cam = cvMat(test_mat[INPUT][4].rows,test_mat[INPUT][4].cols,CV_64F,new_cam);
- CvMat _points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,points);
+ for( y = 0; y < drows; y++ )
+ {
+ uchar* dptr = dst.ptr(y);
+ const float* mx = mapx.ptr<float>(y);
+ const float* my = mapy.ptr<float>(y);
+ uchar* m = mask ? mask->ptr(y) : 0;
+
+ for( x = 0; x < dcols; x++, dptr += elem_size )
+ {
+ float xs = mx[x];
+ float ys = my[x];
+ int ixs = cvFloor(xs);
+ int iys = cvFloor(ys);
+
+ if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 ||
+ (unsigned)(iys - delta - 1) >= (unsigned)srows1 )
+ {
+ if( m )
+ m[x] = 1;
+ if( (unsigned)(ixs - delta) >= (unsigned)scols ||
+ (unsigned)(iys - delta) >= (unsigned)srows )
+ continue;
+ }
- CvMat _input1 = cvMat(test_mat[INPUT][1]);
- CvMat _input2 = cvMat(test_mat[INPUT][2]);
- CvMat _input3 = cvMat(test_mat[INPUT][3]);
- CvMat _input4 = cvMat(test_mat[INPUT][4]);
+ xs -= ixs;
+ ys -= iys;
- cvtest::convert(cvarrToMat(&_input1), cvarrToMat(&_camera), -1);
- cvtest::convert(cvarrToMat(&_input2), cvarrToMat(&_distort), -1);
- cvtest::convert(cvarrToMat(&_input3), cvarrToMat(&_rot), -1);
- cvtest::convert(cvarrToMat(&_input4), cvarrToMat(&_new_cam), -1);
+ switch( depth )
+ {
+ case CV_8U:
+ {
+ const uchar* sptr = sptr0 + iys*step + ixs*cn;
+ for( k = 0; k < cn; k++ )
+ {
+ float v00 = sptr[k];
+ float v01 = sptr[cn + k];
+ float v10 = sptr[step + k];
+ float v11 = sptr[step + cn + k];
+
+ v00 = v00 + xs*(v01 - v00);
+ v10 = v10 + xs*(v11 - v10);
+ v00 = v00 + ys*(v10 - v00);
+ dptr[k] = (uchar)cvRound(v00);
+ }
+ }
+ break;
+ case CV_16U:
+ {
+ const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn;
+ for( k = 0; k < cn; k++ )
+ {
+ float v00 = sptr[k];
+ float v01 = sptr[cn + k];
+ float v10 = sptr[step + k];
+ float v11 = sptr[step + cn + k];
+
+ v00 = v00 + xs*(v01 - v00);
+ v10 = v10 + xs*(v11 - v10);
+ v00 = v00 + ys*(v10 - v00);
+ ((ushort*)dptr)[k] = (ushort)cvRound(v00);
+ }
+ }
+ break;
+ case CV_32F:
+ {
+ const float* sptr = (const float*)sptr0 + iys*step + ixs*cn;
+ for( k = 0; k < cn; k++ )
+ {
+ float v00 = sptr[k];
+ float v01 = sptr[cn + k];
+ float v10 = sptr[step + k];
+ float v11 = sptr[step + cn + k];
+
+ v00 = v00 + xs*(v01 - v00);
+ v10 = v10 + xs*(v11 - v10);
+ v00 = v00 + ys*(v10 - v00);
+ ((float*)dptr)[k] = (float)v00;
+ }
+ }
+ break;
+ default:
- assert(0);
++ CV_Assert(0);
+ }
+ }
+ }
+}
- //Applying precalculated undistort rectify map
- if (!useCPlus)
+class CV_ImgWarpBaseTest : public cvtest::ArrayTest
+{
+public:
+ CV_ImgWarpBaseTest( bool warp_matrix );
+
+protected:
+ int read_params( const cv::FileStorage& fs );
+ int prepare_test_case( int test_case_idx );
+ void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
+ void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
+ void fill_array( int test_case_idx, int i, int j, Mat& arr );
+
+ int interpolation;
+ int max_interpolation;
+ double spatial_scale_zoom, spatial_scale_decimate;
+};
+
+
+CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( bool warp_matrix )
+{
+ test_array[INPUT].push_back(NULL);
+ if( warp_matrix )
+ test_array[INPUT].push_back(NULL);
+ test_array[INPUT_OUTPUT].push_back(NULL);
+ test_array[REF_INPUT_OUTPUT].push_back(NULL);
+ max_interpolation = 5;
+ interpolation = 0;
+ element_wise_relative_error = false;
+ spatial_scale_zoom = 0.01;
+ spatial_scale_decimate = 0.005;
+}
+
+
+int CV_ImgWarpBaseTest::read_params( const cv::FileStorage& fs )
+{
+ int code = cvtest::ArrayTest::read_params( fs );
+ return code;
+}
+
+
+void CV_ImgWarpBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
+{
+ cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
+ if( CV_MAT_DEPTH(type) == CV_32F )
{
- mapx = cv::cvarrToMat(_mapx);
- mapy = cv::cvarrToMat(_mapy);
+ low = Scalar::all(-10.);
+ high = Scalar::all(10);
}
- cv::Mat map1,map2;
- cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
- CvMat _map1 = cvMat(map1);
- CvMat _map2 = cvMat(map2);
- for (int i=0;i<N_POINTS;i++)
+}
+
+
+void CV_ImgWarpBaseTest::get_test_array_types_and_sizes( int test_case_idx,
+ vector<vector<Size> >& sizes, vector<vector<int> >& types )
+{
+ RNG& rng = ts->get_rng();
+ int depth = cvtest::randInt(rng) % 3;
+ int cn = cvtest::randInt(rng) % 3 + 1;
+ cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
+ depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;
+ cn += cn == 2;
+
+ types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
+ if( test_array[INPUT].size() > 1 )
+ types[INPUT][1] = cvtest::randInt(rng) & 1 ? CV_32FC1 : CV_64FC1;
+
+ interpolation = cvtest::randInt(rng) % max_interpolation;
+}
+
+
+void CV_ImgWarpBaseTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
+{
+ if( i != INPUT || j != 0 )
+ cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
+}
+
+int CV_ImgWarpBaseTest::prepare_test_case( int test_case_idx )
+{
+ int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
+ Mat& img = test_mat[INPUT][0];
+ int i, j, cols = img.cols;
+ int type = img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
+ double scale = depth == CV_16U ? 1000. : 255.*0.5;
+ double space_scale = spatial_scale_decimate;
+ vector<float> buffer(img.cols*cn);
+
+ if( code <= 0 )
+ return code;
+
+ if( test_mat[INPUT_OUTPUT][0].cols >= img.cols &&
+ test_mat[INPUT_OUTPUT][0].rows >= img.rows )
+ space_scale = spatial_scale_zoom;
+
+ for( i = 0; i < img.rows; i++ )
{
- double u = test_mat[INPUT][0].ptr<double>()[2*i];
- double v = test_mat[INPUT][0].ptr<double>()[2*i+1];
- _points.data.db[2*i] = (double)_map1.data.fl[(int)v*_map1.cols+(int)u];
- _points.data.db[2*i+1] = (double)_map2.data.fl[(int)v*_map2.cols+(int)u];
+ uchar* ptr = img.ptr(i);
+ switch( cn )
+ {
+ case 1:
+ for( j = 0; j < cols; j++ )
+ buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale);
+ break;
+ case 2:
+ for( j = 0; j < cols; j++ )
+ {
+ buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale);
+ buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale);
+ }
+ break;
+ case 3:
+ for( j = 0; j < cols; j++ )
+ {
+ buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale);
+ buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale);
+ buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
+ }
+ break;
+ case 4:
+ for( j = 0; j < cols; j++ )
+ {
+ buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale);
+ buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale);
+ buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
+ buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale);
+ }
+ break;
+ default:
- assert(0);
++ CV_Assert(0);
+ }
+
+ /*switch( depth )
+ {
+ case CV_8U:
+ for( j = 0; j < cols*cn; j++ )
+ ptr[j] = (uchar)cvRound(buffer[j]);
+ break;
+ case CV_16U:
+ for( j = 0; j < cols*cn; j++ )
+ ((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]);
+ break;
+ case CV_32F:
+ for( j = 0; j < cols*cn; j++ )
+ ((float*)ptr)[j] = (float)buffer[j];
+ break;
+ default:
- assert(0);
++ CV_Assert(0);
+ }*/
+ cv::Mat src(1, cols*cn, CV_32F, &buffer[0]);
+ cv::Mat dst(1, cols*cn, depth, ptr);
+ src.convertTo(dst, dst.type());
}
- //---
+ return code;
+}
- cvUndistortPoints(&_points,&ref_points,&_camera,
- zero_distortion ? 0 : &_distort, zero_R ? 0 : &_rot, zero_new_cam ? &_camera : &_new_cam);
- //cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
- CvMat dst = cvMat(test_mat[REF_OUTPUT][0]);
- cvtest::convert(cvarrToMat(&ref_points), cvarrToMat(&dst), -1);
- cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
+class CV_UndistortTest : public CV_ImgWarpBaseTest
+{
+public:
+ CV_UndistortTest();
- delete[] dist;
- delete[] new_cam;
- delete[] points;
- delete[] r_points;
- cvReleaseMat(&_mapx);
- cvReleaseMat(&_mapy);
-#endif
+protected:
+ void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
+ void run_func();
+ int prepare_test_case( int test_case_idx );
+ void prepare_to_validation( int /*test_case_idx*/ );
+ double get_success_error_level( int test_case_idx, int i, int j );
+ void fill_array( int test_case_idx, int i, int j, Mat& arr );
+
+private:
+ cv::Mat input0;
+ cv::Mat input1;
+ cv::Mat input2;
+ cv::Mat input_new_cam;
+ cv::Mat input_output;
+
+ bool zero_new_cam;
+ bool zero_distortion;
+};
+
+
+CV_UndistortTest::CV_UndistortTest() : CV_ImgWarpBaseTest( false )
+{
+ //spatial_scale_zoom = spatial_scale_decimate;
+ test_array[INPUT].push_back(NULL);
+ test_array[INPUT].push_back(NULL);
+ test_array[INPUT].push_back(NULL);
+
+ spatial_scale_decimate = spatial_scale_zoom;
}
-void CV_InitUndistortRectifyMapTest::run_func()
+
+void CV_UndistortTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
+{
+ RNG& rng = ts->get_rng();
+ CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
+ int type = types[INPUT][0];
+ type = CV_MAKETYPE( CV_8U, CV_MAT_CN(type) );
+ types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = type;
+ types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
+ types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
+ sizes[INPUT][1] = cvSize(3,3);
+ sizes[INPUT][2] = cvtest::randInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
+ types[INPUT][3] = types[INPUT][1];
+ sizes[INPUT][3] = sizes[INPUT][1];
+ interpolation = CV_INTER_LINEAR;
+}
+
+
+void CV_UndistortTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
{
- if (useCPlus)
+ if( i != INPUT )
+ CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr );
+}
+
+
+void CV_UndistortTest::run_func()
+{
+ if (zero_distortion)
{
- cv::Mat input2,input3,input4;
- input2 = zero_distortion ? cv::Mat() : test_mat[INPUT][2];
- input3 = zero_R ? cv::Mat() : test_mat[INPUT][3];
- input4 = zero_new_cam ? cv::Mat() : test_mat[INPUT][4];
- cv::initUndistortRectifyMap(camera_mat,input2,input3,input4,img_size,mat_type,mapx,mapy);
+ cv::undistort(input0,input_output,input1,cv::Mat());
}
else
{
--- /dev/null
- assert(ID >= 0 && ID < (int)(sizeof(openclamdblas_fn)/sizeof(openclamdblas_fn[0])));
+/*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) 2010-2013, Advanced Micro Devices, 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 OpenCV Foundation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "../../precomp.hpp"
+
+#ifdef HAVE_CLAMDBLAS
+
+#include "opencv2/core/opencl/runtime/opencl_core.hpp"
+#include "opencv2/core/opencl/runtime/opencl_clblas.hpp"
+
+#if defined(_WIN32)
+#include <windows.h>
+
+ static void* WinGetProcAddress(const char* name)
+ {
+ static HMODULE opencl_module = NULL;
+ if (!opencl_module)
+ {
+ opencl_module = GetModuleHandleA("clBLAS.dll");
+ if (!opencl_module)
+ {
+ opencl_module = LoadLibraryA("clBLAS.dll");
+ if (!opencl_module)
+ return NULL;
+ }
+ }
+ return (void*)GetProcAddress(opencl_module, name);
+ }
+ #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name)
+#endif // _WIN32
+
+#if defined(__linux__)
+ #include <dlfcn.h>
+ #include <stdio.h>
+
+ static void* GetProcAddress (const char* name)
+ {
+ static void* h = NULL;
+ if (!h)
+ {
+ h = dlopen("libclBLAS.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (!h)
+ return NULL;
+ }
+
+ return dlsym(h, name);
+ }
+ #define CV_CL_GET_PROC_ADDRESS(name) GetProcAddress(name)
+#endif
+
+#ifndef CV_CL_GET_PROC_ADDRESS
+#ifdef __GNUC__
+#warning("OPENCV: OpenCL BLAS dynamic library loader: check configuration")
+#else
+#pragma message("WARNING: OPENCV: OpenCL BLAS dynamic library loader: check configuration")
+#endif
+#define CV_CL_GET_PROC_ADDRESS(name) NULL
+#endif
+
+static void* openclamdblas_check_fn(int ID);
+
+#include "runtime_common.hpp"
+
+//
+// BEGIN OF CUSTOM FUNCTIONS
+//
+
+#define CUSTOM_FUNCTION_ID 1000
+
+//
+// END OF CUSTOM FUNCTIONS HERE
+//
+
+#include "autogenerated/opencl_clblas_impl.hpp"
+
+static void* openclamdblas_check_fn(int ID)
+{
++ CV_Assert(ID >= 0 && ID < (int)(sizeof(openclamdblas_fn)/sizeof(openclamdblas_fn[0])));
+ const struct DynamicFnEntry* e = openclamdblas_fn[ID];
+ void* func = CV_CL_GET_PROC_ADDRESS(e->fnName);
+ if (!func)
+ {
+ throw cv::Exception(cv::Error::OpenCLApiCallError,
+ cv::format("OpenCL AMD BLAS function is not available: [%s]", e->fnName),
+ CV_Func, __FILE__, __LINE__);
+ }
+ *(e->ppFn) = func;
+ return func;
+}
+
+#endif
--- /dev/null
- assert(ID >= 0 && ID < (int)(sizeof(openclamdfft_fn)/sizeof(openclamdfft_fn[0])));
+/*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) 2010-2013, Advanced Micro Devices, 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 OpenCV Foundation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "../../precomp.hpp"
+
+#ifdef HAVE_CLAMDFFT
+
+#include "opencv2/core/opencl/runtime/opencl_core.hpp"
+#include "opencv2/core/opencl/runtime/opencl_clfft.hpp"
+
+#if defined(_WIN32)
+#include <windows.h>
+
+ static void* WinGetProcAddress(const char* name)
+ {
+ static HMODULE opencl_module = NULL;
+ if (!opencl_module)
+ {
+ opencl_module = GetModuleHandleA("clFFT.dll");
+ if (!opencl_module)
+ {
+ opencl_module = LoadLibraryA("clFFT.dll");
+ if (!opencl_module)
+ return NULL;
+ }
+ }
+ return (void*)GetProcAddress(opencl_module, name);
+ }
+ #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name)
+#endif // _WIN32
+
+#if defined(__linux__)
+ #include <dlfcn.h>
+ #include <stdio.h>
+
+ static void* GetProcAddress (const char* name)
+ {
+ static void* h = NULL;
+ if (!h)
+ {
+ h = dlopen("libclFFT.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (!h)
+ return NULL;
+ }
+
+ return dlsym(h, name);
+ }
+ #define CV_CL_GET_PROC_ADDRESS(name) GetProcAddress(name)
+#endif
+
+#ifndef CV_CL_GET_PROC_ADDRESS
+#ifdef __GNUC__
+#warning("OPENCV: OpenCL FFT dynamic library loader: check configuration")
+#else
+#pragma message("WARNING: OPENCV: OpenCL FFT dynamic library loader: check configuration")
+#endif
+#define CV_CL_GET_PROC_ADDRESS(name) NULL
+#endif
+
+static void* openclamdfft_check_fn(int ID);
+
+#include "runtime_common.hpp"
+
+//
+// BEGIN OF CUSTOM FUNCTIONS
+//
+
+#define CUSTOM_FUNCTION_ID 1000
+
+//
+// END OF CUSTOM FUNCTIONS HERE
+//
+
+#include "autogenerated/opencl_clfft_impl.hpp"
+
+static void* openclamdfft_check_fn(int ID)
+{
++ CV_Assert(ID >= 0 && ID < (int)(sizeof(openclamdfft_fn)/sizeof(openclamdfft_fn[0])));
+ const struct DynamicFnEntry* e = openclamdfft_fn[ID];
+ void* func = CV_CL_GET_PROC_ADDRESS(e->fnName);
+ if (!func)
+ {
+ throw cv::Exception(cv::Error::OpenCLApiCallError,
+ cv::format("OpenCL AMD FFT function is not available: [%s]", e->fnName),
+ CV_Func, __FILE__, __LINE__);
+ }
+ *(e->ppFn) = func;
+ return func;
+}
+
+#endif
}
else
{
- int l = (int)strlen(ptr);
- if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !icvEof(fs) )
- CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
+ struct_flags = FileNode::EMPTY + (key ? FileNode::MAP : FileNode::SEQ);
+ //fs->is_first = 0;
}
- fs->lineno++; // FIXIT doesn't really work with long lines. It must be counted via '\n' or '\r' symbols, not the number of icvGets() calls.
+
+ if( !FileNode::isEmptyCollection(struct_flags) )
+ ptr = fs->flush();
}
- }
- return ptr;
-}
+ if( !key )
+ key = "_";
+ else if( key[0] == '_' && key[1] == '\0' )
+ CV_Error( cv::Error::StsBadArg, "A single _ is a reserved tag name" );
-static void icvXMLGetMultilineStringContent(CvFileStorage* fs,
- char* ptr, char* &beg, char* &end)
-{
- ptr = icvXMLSkipSpaces(fs, ptr, CV_XML_INSIDE_TAG);
- beg = ptr;
- end = ptr;
- if ( fs->dummy_eof )
- return ; /* end of file */
-
- if ( *beg == '<' )
- return; /* end of string */
-
- /* find end */
- while( cv_isprint(*ptr) ) /* no check for base64 string */
- ++ ptr;
- if ( *ptr == '\0' )
- CV_PARSE_ERROR( "Unexpected end of line" );
-
- end = ptr;
-}
-
+ len = (int)strlen( key );
+ *ptr++ = '<';
+ if( tag_type == CV_XML_CLOSING_TAG )
+ {
+ if( !attrlist.empty() )
+ CV_Error( cv::Error::StsBadArg, "Closing tag should not include any attributes" );
+ *ptr++ = '/';
+ }
-static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node)
-{
- char * beg = 0;
- char * end = 0;
+ if( !cv_isalpha(key[0]) && key[0] != '_' )
+ CV_Error( cv::Error::StsBadArg, "Key should start with a letter or _" );
- icvXMLGetMultilineStringContent(fs, ptr, beg, end);
- if (beg >= end)
- return end; // CV_PARSE_ERROR("Empty Binary Data");
+ ptr = fs->resizeWriteBuffer( ptr, len );
+ for( i = 0; i < len; i++ )
+ {
+ char c = key[i];
+ if( !cv_isalnum(c) && c != '_' && c != '-' )
+ CV_Error( cv::Error::StsBadArg, "Key name may only contain alphanumeric characters [a-zA-Z0-9], '-' and '_'" );
+ ptr[i] = c;
+ }
+ ptr += len;
- /* calc (decoded) total_byte_size from header */
- std::string dt;
- {
- if (end - beg < static_cast<int>(base64::ENCODED_HEADER_SIZE))
- CV_PARSE_ERROR("Unrecognized Base64 header");
+ int nattr = (int)attrlist.size();
+ CV_Assert( nattr % 2 == 0 );
- std::vector<char> header(base64::HEADER_SIZE + 1, ' ');
- base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE);
- if ( !base64::read_base64_header(header, dt) || dt.empty() )
- CV_PARSE_ERROR("Invalid `dt` in Base64 header");
+ for( i = 0; i < nattr; i += 2 )
+ {
+ size_t len0 = attrlist[i].size();
+ size_t len1 = attrlist[i+1].size();
+ CV_Assert( len0 > 0 );
- beg += base64::ENCODED_HEADER_SIZE;
- }
+ ptr = fs->resizeWriteBuffer( ptr, (int)(len0 + len1 + 4) );
+ *ptr++ = ' ';
- /* get all Base64 data */
- std::string base64_buffer; // not an efficient way.
- base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE );
- while( beg < end )
- {
- base64_buffer.append( beg, end );
- beg = end;
- icvXMLGetMultilineStringContent( fs, beg, beg, end );
- }
- if ( base64_buffer.empty() ||
- !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) )
- CV_PARSE_ERROR( "Invalid Base64 data." );
-
- /* alloc buffer for all decoded data(include header) */
- std::vector<uchar> binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) );
- int total_byte_size = static_cast<int>(
- base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false )
- );
- {
- base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() );
- const uchar * buffer_beg = reinterpret_cast<const uchar *>( base64_buffer.data() );
- const uchar * buffer_end = buffer_beg + base64_buffer.size();
- parser.read( buffer_beg, buffer_end );
- parser.flush();
- }
+ memcpy( ptr, attrlist[i].c_str(), len0 );
+ ptr += len0;
+ *ptr++ = '=';
+ *ptr++ = '\"';
+ if( len1 > 0 )
+ memcpy( ptr, attrlist[i+1].c_str(), len1 );
+ ptr += len1;
+ *ptr++ = '\"';
+ }
- node->tag = CV_NODE_NONE;
- int struct_flags = CV_NODE_SEQ;
- /* after icvFSCreateCollection, node->tag == struct_flags */
- icvFSCreateCollection(fs, struct_flags, node);
- base64::make_seq(fs, binary_buffer.data(), total_byte_size, dt.c_str(), *node->data.seq);
-
- if (fs->dummy_eof) {
- /* end of file */
- return fs->buffer_start;
- } else {
- /* end of line */
- return end;
+ if( tag_type == CV_XML_EMPTY_TAG )
+ *ptr++ = '/';
+ *ptr++ = '>';
+ fs->setBufferPtr(ptr);
+ current_struct.flags = struct_flags & ~FileNode::EMPTY;
}
-}
-
-static char*
-icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
- CvAttrList** _list, int* _tag_type );
-
-static char*
-icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
- int value_type CV_DEFAULT(CV_NODE_NONE))
-{
- CvFileNode *elem = node;
- bool have_space = true, is_simple = true;
- int is_user_type = CV_NODE_IS_USER(value_type);
- memset( node, 0, sizeof(*node) );
-
- value_type = CV_NODE_TYPE(value_type);
-
- for(;;)
+ FStructData startWriteStruct(const FStructData& parent, const char* key,
+ int struct_flags, const char* type_name=0)
{
- char c = *ptr, d;
- char* endptr;
-
- if( cv_isspace(c) || c == '\0' || (c == '<' && ptr[1] == '!' && ptr[2] == '-') ) // FIXIT ptr[1], ptr[2] - out of bounds read without check or data fetch (#11061)
+ std::vector<std::string> attrlist;
+ if( type_name && *type_name )
{
- ptr = icvXMLSkipSpaces( fs, ptr, 0 );
- have_space = true;
- c = *ptr;
+ attrlist.push_back("type_id");
+ attrlist.push_back(type_name);
}
- d = ptr[1]; // FIXIT ptr[1] - out of bounds read without check or data fetch (#11061)
+ writeTag( key, CV_XML_OPENING_TAG, attrlist );
- if( c =='<' || c == '\0' )
- {
- CvStringHashNode *key = 0, *key2 = 0;
- CvAttrList* list = 0;
- CvTypeInfo* info = 0;
- int tag_type = 0;
- int is_noname = 0;
- const char* type_name = 0;
- int elem_type = CV_NODE_NONE;
-
- if( d == '/' || c == '\0' )
- break;
+ FStructData current_struct;
+ current_struct.tag = key ? std::string(key) : std::string();
+ current_struct.flags = struct_flags;
+ current_struct.indent = parent.indent + CV_XML_INDENT;
- ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
+ return current_struct;
+ }
- if( tag_type == CV_XML_DIRECTIVE_TAG )
- CV_PARSE_ERROR( "Directive tags are not allowed here" );
- if( tag_type == CV_XML_EMPTY_TAG )
- CV_PARSE_ERROR( "Empty tags are not supported" );
+ void endWriteStruct(const FStructData& current_struct)
+ {
+ writeTag( current_struct.tag.c_str(), CV_XML_CLOSING_TAG );
+ }
- CV_Assert(tag_type == CV_XML_OPENING_TAG);
+ void write(const char* key, int value)
+ {
+ char buf[128], *ptr = fs::itoa( value, buf, 10 );
+ writeScalar( key, ptr);
+ }
- /* for base64 string */
- bool is_binary_string = false;
+ void write( const char* key, double value )
+ {
+ char buf[128];
+ writeScalar( key, fs::doubleToString( buf, value, false ) );
+ }
- type_name = list ? cvAttrValue( list, "type_id" ) : 0;
- if( type_name )
- {
- if( strcmp( type_name, "str" ) == 0 )
- elem_type = CV_NODE_STRING;
- else if( strcmp( type_name, "map" ) == 0 )
- elem_type = CV_NODE_MAP;
- else if( strcmp( type_name, "seq" ) == 0 )
- elem_type = CV_NODE_SEQ;
- else if (strcmp(type_name, "binary") == 0)
- {
- elem_type = CV_NODE_NONE;
- is_binary_string = true;
- }
- else
- {
- info = cvFindType( type_name );
- if( info )
- elem_type = CV_NODE_USER;
- }
- }
+ void write(const char* key, const char* str, bool quote)
+ {
+ char buf[CV_FS_MAX_LEN*6+16];
+ char* data = (char*)str;
+ int i, len;
- is_noname = key->str.len == 1 && key->str.ptr[0] == '_';
- if( !CV_NODE_IS_COLLECTION(node->tag) )
- {
- icvFSCreateCollection( fs, is_noname ? CV_NODE_SEQ : CV_NODE_MAP, node );
- }
- else if( is_noname ^ CV_NODE_IS_SEQ(node->tag) )
- CV_PARSE_ERROR( is_noname ? "Map element should have a name" :
- "Sequence element should not have name (use <_></_>)" );
+ if( !str )
+ CV_Error( cv::Error::StsNullPtr, "Null string pointer" );
- if( is_noname )
- elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
- else
- elem = cvGetFileNode( fs, node, key, 1 );
- CV_Assert(elem);
- if (!is_binary_string)
- ptr = icvXMLParseValue( fs, ptr, elem, elem_type);
- else {
- /* for base64 string */
- ptr = icvXMLParseBase64( fs, ptr, elem);
- ptr = icvXMLSkipSpaces( fs, ptr, 0 );
- }
+ len = (int)strlen(str);
+ if( len > CV_FS_MAX_LEN )
+ CV_Error( cv::Error::StsBadArg, "The written string is too long" );
- if( !is_noname )
- elem->tag |= CV_NODE_NAMED;
- is_simple = is_simple && !CV_NODE_IS_COLLECTION(elem->tag);
- elem->info = info;
- ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );
- if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
- CV_PARSE_ERROR( "Mismatched closing tag" );
- have_space = true;
- }
- else
+ if( quote || len == 0 || str[0] != '\"' || str[0] != str[len-1] )
{
- if( !have_space )
- CV_PARSE_ERROR( "There should be space between literals" );
-
- elem = node;
- if( node->tag != CV_NODE_NONE )
+ bool need_quote = quote || len == 0;
+ data = buf;
+ *data++ = '\"';
+ for( i = 0; i < len; i++ )
{
- if( !CV_NODE_IS_COLLECTION(node->tag) )
- icvFSCreateCollection( fs, CV_NODE_SEQ, node );
-
- elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
- elem->info = 0;
- }
+ char c = str[i];
- if( value_type != CV_NODE_STRING &&
- (cv_isdigit(c) || ((c == '-' || c == '+') &&
- (cv_isdigit(d) || d == '.')) || (c == '.' && cv_isalnum(d))) ) // a number
- {
- double fval;
- int ival;
- endptr = ptr + (c == '-' || c == '+');
- while( cv_isdigit(*endptr) )
- endptr++;
- if( *endptr == '.' || *endptr == 'e' )
+ if( (uchar)c >= 128 || c == ' ' )
{
- fval = icv_strtod( fs, ptr, &endptr );
- /*if( endptr == ptr || cv_isalpha(*endptr) )
- icvProcessSpecialDouble( fs, ptr, &fval, &endptr ));*/
- elem->tag = CV_NODE_REAL;
- elem->data.f = fval;
+ *data++ = c;
+ need_quote = true;
}
- else
+ else if( !cv_isprint(c) || c == '<' || c == '>' || c == '&' || c == '\'' || c == '\"' )
{
- ival = (int)strtol( ptr, &endptr, 0 );
- elem->tag = CV_NODE_INT;
- elem->data.i = ival;
- }
-
- if( endptr == ptr )
- CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
-
- ptr = endptr;
- CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
- }
- else
- {
- // string
- char buf[CV_FS_MAX_LEN+16] = {0};
- int i = 0, len, is_quoted = 0;
- elem->tag = CV_NODE_STRING;
- if( c == '\"' )
- is_quoted = 1;
- else
- --ptr;
-
- for( ;; )
- {
- c = *++ptr;
- CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
- if( !cv_isalnum(c) )
+ *data++ = '&';
+ if( c == '<' )
{
- if( c == '\"' )
- {
- if( !is_quoted )
- CV_PARSE_ERROR( "Literal \" is not allowed within a string. Use "" );
- ++ptr;
- break;
- }
- else if( !cv_isprint(c) || c == '<' || (!is_quoted && cv_isspace(c)))
- {
- if( is_quoted )
- CV_PARSE_ERROR( "Closing \" is expected" );
- break;
- }
- else if( c == '\'' || c == '>' )
- {
- CV_PARSE_ERROR( "Literal \' or > are not allowed. Use ' or >" );
- }
- else if( c == '&' )
- {
- if( *++ptr == '#' )
- {
- int val, base = 10;
- ptr++;
- if( *ptr == 'x' )
- {
- base = 16;
- ptr++;
- }
- val = (int)strtol( ptr, &endptr, base );
- if( (unsigned)val > (unsigned)255 ||
- !endptr || *endptr != ';' )
- CV_PARSE_ERROR( "Invalid numeric value in the string" );
- c = (char)val;
- }
- else
- {
- endptr = ptr;
- do c = *++endptr;
- while( cv_isalnum(c) );
- if( c != ';' )
- CV_PARSE_ERROR( "Invalid character in the symbol entity name" );
- len = (int)(endptr - ptr);
- if( len == 2 && memcmp( ptr, "lt", len ) == 0 )
- c = '<';
- else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )
- c = '>';
- else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )
- c = '&';
- else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )
- c = '\'';
- else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )
- c = '\"';
- else
- {
- memcpy( buf + i, ptr-1, len + 2 );
- i += len + 2;
- }
- }
- ptr = endptr;
- CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
- }
+ memcpy(data, "lt", 2);
+ data += 2;
+ }
+ else if( c == '>' )
+ {
+ memcpy(data, "gt", 2);
+ data += 2;
+ }
+ else if( c == '&' )
+ {
+ memcpy(data, "amp", 3);
+ data += 3;
}
- buf[i++] = c;
- if( i >= CV_FS_MAX_LEN )
- CV_PARSE_ERROR( "Too long string literal" );
+ else if( c == '\'' )
+ {
+ memcpy(data, "apos", 4);
+ data += 4;
+ }
+ else if( c == '\"' )
+ {
+ memcpy( data, "quot", 4);
+ data += 4;
+ }
+ else
+ {
+ sprintf( data, "#x%02x", (uchar)c );
+ data += 4;
+ }
+ *data++ = ';';
+ need_quote = 1;
}
- elem->data.str = cvMemStorageAllocString( fs->memstorage, buf, i );
+ else
+ *data++ = c;
}
-
- if( !CV_NODE_IS_COLLECTION(value_type) && value_type != CV_NODE_NONE )
- break;
- have_space = false;
+ if( !need_quote && (cv_isdigit(str[0]) ||
+ str[0] == '+' || str[0] == '-' || str[0] == '.' ))
+ need_quote = true;
+
+ if( need_quote )
+ *data++ = '\"';
+ len = (int)(data - buf) - !need_quote;
+ *data++ = '\0';
+ data = buf + (int)!need_quote;
}
- }
- if( (CV_NODE_TYPE(node->tag) == CV_NODE_NONE ||
- (CV_NODE_TYPE(node->tag) != value_type &&
- !CV_NODE_IS_COLLECTION(node->tag))) &&
- CV_NODE_IS_COLLECTION(value_type) )
- {
- icvFSCreateCollection( fs, CV_NODE_IS_MAP(value_type) ?
- CV_NODE_MAP : CV_NODE_SEQ, node );
+ writeScalar( key, data );
}
- if( value_type != CV_NODE_NONE &&
- value_type != CV_NODE_TYPE(node->tag) )
- CV_PARSE_ERROR( "The actual type is different from the specified type" );
-
- if( CV_NODE_IS_COLLECTION(node->tag) && is_simple )
- node->data.seq->flags |= CV_NODE_SEQ_SIMPLE;
-
- node->tag |= is_user_type ? CV_NODE_USER : 0;
- return ptr;
-}
-
-
-static char*
-icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
- CvAttrList** _list, int* _tag_type )
-{
- int tag_type = 0;
- CvStringHashNode* tagname = 0;
- CvAttrList *first = 0, *last = 0;
- int count = 0, max_count = 4;
- int attr_buf_size = (max_count*2 + 1)*sizeof(char*) + sizeof(CvAttrList);
- char* endptr;
- char c;
- int have_space;
-
- if( *ptr == '\0' )
- CV_PARSE_ERROR( "Preliminary end of the stream" );
-
- if( *ptr != '<' )
- CV_PARSE_ERROR( "Tag should start with \'<\'" );
-
- ptr++;
- CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
- if( cv_isalnum(*ptr) || *ptr == '_' )
- tag_type = CV_XML_OPENING_TAG;
- else if( *ptr == '/' )
- {
- tag_type = CV_XML_CLOSING_TAG;
- ptr++;
- }
- else if( *ptr == '?' )
- {
- tag_type = CV_XML_HEADER_TAG;
- ptr++;
- }
- else if( *ptr == '!' )
+ void writeScalar(const char* key, const char* data)
{
- tag_type = CV_XML_DIRECTIVE_TAG;
- CV_Assert( ptr[1] != '-' || ptr[2] != '-' );
- ptr++;
- }
- else
- CV_PARSE_ERROR( "Unknown tag type" );
-
- for(;;)
- {
- CvStringHashNode* attrname;
-
- if( !cv_isalpha(*ptr) && *ptr != '_' )
- CV_PARSE_ERROR( "Name should start with a letter or underscore" );
+ fs->check_if_write_struct_is_delayed(false);
+ if ( fs->get_state_of_writing_base64() == FileStorage_API::Uncertain )
+ {
+ fs->switch_to_Base64_state( FileStorage_API::NotUse );
+ }
+ else if ( fs->get_state_of_writing_base64() == FileStorage_API::InUse )
+ {
+ CV_Error( cv::Error::StsError, "At present, output Base64 data only." );
+ }
- endptr = ptr - 1;
- do c = *++endptr;
- while( cv_isalnum(c) || c == '_' || c == '-' );
+ int len = (int)strlen(data);
+ if( key && *key == '\0' )
+ key = 0;
- attrname = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );
- CV_Assert(attrname);
- ptr = endptr;
- CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
+ FStructData& current_struct = fs->getCurrentStruct();
+ int struct_flags = current_struct.flags;
- if( !tagname )
- tagname = attrname;
- else
+ if( FileNode::isMap(struct_flags) ||
+ (!FileNode::isCollection(struct_flags) && key) )
{
- if( tag_type == CV_XML_CLOSING_TAG )
- CV_PARSE_ERROR( "Closing tag should not contain any attributes" );
-
- if( !last || count >= max_count )
- {
- CvAttrList* chunk;
-
- chunk = (CvAttrList*)cvMemStorageAlloc( fs->memstorage, attr_buf_size );
- memset( chunk, 0, attr_buf_size );
- chunk->attr = (const char**)(chunk + 1);
- count = 0;
- if( !last )
- first = last = chunk;
- else
- last = last->next = chunk;
- }
- last->attr[count*2] = attrname->str.ptr;
+ writeTag( key, CV_XML_OPENING_TAG );
+ char* ptr = fs->resizeWriteBuffer( fs->bufferPtr(), len );
+ memcpy( ptr, data, len );
+ fs->setBufferPtr( ptr + len );
+ writeTag( key, CV_XML_CLOSING_TAG );
}
-
- if( last )
+ else
{
- CvFileNode stub;
+ char* ptr = fs->bufferPtr();
+ int new_offset = (int)(ptr - fs->bufferStart()) + len;
- if( *ptr != '=' )
- {
- ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
- if( *ptr != '=' )
- CV_PARSE_ERROR( "Attribute name should be followed by \'=\'" );
- }
+ if( key )
+ CV_Error( cv::Error::StsBadArg, "elements with keys can not be written to sequence" );
+
+ current_struct.flags = FileNode::SEQ;
- c = *++ptr;
- if( c != '\"' && c != '\'' )
+ if( (new_offset > fs->wrapMargin() && new_offset - current_struct.indent > 10) ||
+ (ptr > fs->bufferStart() && ptr[-1] == '>') )
{
- ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
- if( *ptr != '\"' && *ptr != '\'' )
- CV_PARSE_ERROR( "Attribute value should be put into single or double quotes" );
+ ptr = fs->flush();
}
+ else if( ptr > fs->bufferStart() + current_struct.indent && ptr[-1] != '>' )
+ *ptr++ = ' ';
- ptr = icvXMLParseValue( fs, ptr, &stub, CV_NODE_STRING );
- CV_Assert( stub.tag == CV_NODE_STRING );
- last->attr[count*2+1] = stub.data.str.ptr;
- count++;
+ memcpy( ptr, data, len );
+ fs->setBufferPtr(ptr + len);
}
+ }
- c = *ptr;
- have_space = cv_isspace(c) || c == '\0';
-
- if( c != '>' )
- {
- ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
- c = *ptr;
- }
+ void writeComment(const char* comment, bool eol_comment)
+ {
+ FStructData& current_struct = fs->getCurrentStruct();
+ int len;
+ int multiline;
+ const char* eol;
+ char* ptr;
+
+ if( !comment )
+ CV_Error( cv::Error::StsNullPtr, "Null comment" );
+
+ if( strstr(comment, "--") != 0 )
+ CV_Error( cv::Error::StsBadArg, "Double hyphen \'--\' is not allowed in the comments" );
+
+ len = (int)strlen(comment);
+ eol = strchr(comment, '\n');
+ multiline = eol != 0;
+ ptr = fs->bufferPtr();
+
+ if( multiline || !eol_comment || fs->bufferEnd() - ptr < len + 5 )
+ ptr = fs->flush();
+ else if( ptr > fs->bufferStart() + current_struct.indent )
+ *ptr++ = ' ';
- if( c == '>' )
+ if( !multiline )
{
- if( tag_type == CV_XML_HEADER_TAG )
- CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
- ptr++;
- break;
+ ptr = fs->resizeWriteBuffer( ptr, len + 9 );
+ sprintf( ptr, "<!-- %s -->", comment );
+ len = (int)strlen(ptr);
}
- else if( c == '?' && tag_type == CV_XML_HEADER_TAG )
+ else
{
- if( ptr[1] != '>' ) // FIXIT ptr[1] - out of bounds read without check
- CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
- ptr += 2;
- break;
+ strcpy( ptr, "<!--" );
+ len = 4;
}
- else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG ) // FIXIT ptr[1] - out of bounds read without check
+
+ fs->setBufferPtr(ptr + len);
+ ptr = fs->flush();
+
+ if( multiline )
{
- tag_type = CV_XML_EMPTY_TAG;
- ptr += 2;
- break;
+ while( comment )
+ {
+ if( eol )
+ {
+ ptr = fs->resizeWriteBuffer( ptr, (int)(eol - comment) + 1 );
+ memcpy( ptr, comment, eol - comment + 1 );
+ ptr += eol - comment;
+ comment = eol + 1;
+ eol = strchr( comment, '\n' );
+ }
+ else
+ {
+ len = (int)strlen(comment);
+ ptr = fs->resizeWriteBuffer( ptr, len );
+ memcpy( ptr, comment, len );
+ ptr += len;
+ comment = 0;
+ }
+ fs->setBufferPtr(ptr);
+ ptr = fs->flush();
+ }
+ sprintf( ptr, "-->" );
+ fs->setBufferPtr(ptr + 3);
+ fs->flush();
}
-
- if( !have_space )
- CV_PARSE_ERROR( "There should be space between attributes" );
}
- *_tag = tagname;
- *_tag_type = tag_type;
- *_list = first;
-
- return ptr;
-}
+ void startNextStream()
+ {
+ fs->puts( "\n<!-- next stream -->\n" );
+ }
+protected:
+ FileStorage_API* fs;
+};
-void icvXMLParse( CvFileStorage* fs )
+class XMLParser : public FileStorageParser
{
- char* ptr = fs->buffer_start;
- CvStringHashNode *key = 0, *key2 = 0;
- CvAttrList* list = 0;
- int tag_type = 0;
-
- // CV_XML_INSIDE_TAG is used to prohibit leading comments
- ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
-
- if( memcmp( ptr, "<?xml", 5 ) != 0 ) // FIXIT ptr[1..] - out of bounds read without check
- CV_PARSE_ERROR( "Valid XML should start with \'<?xml ...?>\'" );
-
- ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
-
- /*{
- const char* version = cvAttrValue( list, "version" );
- if( version && strncmp( version, "1.", 2 ) != 0 )
- CV_Error( CV_StsParseError, "Unsupported version of XML" );
- }*/
- // we support any 8-bit encoding, so we do not need to check the actual encoding.
- // we do not support utf-16, but in the case of utf-16 we will not get here anyway.
- /*{
- const char* encoding = cvAttrValue( list, "encoding" );
- if( encoding && strcmp( encoding, "ASCII" ) != 0 &&
- strcmp( encoding, "UTF-8" ) != 0 &&
- strcmp( encoding, "utf-8" ) != 0 )
- CV_PARSE_ERROR( "Unsupported encoding" );
- }*/
-
- while( *ptr != '\0' )
+public:
+ XMLParser(FileStorage_API* _fs) : fs(_fs)
{
- ptr = icvXMLSkipSpaces( fs, ptr, 0 );
-
- if( *ptr != '\0' )
- {
- CvFileNode* root_node;
- ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
- if( tag_type != CV_XML_OPENING_TAG ||
- !key ||
- strcmp(key->str.ptr,"opencv_storage") != 0 )
- CV_PARSE_ERROR( "<opencv_storage> tag is missing" );
-
- root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );
- ptr = icvXMLParseValue( fs, ptr, root_node, CV_NODE_NONE );
- ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );
- if( tag_type != CV_XML_CLOSING_TAG || key != key2 )
- CV_PARSE_ERROR( "</opencv_storage> tag is missing" );
- ptr = icvXMLSkipSpaces( fs, ptr, 0 );
- }
}
- CV_Assert( fs->dummy_eof != 0 );
-}
-
-
-/****************************************************************************************\
-* XML Emitter *
-\****************************************************************************************/
-#define icvXMLFlush icvFSFlush
+ virtual ~XMLParser() {}
-static void
-icvXMLWriteTag( CvFileStorage* fs, const char* key, int tag_type, CvAttrList list )
-{
- char* ptr = fs->buffer;
- int i, len = 0;
- int struct_flags = fs->struct_flags;
+ char* skipSpaces( char* ptr, int mode )
+ {
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
- if( key && key[0] == '\0' )
- key = 0;
+ int level = 0;
- if( tag_type == CV_XML_OPENING_TAG || tag_type == CV_XML_EMPTY_TAG )
- {
- if( CV_NODE_IS_COLLECTION(struct_flags) )
+ for(;;)
{
- if( CV_NODE_IS_MAP(struct_flags) ^ (key != 0) )
- CV_Error( CV_StsBadArg, "An attempt to add element without a key to a map, "
- "or add element with key to sequence" );
- }
- else
- {
- struct_flags = CV_NODE_EMPTY + (key ? CV_NODE_MAP : CV_NODE_SEQ);
- fs->is_first = 0;
- }
+ char c;
+ ptr--;
- if( !CV_NODE_IS_EMPTY(struct_flags) )
- ptr = icvXMLFlush(fs);
- }
+ if( mode == CV_XML_INSIDE_COMMENT )
+ {
+ do c = *++ptr;
+ while( cv_isprint_or_tab(c) && (c != '-' || ptr[1] != '-' || ptr[2] != '>') );
- if( !key )
- key = "_";
- else if( key[0] == '_' && key[1] == '\0' )
- CV_Error( CV_StsBadArg, "A single _ is a reserved tag name" );
+ if( c == '-' )
+ {
- assert( ptr[1] == '-' && ptr[2] == '>' );
++ CV_Assert( ptr[1] == '-' && ptr[2] == '>' );
+ mode = 0;
+ ptr += 3;
+ }
+ }
+ else if( mode == CV_XML_INSIDE_DIRECTIVE )
+ {
+ // !!!NOTE!!! This is not quite correct, but should work in most cases
+ do
+ {
+ c = *++ptr;
+ level += c == '<';
+ level -= c == '>';
+ if( level < 0 )
+ return ptr;
+ } while( cv_isprint_or_tab(c) );
+ }
+ else
+ {
+ do c = *++ptr;
+ while( c == ' ' || c == '\t' );
- len = (int)strlen( key );
- *ptr++ = '<';
- if( tag_type == CV_XML_CLOSING_TAG )
- {
- if( list.attr )
- CV_Error( CV_StsBadArg, "Closing tag should not include any attributes" );
- *ptr++ = '/';
- }
+ if( c == '<' && ptr[1] == '!' && ptr[2] == '-' && ptr[3] == '-' )
+ {
+ if( mode != 0 )
+ CV_PARSE_ERROR_CPP( "Comments are not allowed here" );
+ mode = CV_XML_INSIDE_COMMENT;
+ ptr += 4;
+ }
+ else if( cv_isprint(c) )
+ break;
+ }
- if( !cv_isalpha(key[0]) && key[0] != '_' )
- CV_Error( CV_StsBadArg, "Key should start with a letter or _" );
+ if( !cv_isprint(*ptr) )
+ {
+ if( *ptr != '\0' && *ptr != '\n' && *ptr != '\r' )
+ CV_PARSE_ERROR_CPP( "Invalid character in the stream" );
+ ptr = fs->gets();
+ if( !ptr || *ptr == '\0' )
+ break;
+ }
+ }
+ return ptr;
+ }
- ptr = icvFSResizeWriteBuffer( fs, ptr, len );
- for( i = 0; i < len; i++ )
+ bool getBase64Row(char* ptr, int /*indent*/, char* &beg, char* &end)
{
- char c = key[i];
- if( !cv_isalnum(c) && c != '_' && c != '-' )
- CV_Error( CV_StsBadArg, "Key name may only contain alphanumeric characters [a-zA-Z0-9], '-' and '_'" );
- ptr[i] = c;
+ beg = end = ptr = skipSpaces(ptr, CV_XML_INSIDE_TAG);
+ if( !ptr || !*ptr )
+ return false;
+
+ // closing XML tag
+ if ( *beg == '<' )
+ return false;
+
+ // find end of the row
+ while( cv_isprint(*ptr) )
+ ++ptr;
+ if ( *ptr == '\0' )
+ CV_PARSE_ERROR_CPP( "Unexpected end of line" );
+
+ end = ptr;
+ return true;
}
- ptr += len;
- for(;;)
+ char* parseValue( char* ptr, FileNode& node )
{
- const char** attr = list.attr;
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
- for( ; attr && attr[0] != 0; attr += 2 )
+ FileNode new_elem;
+ bool have_space = true;
+ int value_type = node.type();
+ std::string key, key2, type_name;
+
+ for(;;)
{
- int len0 = (int)strlen(attr[0]);
- int len1 = (int)strlen(attr[1]);
+ char c = *ptr, d;
+ char* endptr;
- ptr = icvFSResizeWriteBuffer( fs, ptr, len0 + len1 + 4 );
- *ptr++ = ' ';
- memcpy( ptr, attr[0], len0 );
- ptr += len0;
- *ptr++ = '=';
- *ptr++ = '\"';
- memcpy( ptr, attr[1], len1 );
- ptr += len1;
- *ptr++ = '\"';
- }
- if( !list.next )
- break;
- list = *list.next;
- }
+ // FIXIT ptr[1], ptr[2] - out of bounds read without check or data fetch (#11061)
+ if( cv_isspace(c) || c == '\0' ||
+ (c == '<' && ptr[1] == '!' && ptr[2] == '-') )
+ {
+ ptr = skipSpaces( ptr, 0 );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+ have_space = true;
+ c = *ptr;
+ }
- if( tag_type == CV_XML_EMPTY_TAG )
- *ptr++ = '/';
- *ptr++ = '>';
- fs->buffer = ptr;
- fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;
-}
+ d = ptr[1]; // FIXIT ptr[1] - out of bounds read without check or data fetch (#11061)
+ if( c =='<' || c == '\0' )
+ {
+ int tag_type = 0;
+ int elem_type = FileNode::NONE;
-void icvXMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, const char* type_name)
-{
- CvXMLStackRecord parent;
- const char* attr[10];
- int idx = 0;
+ if( d == '/' || c == '\0' )
+ break;
- struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;
- if( !CV_NODE_IS_COLLECTION(struct_flags))
- CV_Error( CV_StsBadArg,
- "Some collection type: CV_NODE_SEQ or CV_NODE_MAP must be specified" );
+ ptr = parseTag( ptr, key, type_name, tag_type );
- if ( type_name && *type_name == '\0' )
- type_name = 0;
+ if( tag_type == CV_XML_DIRECTIVE_TAG )
+ CV_PARSE_ERROR_CPP( "Directive tags are not allowed here" );
+ if( tag_type == CV_XML_EMPTY_TAG )
+ CV_PARSE_ERROR_CPP( "Empty tags are not supported" );
- if( type_name )
- {
- attr[idx++] = "type_id";
- attr[idx++] = type_name;
- }
- attr[idx++] = 0;
+ CV_Assert(tag_type == CV_XML_OPENING_TAG);
- icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(attr,0) );
+ /* for base64 string */
+ bool binary_string = false;
- parent.struct_flags = fs->struct_flags & ~CV_NODE_EMPTY;
- parent.struct_indent = fs->struct_indent;
- parent.struct_tag = fs->struct_tag;
- cvSaveMemStoragePos( fs->strstorage, &parent.pos );
- cvSeqPush( fs->write_stack, &parent );
+ if( !type_name.empty() )
+ {
+ const char* tn = type_name.c_str();
+ if( strcmp(tn, "str") == 0 )
+ elem_type = FileNode::STRING;
+ else if( strcmp( tn, "map" ) == 0 )
+ elem_type = FileNode::MAP;
+ else if( strcmp( tn, "seq" ) == 0 )
+ elem_type = FileNode::SEQ;
+ else if( strcmp( tn, "binary") == 0)
+ binary_string = true;
+ }
- fs->struct_indent += CV_XML_INDENT;
- if( !CV_NODE_IS_FLOW(struct_flags) )
- icvXMLFlush( fs );
+ new_elem = fs->addNode(node, key, elem_type, 0);
+ if (!binary_string)
+ ptr = parseValue(ptr, new_elem);
+ else
+ {
+ ptr = fs->parseBase64( ptr, 0, new_elem);
+ ptr = skipSpaces( ptr, 0 );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+ }
- fs->struct_flags = struct_flags;
- if( key )
- {
- fs->struct_tag = cvMemStorageAllocString( fs->strstorage, (char*)key, -1 );
- }
- else
- {
- fs->struct_tag.ptr = 0;
- fs->struct_tag.len = 0;
- }
-}
+ ptr = parseTag( ptr, key2, type_name, tag_type );
+ if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
+ CV_PARSE_ERROR_CPP( "Mismatched closing tag" );
+ have_space = true;
+ }
+ else
+ {
+ if( !have_space )
+ CV_PARSE_ERROR_CPP( "There should be space between literals" );
+ FileNode* elem = &node;
+ if( node.type() != FileNode::NONE )
+ {
+ fs->convertToCollection( FileNode::SEQ, node );
+ new_elem = fs->addNode(node, std::string(), FileNode::NONE, 0);
+ elem = &new_elem;
+ }
-void icvXMLEndWriteStruct( CvFileStorage* fs )
-{
- CvXMLStackRecord parent;
+ if( value_type != FileNode::STRING &&
+ (cv_isdigit(c) || ((c == '-' || c == '+') &&
+ (cv_isdigit(d) || d == '.')) || (c == '.' && cv_isalnum(d))) ) // a number
+ {
+ endptr = ptr + (c == '-' || c == '+');
+ while( cv_isdigit(*endptr) )
+ endptr++;
+ if( *endptr == '.' || *endptr == 'e' )
+ {
+ double fval = fs->strtod( ptr, &endptr );
+ elem->setValue(FileNode::REAL, &fval);
+ }
+ else
+ {
+ int ival = (int)strtol( ptr, &endptr, 0 );
+ elem->setValue(FileNode::INT, &ival);
+ }
- if( fs->write_stack->total == 0 )
- CV_Error( CV_StsError, "An extra closing tag" );
+ if( endptr == ptr )
+ CV_PARSE_ERROR_CPP( "Invalid numeric value (inconsistent explicit type specification?)" );
- icvXMLWriteTag( fs, fs->struct_tag.ptr, CV_XML_CLOSING_TAG, cvAttrList(0,0) );
- cvSeqPop( fs->write_stack, &parent );
+ ptr = endptr;
+ CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
+ }
+ else
+ {
+ // string
+ int i = 0, len, is_quoted = 0;
+ if( c == '\"' )
+ is_quoted = 1;
+ else
+ --ptr;
+ strbuf[0] = '\0';
+
+ for( ;; )
+ {
+ c = *++ptr;
+ CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
- fs->struct_indent = parent.struct_indent;
- fs->struct_flags = parent.struct_flags;
- fs->struct_tag = parent.struct_tag;
- cvRestoreMemStoragePos( fs->strstorage, &parent.pos );
-}
+ if( !cv_isalnum(c) )
+ {
+ if( c == '\"' )
+ {
+ if( !is_quoted )
+ CV_PARSE_ERROR_CPP( "Literal \" is not allowed within a string. Use "" );
+ ++ptr;
+ break;
+ }
+ else if( !cv_isprint(c) || c == '<' || (!is_quoted && cv_isspace(c)))
+ {
+ if( is_quoted )
+ CV_PARSE_ERROR_CPP( "Closing \" is expected" );
+ break;
+ }
+ else if( c == '\'' || c == '>' )
+ {
+ CV_PARSE_ERROR_CPP( "Literal \' or > are not allowed. Use ' or >" );
+ }
+ else if( c == '&' )
+ {
+ if( *++ptr == '#' )
+ {
+ int val, base = 10;
+ ptr++;
+ if( *ptr == 'x' )
+ {
+ base = 16;
+ ptr++;
+ }
+ val = (int)strtol( ptr, &endptr, base );
+ if( (unsigned)val > (unsigned)255 ||
+ !endptr || *endptr != ';' )
+ CV_PARSE_ERROR_CPP( "Invalid numeric value in the string" );
+ c = (char)val;
+ }
+ else
+ {
+ endptr = ptr;
+ do c = *++endptr;
+ while( cv_isalnum(c) );
+ if( c != ';' )
+ CV_PARSE_ERROR_CPP( "Invalid character in the symbol entity name" );
+ len = (int)(endptr - ptr);
+ if( len == 2 && memcmp( ptr, "lt", len ) == 0 )
+ c = '<';
+ else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )
+ c = '>';
+ else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )
+ c = '&';
+ else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )
+ c = '\'';
+ else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )
+ c = '\"';
+ else
+ {
+ if (len + 2 + i >= CV_FS_MAX_LEN)
+ CV_PARSE_ERROR_CPP("string is too long");
+ memcpy( strbuf + i, ptr-1, len + 2 );
+ i += len + 2;
+ }
+ }
+ ptr = endptr;
+ CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
+ }
+ }
+ if (i + 1 >= CV_FS_MAX_LEN)
+ CV_PARSE_ERROR_CPP("Too long string literal");
+ strbuf[i++] = c;
+ }
+ elem->setValue(FileNode::STRING, strbuf, i);
+ }
+ if( value_type != FileNode::NONE && value_type != FileNode::SEQ && value_type != FileNode::MAP )
+ break;
+ have_space = false;
+ }
+ }
+ fs->finalizeCollection(node);
-void icvXMLStartNextStream( CvFileStorage* fs )
-{
- if( !fs->is_first )
- {
- while( fs->write_stack->total > 0 )
- icvXMLEndWriteStruct(fs);
-
- fs->struct_indent = 0;
- icvXMLFlush(fs);
- /* XML does not allow multiple top-level elements,
- so we just put a comment and continue
- the current (and the only) "stream" */
- icvPuts( fs, "\n<!-- next stream -->\n" );
- /*fputs( "</opencv_storage>\n", fs->file );
- fputs( "<opencv_storage>\n", fs->file );*/
- fs->buffer = fs->buffer_start;
+ return ptr;
}
-}
-
-void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len )
-{
- check_if_write_struct_is_delayed( fs );
- if ( fs->state_of_writing_base64 == base64::fs::Uncertain )
- {
- switch_to_Base64_state( fs, base64::fs::NotUse );
- }
- else if ( fs->state_of_writing_base64 == base64::fs::InUse )
+ char* parseTag( char* ptr, std::string& tag_name,
+ std::string& type_name, int& tag_type )
{
- CV_Error( CV_StsError, "Currently only Base64 data is allowed." );
- }
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid tag input");
- if( CV_NODE_IS_MAP(fs->struct_flags) ||
- (!CV_NODE_IS_COLLECTION(fs->struct_flags) && key) )
- {
- icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(0,0) );
- char* ptr = icvFSResizeWriteBuffer( fs, fs->buffer, len );
- memcpy( ptr, data, len );
- fs->buffer = ptr + len;
- icvXMLWriteTag( fs, key, CV_XML_CLOSING_TAG, cvAttrList(0,0) );
- }
- else
- {
- char* ptr = fs->buffer;
- int new_offset = (int)(ptr - fs->buffer_start) + len;
+ if( *ptr == '\0' )
+ CV_PARSE_ERROR_CPP( "Unexpected end of the stream" );
- if( key && key[0] != '\0' )
- CV_Error( CV_StsBadArg, "elements with keys can not be written to sequence" );
+ if( *ptr != '<' )
+ CV_PARSE_ERROR_CPP( "Tag should start with \'<\'" );
- fs->struct_flags = CV_NODE_SEQ;
+ ptr++;
+ CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
- if( (new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10) ||
- (ptr > fs->buffer_start && ptr[-1] == '>' && !CV_NODE_IS_EMPTY(fs->struct_flags)) )
+ if( cv_isalnum(*ptr) || *ptr == '_' )
+ tag_type = CV_XML_OPENING_TAG;
+ else if( *ptr == '/' )
{
- ptr = icvXMLFlush(fs);
+ tag_type = CV_XML_CLOSING_TAG;
+ ptr++;
}
- else if( ptr > fs->buffer_start + fs->struct_indent && ptr[-1] != '>' )
- *ptr++ = ' ';
-
- memcpy( ptr, data, len );
- fs->buffer = ptr + len;
- }
-}
-
-
-void icvXMLWriteInt( CvFileStorage* fs, const char* key, int value )
-{
- char buf[128], *ptr = icv_itoa( value, buf, 10 );
- int len = (int)strlen(ptr);
- icvXMLWriteScalar( fs, key, ptr, len );
-}
-
-
-void icvXMLWriteReal( CvFileStorage* fs, const char* key, double value )
-{
- char buf[128];
- int len = (int)strlen( icvDoubleToString( buf, value ));
- icvXMLWriteScalar( fs, key, buf, len );
-}
+ else if( *ptr == '?' )
+ {
+ tag_type = CV_XML_HEADER_TAG;
+ ptr++;
+ }
+ else if( *ptr == '!' )
+ {
+ tag_type = CV_XML_DIRECTIVE_TAG;
- assert( ptr[1] != '-' || ptr[2] != '-' );
++ CV_Assert( ptr[1] != '-' || ptr[2] != '-' );
+ ptr++;
+ }
+ else
+ CV_PARSE_ERROR_CPP( "Unknown tag type" );
+ tag_name.clear();
+ type_name.clear();
-void icvXMLWriteString( CvFileStorage* fs, const char* key, const char* str, int quote )
-{
- char buf[CV_FS_MAX_LEN*6+16];
- char* data = (char*)str;
- int i, len;
+ for(;;)
+ {
+ char c, *endptr;
+ if( !cv_isalpha(*ptr) && *ptr != '_' )
+ CV_PARSE_ERROR_CPP( "Name should start with a letter or underscore" );
- if( !str )
- CV_Error( CV_StsNullPtr, "Null string pointer" );
+ endptr = ptr - 1;
+ do c = *++endptr;
+ while( cv_isalnum(c) || c == '_' || c == '-' );
- len = (int)strlen(str);
- if( len > CV_FS_MAX_LEN )
- CV_Error( CV_StsBadArg, "The written string is too long" );
+ std::string attrname(ptr, (size_t)(endptr - ptr));
+ ptr = endptr;
+ CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
- if( quote || len == 0 || str[0] != '\"' || str[0] != str[len-1] )
- {
- int need_quote = quote || len == 0;
- data = buf;
- *data++ = '\"';
- for( i = 0; i < len; i++ )
- {
- char c = str[i];
-
- if( (uchar)c >= 128 || c == ' ' )
- {
- *data++ = c;
- need_quote = 1;
- }
- else if( !cv_isprint(c) || c == '<' || c == '>' || c == '&' || c == '\'' || c == '\"' )
+ if( tag_name.empty() )
+ tag_name = attrname;
+ else
{
- *data++ = '&';
- if( c == '<' )
- {
- memcpy(data, "lt", 2);
- data += 2;
- }
- else if( c == '>' )
- {
- memcpy(data, "gt", 2);
- data += 2;
- }
- else if( c == '&' )
+ if( tag_type == CV_XML_CLOSING_TAG )
+ CV_PARSE_ERROR_CPP( "Closing tag should not contain any attributes" );
+
+ if( *ptr != '=' )
{
- memcpy(data, "amp", 3);
- data += 3;
+ ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid attribute");
+ if( *ptr != '=' )
+ CV_PARSE_ERROR_CPP( "Attribute name should be followed by \'=\'" );
}
- else if( c == '\'' )
+
+ c = *++ptr;
+ if( c != '\"' && c != '\'' )
{
- memcpy(data, "apos", 4);
- data += 4;
+ ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
+ if( *ptr != '\"' && *ptr != '\'' )
+ CV_PARSE_ERROR_CPP( "Attribute value should be put into single or double quotes" );
}
- else if( c == '\"' )
+
+ char quote = *ptr++;
+ endptr = ptr;
+ for(;;)
{
- memcpy( data, "quot", 4);
- data += 4;
+ c = *endptr++;
+ if( c == quote )
+ break;
+ if( c == '\0' )
+ CV_PARSE_ERROR_CPP( "Unexpected end of line" );
}
- else
+
+ if( attrname == "type_id" )
{
- sprintf( data, "#x%02x", (uchar)c );
- data += 4;
+ CV_Assert( type_name.empty() );
+ type_name = std::string(ptr, (size_t)(endptr - 1 - ptr));
}
- *data++ = ';';
- need_quote = 1;
+
+ ptr = endptr;
}
- else
- *data++ = c;
- }
- if( !need_quote && (cv_isdigit(str[0]) ||
- str[0] == '+' || str[0] == '-' || str[0] == '.' ))
- need_quote = 1;
- if( need_quote )
- *data++ = '\"';
- len = (int)(data - buf) - !need_quote;
- *data++ = '\0';
- data = buf + !need_quote;
- }
+ c = *ptr;
+ bool have_space = cv_isspace(c) || c == '\0';
- icvXMLWriteScalar( fs, key, data, len );
-}
+ if( c != '>' )
+ {
+ ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+ c = *ptr;
+ }
+ if( c == '>' )
+ {
+ if( tag_type == CV_XML_HEADER_TAG )
+ CV_PARSE_ERROR_CPP( "Invalid closing tag for <?xml ..." );
+ ptr++;
+ break;
+ }
+ else if( c == '?' && tag_type == CV_XML_HEADER_TAG )
+ {
+ if( ptr[1] != '>' ) // FIXIT ptr[1] - out of bounds read without check
+ CV_PARSE_ERROR_CPP( "Invalid closing tag for <?xml ..." );
+ ptr += 2;
+ break;
+ }
+ else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG ) // FIXIT ptr[1] - out of bounds read without check
+ {
+ tag_type = CV_XML_EMPTY_TAG;
+ ptr += 2;
+ break;
+ }
-void icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
-{
- int len;
- int multiline;
- const char* eol;
- char* ptr;
+ if( !have_space )
+ CV_PARSE_ERROR_CPP( "There should be space between attributes" );
+ }
- if( !comment )
- CV_Error( CV_StsNullPtr, "Null comment" );
+ return ptr;
+ }
- if( strstr(comment, "--") != 0 )
- CV_Error( CV_StsBadArg, "Double hyphen \'--\' is not allowed in the comments" );
+ bool parse(char* ptr)
+ {
+ CV_Assert( fs != 0 );
- len = (int)strlen(comment);
- eol = strchr(comment, '\n');
- multiline = eol != 0;
- ptr = fs->buffer;
+ std::string key, key2, type_name;
+ int tag_type = 0;
+ bool ok = false;
- if( multiline || !eol_comment || fs->buffer_end - ptr < len + 5 )
- ptr = icvXMLFlush( fs );
- else if( ptr > fs->buffer_start + fs->struct_indent )
- *ptr++ = ' ';
+ // CV_XML_INSIDE_TAG is used to prohibit leading comments
+ ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
- if( !multiline )
- {
- ptr = icvFSResizeWriteBuffer( fs, ptr, len + 9 );
- sprintf( ptr, "<!-- %s -->", comment );
- len = (int)strlen(ptr);
- }
- else
- {
- strcpy( ptr, "<!--" );
- len = 4;
- }
+ if( memcmp( ptr, "<?xml", 5 ) != 0 ) // FIXIT ptr[1..] - out of bounds read without check
+ CV_PARSE_ERROR_CPP( "Valid XML should start with \'<?xml ...?>\'" );
- fs->buffer = ptr + len;
- ptr = icvXMLFlush(fs);
+ ptr = parseTag( ptr, key, type_name, tag_type );
+ FileNode root_collection(fs->getFS(), 0, 0);
- if( multiline )
- {
- while( comment )
+ while( ptr && *ptr != '\0' )
{
- if( eol )
- {
- ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );
- memcpy( ptr, comment, eol - comment + 1 );
- ptr += eol - comment;
- comment = eol + 1;
- eol = strchr( comment, '\n' );
- }
- else
+ ptr = skipSpaces( ptr, 0 );
+ if (!ptr)
+ CV_PARSE_ERROR_CPP("Invalid input");
+
+ if( *ptr != '\0' )
{
- len = (int)strlen(comment);
- ptr = icvFSResizeWriteBuffer( fs, ptr, len );
- memcpy( ptr, comment, len );
- ptr += len;
- comment = 0;
+ ptr = parseTag( ptr, key, type_name, tag_type );
+ if( tag_type != CV_XML_OPENING_TAG || key != "opencv_storage" )
+ CV_PARSE_ERROR_CPP( "<opencv_storage> tag is missing" );
+ FileNode root = fs->addNode(root_collection, std::string(), FileNode::MAP, 0);
+ ptr = parseValue( ptr, root );
+ ptr = parseTag( ptr, key2, type_name, tag_type );
+ if( tag_type != CV_XML_CLOSING_TAG || key != key2 )
+ CV_PARSE_ERROR_CPP( "</opencv_storage> tag is missing" );
+ ptr = skipSpaces( ptr, 0 );
+ ok = true;
}
- fs->buffer = ptr;
- ptr = icvXMLFlush( fs );
}
- sprintf( ptr, "-->" );
- fs->buffer = ptr + 3;
- icvXMLFlush( fs );
+ CV_Assert( fs->eof() );
+ return ok;
}
+
+ FileStorage_API* fs;
+ char strbuf[CV_FS_MAX_LEN+16];
+};
+
+Ptr<FileStorageEmitter> createXMLEmitter(FileStorage_API* fs)
+{
+ return makePtr<XMLEmitter>(fs);
+}
+
+Ptr<FileStorageParser> createXMLParser(FileStorage_API* fs)
+{
+ return makePtr<XMLParser>(fs);
+}
+
}
#include "precomp.hpp"
#include "persistence.hpp"
-#define CV_YML_INDENT 3
-#define CV_YML_INDENT_FLOW 1
+enum
+{
+ CV_YML_INDENT = 3,
+ CV_YML_INDENT_FLOW = 1
+};
-/****************************************************************************************\
-* YAML Parser *
-\****************************************************************************************/
+namespace cv
+{
-static char* icvYMLSkipSpaces( CvFileStorage* fs, char* ptr, int min_indent, int max_comment_indent )
+class YAMLEmitter : public FileStorageEmitter
{
- for(;;)
+public:
+ YAMLEmitter(FileStorage_API* _fs) : fs(_fs)
{
- while( *ptr == ' ' )
- ptr++;
- if( *ptr == '#' )
- {
- if( ptr - fs->buffer_start > max_comment_indent )
- return ptr;
- *ptr = '\0';
- }
- else if( cv_isprint(*ptr) )
+ }
+ virtual ~YAMLEmitter() {}
+
+ FStructData startWriteStruct(const FStructData& parent, const char* key,
+ int struct_flags, const char* type_name=0)
+ {
+ char buf[CV_FS_MAX_LEN + 1024];
+ const char* data = 0;
+
+ if ( type_name && *type_name == '\0' )
+ type_name = 0;
+
+ struct_flags = (struct_flags & (FileNode::TYPE_MASK|FileNode::FLOW)) | FileNode::EMPTY;
+ if( !FileNode::isCollection(struct_flags))
+ CV_Error( cv::Error::StsBadArg,
+ "Some collection type - FileNode::SEQ or FileNode::MAP, must be specified" );
+
+ if (type_name && memcmp(type_name, "binary", 6) == 0)
{
- if( ptr - fs->buffer_start < min_indent )
- CV_PARSE_ERROR( "Incorrect indentation" );
- break;
+ /* reset struct flag. in order not to print ']' */
+ struct_flags = FileNode::SEQ;
+ sprintf(buf, "!!binary |");
+ data = buf;
}
- else if( *ptr == '\0' || *ptr == '\n' || *ptr == '\r' )
+ else if( FileNode::isFlow(struct_flags))
{
- int max_size = (int)(fs->buffer_end - fs->buffer_start);
- ptr = icvGets( fs, fs->buffer_start, max_size );
- if( !ptr )
- {
- // emulate end of stream
- ptr = fs->buffer_start;
- ptr[0] = ptr[1] = ptr[2] = '.';
- ptr[3] = '\0';
- fs->dummy_eof = 1;
- break;
- }
+ char c = FileNode::isMap(struct_flags) ? '{' : '[';
+ struct_flags |= FileNode::FLOW;
+
+ if( type_name )
+ sprintf( buf, "!!%s %c", type_name, c );
else
{
- int l = (int)strlen(ptr);
- if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !icvEof(fs) )
- CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
+ buf[0] = c;
+ buf[1] = '\0';
}
-
- fs->lineno++; // FIXIT doesn't really work with long lines. It must be counted via '\n' or '\r' symbols, not the number of icvGets() calls.
+ data = buf;
+ }
+ else if( type_name )
+ {
+ sprintf( buf, "!!%s", type_name );
+ data = buf;
}
- else
- CV_PARSE_ERROR( *ptr == '\t' ? "Tabs are prohibited in YAML!" : "Invalid character" );
- }
-
- return ptr;
-}
+ writeScalar( key, data );
-static void icvYMLGetMultilineStringContent(CvFileStorage* fs, char* ptr, int indent, char* &beg, char* &end)
-{
- ptr = icvYMLSkipSpaces(fs, ptr, 0, INT_MAX);
- beg = ptr;
- end = ptr;
- if (fs->dummy_eof)
- return ; /* end of file */
-
- if (ptr - fs->buffer_start != indent)
- return ; /* end of string */
-
- /* find end */
- while(cv_isprint(*ptr)) /* no check for base64 string */
- ++ ptr;
- if (*ptr == '\0')
- CV_PARSE_ERROR("Unexpected end of line");
-
- end = ptr;
-}
+ FStructData fsd;
+ fsd.indent = parent.indent;
+ fsd.flags = struct_flags;
-static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileNode * node)
-{
- char * beg = 0;
- char * end = 0;
+ if( !FileNode::isFlow(parent.flags) )
+ fsd.indent += CV_YML_INDENT + FileNode::isFlow(struct_flags);
- icvYMLGetMultilineStringContent(fs, ptr, indent, beg, end);
- if (beg >= end)
- return end; // CV_PARSE_ERROR("Empty Binary Data");
+ return fsd;
+ }
- /* calc (decoded) total_byte_size from header */
- std::string dt;
+ void endWriteStruct(const FStructData& current_struct)
{
- if (end - beg < static_cast<int>(base64::ENCODED_HEADER_SIZE))
- CV_PARSE_ERROR("Unrecognized Base64 header");
+ char* ptr;
- std::vector<char> header(base64::HEADER_SIZE + 1, ' ');
- base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE);
- if ( !base64::read_base64_header(header, dt) || dt.empty() )
- CV_PARSE_ERROR("Invalid `dt` in Base64 header");
+ int struct_flags = current_struct.flags;
- beg += base64::ENCODED_HEADER_SIZE;
+ if( FileNode::isFlow(struct_flags) )
+ {
+ ptr = fs->bufferPtr();
+ if( ptr > fs->bufferStart() + current_struct.indent && !FileNode::isEmptyCollection(struct_flags) )
+ *ptr++ = ' ';
+ *ptr++ = FileNode::isMap(struct_flags) ? '}' : ']';
+ fs->setBufferPtr(ptr);
+ }
+ else if( FileNode::isEmptyCollection(struct_flags) )
+ {
+ ptr = fs->flush();
+ memcpy( ptr, FileNode::isMap(struct_flags) ? "{}" : "[]", 2 );
+ fs->setBufferPtr(ptr + 2);
+ }
+ /*
+ if( !FileNode::isFlow(parent_flags) )
+ fs->struct_indent -= CV_YML_INDENT + FileNode::isFlow(struct_flags);
- assert( fs->struct_indent >= 0 );*/
++ CV_Assert( fs->struct_indent >= 0 );*/
}
- /* get all Base64 data */
- std::string base64_buffer;
- base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE );
- while( beg < end )
- {
- base64_buffer.append( beg, end );
- beg = end;
- icvYMLGetMultilineStringContent( fs, beg, indent, beg, end );
- }
- if ( base64_buffer.empty() ||
- !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) )
- CV_PARSE_ERROR( "Invalid Base64 data." );
-
- /* buffer for decoded data(exclude header) */
- std::vector<uchar> binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) );
- int total_byte_size = static_cast<int>(
- base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false )
- );
+ void write(const char* key, int value)
{
- base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() );
- const uchar * buffer_beg = reinterpret_cast<const uchar *>( base64_buffer.data() );
- const uchar * buffer_end = buffer_beg + base64_buffer.size();
- parser.read( buffer_beg, buffer_end );
- parser.flush();
+ char buf[128];
+ writeScalar( key, fs::itoa( value, buf, 10 ));
}
- node->tag = CV_NODE_NONE;
- int struct_flags = CV_NODE_FLOW | CV_NODE_SEQ;
- /* after icvFSCreateCollection, node->tag == struct_flags */
- icvFSCreateCollection(fs, struct_flags, node);
- base64::make_seq(fs, binary_buffer.data(), total_byte_size, dt.c_str(), *node->data.seq);
-
- if (fs->dummy_eof) {
- /* end of file */
- return fs->buffer_start;
- } else {
- /* end of line */
- return end;
+ void write( const char* key, double value )
+ {
+ char buf[128];
+ writeScalar( key, fs::doubleToString( buf, value, false ));
}
-}
-
-
-static char* icvYMLParseKey( CvFileStorage* fs, char* ptr, CvFileNode* map_node, CvFileNode** value_placeholder )
-{
- char c;
- char *endptr = ptr - 1, *saveptr;
- CvStringHashNode* str_hash_node;
-
- if( *ptr == '-' )
- CV_PARSE_ERROR( "Key may not start with \'-\'" );
-
- do c = *++endptr;
- while( cv_isprint(c) && c != ':' );
-
- if( c != ':' )
- CV_PARSE_ERROR( "Missing \':\'" );
-
- saveptr = endptr + 1;
- do c = *--endptr;
- while( c == ' ' );
-
- ++endptr;
- if( endptr == ptr )
- CV_PARSE_ERROR( "An empty key" );
-
- str_hash_node = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );
- *value_placeholder = cvGetFileNode( fs, map_node, str_hash_node, 1 );
- ptr = saveptr;
-
- return ptr;
-}
+ void write(const char* key, const char* str, bool quote)
+ {
+ char buf[CV_FS_MAX_LEN*4+16];
+ char* data = (char*)str;
+ int i, len;
-static char*
-icvYMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
- int parent_flags, int min_indent )
-{
- char buf[CV_FS_MAX_LEN + 1024] = {0};
- char* endptr = 0;
- char c = ptr[0], d = ptr[1];
- int is_parent_flow = CV_NODE_IS_FLOW(parent_flags);
- int value_type = CV_NODE_NONE;
- int len;
- bool is_binary_string = false;
+ if( !str )
+ CV_Error( cv::Error::StsNullPtr, "Null string pointer" );
- memset( node, 0, sizeof(*node) );
+ len = (int)strlen(str);
+ if( len > CV_FS_MAX_LEN )
+ CV_Error( cv::Error::StsBadArg, "The written string is too long" );
- if( c == '!' ) // handle explicit type specification
- {
- if( d == '!' || d == '^' )
+ if( quote || len == 0 || str[0] != str[len-1] || (str[0] != '\"' && str[0] != '\'') )
{
- ptr++;
- value_type |= CV_NODE_USER;
- }
- if ( d == '<') //support of full type heading from YAML 1.2
- {
- const char* yamlTypeHeading = "<tag:yaml.org,2002:";
- const size_t headingLength = strlen(yamlTypeHeading);
-
- char* typeEndPtr = ++ptr;
+ int need_quote = quote || len == 0 || str[0] == ' ';
+ data = buf;
+ *data++ = '\"';
+ for( i = 0; i < len; i++ )
+ {
+ char c = str[i];
- do d = *++typeEndPtr;
- while( cv_isprint(d) && d != ' ' && d != '>' );
+ if( !need_quote && !cv_isalnum(c) && c != '_' && c != ' ' && c != '-' &&
+ c != '(' && c != ')' && c != '/' && c != '+' && c != ';' )
+ need_quote = 1;
- if ( d == '>' && (size_t)(typeEndPtr - ptr) > headingLength )
- {
- if ( memcmp(ptr, yamlTypeHeading, headingLength) == 0 )
+ if( !cv_isalnum(c) && (!cv_isprint(c) || c == '\\' || c == '\'' || c == '\"') )
{
- value_type |= CV_NODE_USER;
- *typeEndPtr = ' ';
- ptr += headingLength - 1;
+ *data++ = '\\';
+ if( cv_isprint(c) )
+ *data++ = c;
+ else if( c == '\n' )
+ *data++ = 'n';
+ else if( c == '\r' )
+ *data++ = 'r';
+ else if( c == '\t' )
+ *data++ = 't';
+ else
+ {
+ sprintf( data, "x%02x", c );
+ data += 3;
+ }
}
+ else
+ *data++ = c;
}
+ if( !need_quote && (cv_isdigit(str[0]) ||
+ str[0] == '+' || str[0] == '-' || str[0] == '.' ))
+ need_quote = 1;
+
+ if( need_quote )
+ *data++ = '\"';
+ *data++ = '\0';
+ data = buf + !need_quote;
}
- endptr = ptr++;
- do d = *++endptr;
- while( cv_isprint(d) && d != ' ' );
- len = (int)(endptr - ptr);
- if( len == 0 )
- CV_PARSE_ERROR( "Empty type name" );
- d = *endptr;
- *endptr = '\0';
+ writeScalar( key, data);
+ }
- if( len == 3 && !CV_NODE_IS_USER(value_type) )
+ void writeScalar(const char* key, const char* data)
+ {
+ fs->check_if_write_struct_is_delayed(false);
+ if ( fs->get_state_of_writing_base64() == FileStorage_API::Uncertain )
{
- if( memcmp( ptr, "str", 3 ) == 0 )
- value_type = CV_NODE_STRING;
- else if( memcmp( ptr, "int", 3 ) == 0 )
- value_type = CV_NODE_INT;
- else if( memcmp( ptr, "seq", 3 ) == 0 )
- value_type = CV_NODE_SEQ;
- else if( memcmp( ptr, "map", 3 ) == 0 )
- value_type = CV_NODE_MAP;
+ fs->switch_to_Base64_state( FileStorage_API::NotUse );
}
- else if( len == 5 && !CV_NODE_IS_USER(value_type) )
+ else if ( fs->get_state_of_writing_base64() == FileStorage_API::InUse )
{
- if( memcmp( ptr, "float", 5 ) == 0 )
- value_type = CV_NODE_REAL;
+ CV_Error( cv::Error::StsError, "At present, output Base64 data only." );
}
- else if (len == 6 && CV_NODE_IS_USER(value_type))
- {
- if( memcmp( ptr, "binary", 6 ) == 0 ) {
- value_type = CV_NODE_SEQ;
- is_binary_string = true;
- /* for ignore '|' */
+ int i, keylen = 0;
+ int datalen = 0;
+ char* ptr;
- /**** operation with endptr ****/
- *endptr = d;
+ FStructData& current_struct = fs->getCurrentStruct();
- do {
- d = *++endptr;
- if (d == '|')
- break;
- } while (d == ' ');
+ int struct_flags = current_struct.flags;
- d = *++endptr;
- *endptr = '\0';
- }
- }
- else if( CV_NODE_IS_USER(value_type) )
+ if( key && key[0] == '\0' )
+ key = 0;
+
+ if( FileNode::isCollection(struct_flags) )
{
- node->info = cvFindType( ptr );
- if( !node->info )
- node->tag &= ~CV_NODE_USER;
+ if( (FileNode::isMap(struct_flags) ^ (key != 0)) )
+ CV_Error( cv::Error::StsBadArg, "An attempt to add element without a key to a map, "
+ "or add element with key to sequence" );
}
-
- *endptr = d;
- ptr = icvYMLSkipSpaces( fs, endptr, min_indent, INT_MAX );
-
- c = *ptr;
-
- if( !CV_NODE_IS_USER(value_type) )
+ else
{
- if (value_type == CV_NODE_STRING && c != '\'' && c != '\"')
- goto force_string;
- if( value_type == CV_NODE_INT )
- goto force_int;
- if( value_type == CV_NODE_REAL )
- goto force_real;
+ fs->setNonEmpty();
+ struct_flags = FileNode::EMPTY | (key ? FileNode::MAP : FileNode::SEQ);
}
- }
- if (is_binary_string)
- {
- /* for base64 string */
- int indent = static_cast<int>(ptr - fs->buffer_start);
- ptr = icvYMLParseBase64(fs, ptr, indent, node);
- }
- else if( cv_isdigit(c) ||
- ((c == '-' || c == '+') && (cv_isdigit(d) || d == '.')) ||
- (c == '.' && cv_isalnum(d))) // a number
- {
- double fval;
- int ival;
- endptr = ptr + (c == '-' || c == '+');
- while( cv_isdigit(*endptr) )
- endptr++;
- if( *endptr == '.' || *endptr == 'e' )
+ if( key )
{
-force_real:
- fval = icv_strtod( fs, ptr, &endptr );
- /*if( endptr == ptr || cv_isalpha(*endptr) )
- icvProcessSpecialDouble( fs, endptr, &fval, &endptr ));*/
+ keylen = (int)strlen(key);
+ if( keylen == 0 )
+ CV_Error( cv::Error::StsBadArg, "The key is an empty" );
- node->tag = CV_NODE_REAL;
- node->data.f = fval;
- }
- else
- {
-force_int:
- ival = (int)strtol( ptr, &endptr, 0 );
- node->tag = CV_NODE_INT;
- node->data.i = ival;
+ if( keylen > CV_FS_MAX_LEN )
+ CV_Error( cv::Error::StsBadArg, "The key is too long" );
}
- if( !endptr || endptr == ptr )
- CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
+ if( data )
+ datalen = (int)strlen(data);
- ptr = endptr;
- CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
- }
- else if( c == '\'' || c == '\"' ) // an explicit string
- {
- node->tag = CV_NODE_STRING;
- if( c == '\'' )
- for( len = 0; len < CV_FS_MAX_LEN; )
+ if( FileNode::isFlow(struct_flags) )
+ {
+ ptr = fs->bufferPtr();
+ if( !FileNode::isEmptyCollection(struct_flags) )
+ *ptr++ = ',';
+ int new_offset = (int)(ptr - fs->bufferStart()) + keylen + datalen;
+ if( new_offset > fs->wrapMargin() && new_offset - current_struct.indent > 10 )
{
- c = *++ptr;
- if( cv_isalnum(c) || (c != '\'' && cv_isprint(c)))
- buf[len++] = c;
- else if( c == '\'' )
- {
- c = *++ptr;
- if( c != '\'' )
- break;
- buf[len++] = c;
- }
- else
- CV_PARSE_ERROR( "Invalid character" );
+ fs->setBufferPtr(ptr);
+ ptr = fs->flush();
}
+ else
+ *ptr++ = ' ';
+ }
else
- for( len = 0; len < CV_FS_MAX_LEN; )
+ {
+ ptr = fs->flush();
+ if( !FileNode::isMap(struct_flags) )
{
- c = *++ptr;
- if( cv_isalnum(c) || (c != '\\' && c != '\"' && cv_isprint(c)))
- buf[len++] = c;
- else if( c == '\"' )
- {
- ++ptr;
- break;
- }
- else if( c == '\\' )
- {
- d = *++ptr;
- if( d == '\'' )
- buf[len++] = d;
- else if( d == '\"' || d == '\\' || d == '\'' )
- buf[len++] = d;
- else if( d == 'n' )
- buf[len++] = '\n';
- else if( d == 'r' )
- buf[len++] = '\r';
- else if( d == 't' )
- buf[len++] = '\t';
- else if( d == 'x' || (cv_isdigit(d) && d < '8') )
- {
- int val, is_hex = d == 'x';
- c = ptr[3];
- ptr[3] = '\0';
- val = (int)strtol( ptr + is_hex, &endptr, is_hex ? 8 : 16 );
- ptr[3] = c;
- if( endptr == ptr + is_hex )
- buf[len++] = 'x';
- else
- {
- buf[len++] = (char)val;
- ptr = endptr;
- }
- }
- }
- else
- CV_PARSE_ERROR( "Invalid character" );
+ *ptr++ = '-';
+ if( data )
+ *ptr++ = ' ';
}
+ }
- if( len >= CV_FS_MAX_LEN )
- CV_PARSE_ERROR( "Too long string literal" );
-
- node->data.str = cvMemStorageAllocString( fs->memstorage, buf, len );
- }
- else if( c == '[' || c == '{' ) // collection as a flow
- {
- int new_min_indent = min_indent + !is_parent_flow;
- int struct_flags = CV_NODE_FLOW + (c == '{' ? CV_NODE_MAP : CV_NODE_SEQ);
- bool is_simple = true;
-
- icvFSCreateCollection( fs, CV_NODE_TYPE(struct_flags) +
- (node->info ? CV_NODE_USER : 0), node );
-
- d = c == '[' ? ']' : '}';
-
- for( ++ptr ;;)
+ if( key )
{
- CvFileNode* elem = 0;
+ if( !cv_isalpha(key[0]) && key[0] != '_' )
+ CV_Error( cv::Error::StsBadArg, "Key must start with a letter or _" );
- ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );
- if( *ptr == '}' || *ptr == ']' )
- {
- if( *ptr != d )
- CV_PARSE_ERROR( "The wrong closing bracket" );
- ptr++;
- break;
- }
+ ptr = fs->resizeWriteBuffer( ptr, keylen );
- if( node->data.seq->total != 0 )
+ for( i = 0; i < keylen; i++ )
{
- if( *ptr != ',' )
- CV_PARSE_ERROR( "Missing , between the elements" );
- ptr = icvYMLSkipSpaces( fs, ptr + 1, new_min_indent, INT_MAX );
- }
+ char c = key[i];
- if( CV_NODE_IS_MAP(struct_flags) )
- {
- ptr = icvYMLParseKey( fs, ptr, node, &elem );
- ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );
+ ptr[i] = c;
+ if( !cv_isalnum(c) && c != '-' && c != '_' && c != ' ' )
+ CV_Error( cv::Error::StsBadArg, "Key names may only contain alphanumeric characters [a-zA-Z0-9], '-', '_' and ' '" );
}
- else
- {
- if( *ptr == ']' )
- break;
- elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
- }
- CV_Assert(elem);
- ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, new_min_indent );
- if( CV_NODE_IS_MAP(struct_flags) )
- elem->tag |= CV_NODE_NAMED;
- is_simple = is_simple && !CV_NODE_IS_COLLECTION(elem->tag);
+
+ ptr += keylen;
+ *ptr++ = ':';
+ if( !FileNode::isFlow(struct_flags) && data )
+ *ptr++ = ' ';
}
- node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;
- }
- else
- {
- int indent, struct_flags;
- bool is_simple;
- if( is_parent_flow || c != '-' )
+ if( data )
{
- // implicit (one-line) string or nested block-style collection
- if( !is_parent_flow )
- {
- if( c == '?' )
- CV_PARSE_ERROR( "Complex keys are not supported" );
- if( c == '|' || c == '>' )
- CV_PARSE_ERROR( "Multi-line text literals are not supported" );
- }
+ ptr = fs->resizeWriteBuffer( ptr, datalen );
+ memcpy( ptr, data, datalen );
+ ptr += datalen;
+ }
-force_string:
- endptr = ptr - 1;
+ fs->setBufferPtr(ptr);
+ current_struct.flags &= ~FileNode::EMPTY;
+ }
- do c = *++endptr;
- while( cv_isprint(c) &&
- (!is_parent_flow || (c != ',' && c != '}' && c != ']')) &&
- (is_parent_flow || c != ':' || value_type == CV_NODE_STRING));
+ void writeComment(const char* comment, bool eol_comment)
+ {
+ if( !comment )
+ CV_Error( cv::Error::StsNullPtr, "Null comment" );
- if( endptr == ptr )
- CV_PARSE_ERROR( "Invalid character" );
+ int len = (int)strlen(comment);
+ const char* eol = strchr(comment, '\n');
+ bool multiline = eol != 0;
+ char* ptr = fs->bufferPtr();
- if( is_parent_flow || c != ':' )
- {
- char* str_end = endptr;
- node->tag = CV_NODE_STRING;
- // strip spaces in the end of string
- do c = *--str_end;
- while( str_end > ptr && c == ' ' );
- str_end++;
- node->data.str = cvMemStorageAllocString( fs->memstorage, ptr, (int)(str_end - ptr) );
- ptr = endptr;
- return ptr;
- }
- struct_flags = CV_NODE_MAP;
- }
+ if( !eol_comment || multiline ||
+ fs->bufferEnd() - ptr < len || ptr == fs->bufferStart() )
+ ptr = fs->flush();
else
- struct_flags = CV_NODE_SEQ;
-
- icvFSCreateCollection( fs, struct_flags +
- (node->info ? CV_NODE_USER : 0), node );
-
- indent = (int)(ptr - fs->buffer_start);
- is_simple = true;
+ *ptr++ = ' ';
- for(;;)
+ while( comment )
{
- CvFileNode* elem = 0;
-
- if( CV_NODE_IS_MAP(struct_flags) )
+ *ptr++ = '#';
+ *ptr++ = ' ';
+ if( eol )
{
- ptr = icvYMLParseKey( fs, ptr, node, &elem );
+ ptr = fs->resizeWriteBuffer( ptr, (int)(eol - comment) + 1 );
+ memcpy( ptr, comment, eol - comment + 1 );
+ fs->setBufferPtr(ptr + (eol - comment));
+ comment = eol + 1;
+ eol = strchr( comment, '\n' );
}
else
{
#include "opencv2/core/ocl.hpp"
#endif
--#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <limits.h>
inline float calculate(float x) const
{
- return x >= 0.f ? x : exp(x) - 1.f;
+ return x >= 0.f ? x : alpha * (exp(x) - 1.f);
+ }
+
+ inline void setKernelParams(ocl::Kernel& kernel) const
+ {
+ kernel.set(3, alpha);
}
+#ifdef HAVE_CUDA
+ Ptr<BackendNode> initCUDA(int target, csl::Stream stream)
+ {
+ return make_cuda_node<cuda4dnn::ELUOp>(target, stream);
+ }
+#endif
+
#ifdef HAVE_HALIDE
void attachHalide(const Halide::Expr& input, Halide::Func& top)
{
#endif
#if CV_TRY_AVX
if( useAVX )
- opt_AVX::fastGEMM1T( sptr, wptr, wstep, biasptr, dptr, nw, vecsize);
+ opt_AVX::fastGEMM1T( sptr, wptr, wstep, biasptr, dptr, nw, vecsize_aligned);
else
#endif
+ #if CV_TRY_RVV
+ if( useRVV )
+ opt_RVV::fastGEMM1T( sptr, wptr, wstep, biasptr, dptr, nw, vecsize);
+ else
+ #endif
{
int i = 0;
}
}
+ void setCeilMode(LayerParams& layerParams)
+ {
+ // auto_pad attribute is deprecated and uses ceil
+ if (layerParams.has("pad_mode"))
+ {
+ layerParams.set("ceil_mode", true);
+ }
+ else if (!layerParams.has("ceil_mode"))
+ {
+ layerParams.set("ceil_mode", false);
+ }
+ }
+
void ONNXImporter::parseMaxPool(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
{
- layerParams.type = "Pooling";
+ int depth = layerParams.get<int>("depth", CV_32F);
+ layerParams.type = (depth == CV_8S) ? "PoolingInt8" : "Pooling";
layerParams.set("pool", "MAX");
- layerParams.set("ceil_mode", layerParams.has("pad_mode"));
+ setCeilMode(layerParams);
addLayer(layerParams, node_proto);
}
{
layerParams.set("num_split", node_proto.output_size());
}
- layerParams.type = "Slice";
+ int depth = layerParams.get<int>("depth", CV_32F);
+ layerParams.type = (depth == CV_8S) ? "SliceInt8" : "Slice";
+ layerParams.set("axis", layerParams.get<float>("axis", 0));
addLayer(layerParams, node_proto);
}
void ONNXImporter::parseTranspose(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
{
- layerParams.type = "Permute";
+ int depth = layerParams.get<int>("depth", CV_32F);
+ layerParams.type = (depth == CV_8S) ? "PermuteInt8" : "Permute";
replaceLayerParam(layerParams, "perm", "order");
+ if (!layerParams.has("order")) {
+ MatShape inpShape = outShapes[node_proto.input(0)];
+ size_t dims = inpShape.size();
+ std::vector<int> perm(dims);
+ for (size_t d = 0; d < dims; ++d)
+ {
+ perm[d] = static_cast<int>(dims - 1 - d);
+ }
+ layerParams.set("order", DictValue::arrayInt(perm.data(), perm.size()));
+ }
CV_Assert(node_proto.input_size() == 1);
if (constBlobs.find(node_proto.input(0)) != constBlobs.end())
l1 = 2e-4;
lInf = 1e-3;
}
- else if(target == DNN_TARGET_CUDA_FP16)
+ if (target == DNN_TARGET_MYRIAD)
+ {
+ l1 = 0.001;
+ lInf = 0.001;
+ }
++ if(target == DNN_TARGET_CUDA_FP16)
+ {
+ l1 = 0.0002;
+ lInf = 0.0007;
+ }
normAssert(ref, out, "", l1, lInf);
}
Mat input(4, &sz[0], CV_32F);
double l1 = 0.0;
- else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && targetId == DNN_TARGET_OPENCL_FP16)
+ double lInf = 0.0;
+ #if defined(INF_ENGINE_RELEASE)
+ if (targetId == DNN_TARGET_MYRIAD)
+ {
+ l1 = 0.015;
+ lInf = 0.025;
+ }
- test(lp, input, backendId, targetId, false, true, l1);
++ if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && targetId == DNN_TARGET_OPENCL_FP16)
+ {
+ l1 = 0.01;
+ }
+ #endif
+ if (targetId == DNN_TARGET_CUDA_FP16)
+ l1 = 0.015;
++
+ test(lp, input, backendId, targetId, false, l1, lInf);
}
INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, FullyConnected, Combine(
TEST_P(Test_ONNX_layers, ReduceMean3D)
{
- if (backend == DNN_BACKEND_CUDA)
- {
- // ok
- }
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
- else if (target != DNN_TARGET_CPU)
- throw SkipTestException("Only CPU is supported");
+ #endif
+ if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+ throw SkipTestException("Only CPU is supported"); // FIXIT use tags
testONNXModels("reduce_mean3d");
}
TEST_P(Test_ONNX_layers, Eltwise3D)
{
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
- applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
-- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
++ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
+ #endif
testONNXModels("eltwise3d");
}
TEST_P(Test_ONNX_layers, MaxPooling3D)
{
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
- applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
- if (backend == DNN_BACKEND_CUDA)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
- // ok
+ // accuracy
+ if (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)
+ applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
+ CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
+ );
+ // IE exception: [ GENERAL_ERROR ] AssertionFailed: !expired()
+ if (target == DNN_TARGET_MYRIAD)
+ applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
}
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
- else if (target != DNN_TARGET_CPU)
- throw SkipTestException("Only CPU is supported");
+ #endif
+ if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+ throw SkipTestException("Only CPU is supported"); // FIXIT use tags
+
testONNXModels("max_pool3d", npy, 0, 0, false, false);
}
TEST_P(Test_ONNX_layers, AvePooling3D)
{
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
- applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
- if (backend == DNN_BACKEND_CUDA)
- {
- // ok
- }
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
- else if (target != DNN_TARGET_CPU)
- throw SkipTestException("Only CPU is supported");
+ #endif
+ if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+ throw SkipTestException("Only CPU is supported"); // FIXIT use tags
+
testONNXModels("ave_pool3d");
}
TEST_P(Test_ONNX_layers, PoolConv3D)
{
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
- applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
- if (backend == DNN_BACKEND_CUDA)
- {
- // ok
- }
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
- else if (target != DNN_TARGET_CPU)
- throw SkipTestException("Only CPU is supported");
+ #endif
+ if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+ throw SkipTestException("Only CPU is supported"); // FIXIT use tags
+
testONNXModels("pool_conv_3d");
}
TEST_P(Test_ONNX_nets, Resnet34_kinetics)
{
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
- applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
- if (backend == DNN_BACKEND_CUDA)
- {
- // ok
- }
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
- else if (target != DNN_TARGET_CPU)
- throw SkipTestException("Only CPU is supported");
+ #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
+ {
+ // IE exception: Function contains several inputs and outputs with one friendly name!
+ if (target == DNN_TARGET_MYRIAD)
+ applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
+ }
+ #endif
+ if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+ throw SkipTestException("Only CPU is supported"); // FIXIT use tags
String onnxmodel = findDataFile("dnn/resnet-34_kinetics.onnx", false);
Mat image0 = imread(findDataFile("dnn/dog416.png"));
net.setPreferableTarget(target);
// output range [-5, 11]
- float l1 = 0.0013, lInf = 0.009;
+ float l1 = 0.0013;
+ float lInf = 0.009;
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
+ {
+ l1 = 0.02;
+ lInf = 0.07;
+ }
+ if (target == DNN_TARGET_CUDA_FP16)
+ {
+ l1 = 0.01;
+ lInf = 0.06;
+ }
checkBackend(&input0, &ref0);
net.setInput(input0);
l1 = 0.041;
lInf = 0.33;
}
+ #if defined(INF_ENGINE_RELEASE)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
+ {
+ lInf = 0.0002;
+ }
+ #endif
+ else if (target == DNN_TARGET_CUDA_FP16)
+ {
+ l1 = 0.005;
+ lInf = 0.33;
+ }
+
runTensorFlowNet("slim_batch_norm", false, l1, lInf);
}
TEST_P(Test_TensorFlow_layers, MaxPooling3D)
{
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
- applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
- if (backend == DNN_BACKEND_CUDA)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
{
- // ok
+ // accuracy
+ if (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)
+ applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
+ CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
+ );
+ // IE exception: [ GENERAL_ERROR ] AssertionFailed: !expired()
+ if (target == DNN_TARGET_MYRIAD)
+ applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
}
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
- else if (target != DNN_TARGET_CPU)
- throw SkipTestException("Only CPU is supported");
+ #endif
+ if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+ throw SkipTestException("Only CPU is supported"); // FIXIT use tags
runTensorFlowNet("max_pool3d");
}
TEST_P(Test_TensorFlow_layers, AvePooling3D)
{
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
- applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
- if (backend == DNN_BACKEND_CUDA)
- {
- // ok
- }
- else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+ if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER); // Only CPU on DLIE backend is supported
- if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
+ else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // Only CPU on DLIE backend is supported
- else if (target != DNN_TARGET_CPU)
- throw SkipTestException("Only CPU is supported");
+ #endif
+ if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+ throw SkipTestException("Only CPU is supported"); // FIXIT use tags
runTensorFlowNet("ave_pool3d");
}
TEST_P(Test_TensorFlow_layers, lstm)
{
+ if(backend == DNN_BACKEND_CUDA)
+ applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); /* not supported */
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
TEST_P(Test_TensorFlow_layers, tf2_prelu)
{
++ if (backend == DNN_BACKEND_CUDA)
++ applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); // not supported; only across channels is supported
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
l1 = 0.046;
lInf = 0.023;
}
+ else if (target == DNN_TARGET_MYRIAD)
+ {
+ l1 = 0.02;
+ lInf = 0.05;
+ }
+ else if (target == DNN_TARGET_CUDA_FP16)
+ {
+ l1 = 0.0042;
+ lInf = 0.021;
+ }
// The OpenCL kernels use the native_ math functions which have
// implementation defined accuracy, so we use relaxed thresholds. See
// https://github.com/opencv/opencv/issues/9821 for more details.
}
}
-- //assert( pt.x == chain->origin.x && pt.y == chain->origin.y );
++ //CV_Assert( pt.x == chain->origin.x && pt.y == chain->origin.y );
if( method <= CV_CHAIN_APPROX_SIMPLE )
return cvEndWriteSeq( &writer );
if( !s[j] )
{
tmp[j] = 0;
-- //assert( lls[j] != 0 );
++ //CV_Assert( lls[j] != 0 );
}
else
{
size_t step = img.step;
Size size = img.size();
-- //assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U );
++ //CV_Assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U );
Size2l sizeScaled(((int64)size.width) << XY_SHIFT, ((int64)size.height) << XY_SHIFT);
if( !clipLine( sizeScaled, pt1, pt2 ))
int g_rshift = dst_bits == 16 ? 2 : 3;
int r_lshift = dst_bits == 16 ? 11 : 10;
-- //assert( (cn == 3 || cn == 4) && (dst_cn == 3 || (dst_cn == 2 && depth == CV_8U)) );
++ //CV_Assert( (cn == 3 || cn == 4) && (dst_cn == 3 || (dst_cn == 2 && depth == CV_8U)) );
for( i = 0; i < src.rows; i++ )
{
int g_lshift = dst_bits == 16 ? 2 : 3;
int r_rshift = dst_bits == 16 ? 11 : 10;
-- //assert( (cn == 3 || cn == 4) && (src_cn == 3 || (src_cn == 2 && depth == CV_8U)) );
++ //CV_Assert( (cn == 3 || cn == 4) && (src_cn == 3 || (src_cn == 2 && depth == CV_8U)) );
for( i = 0; i < src.rows; i++ )
{
((float*)ptr)[j] = (float)buffer[j];
break;
default:
-- assert(0);
++ CV_Assert(0);
}*/
cv::Mat src(1, cols*cn, CV_32F, &buffer[0]);
cv::Mat dst(1, cols*cn, depth, ptr);
step = aligned_step;
}
- if ( c->pix_fmt != input_pix_fmt ) {
+ AVPixelFormat sw_pix_fmt = c->pix_fmt;
+#if USE_AV_HW_CODECS
+ if (c->hw_frames_ctx)
+ sw_pix_fmt = ((AVHWFramesContext*)c->hw_frames_ctx->data)->sw_format;
+#endif
+ if ( sw_pix_fmt != input_pix_fmt ) {
- assert( input_picture );
+ CV_Assert( input_picture );
// let input_picture point to the raw data buffer of 'image'
_opencv_ffmpeg_av_image_fill_arrays(input_picture, (uint8_t *) data,
(AVPixelFormat)input_pix_fmt, width, height);
fourcc = supported_tag;
}
}
-#endif
// alloc memory for context
-#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
oc = avformat_alloc_context();
- assert (oc);
-#else
- oc = av_alloc_format_context();
-#endif
- CV_Assert (oc);
++ CV_Assert(oc);
/* set file name */
oc->oformat = fmt;