diff --git a/modules/video/doc/motion_analysis_and_object_tracking.rst b/modules/video/doc/motion_analysis_and_object_tracking.rst index ebb9290cc4..6db525a743 100644 --- a/modules/video/doc/motion_analysis_and_object_tracking.rst +++ b/modules/video/doc/motion_analysis_and_object_tracking.rst @@ -601,6 +601,8 @@ calcOpticalFlowSF ----------- Calculate an optical flow using "SimpleFlow" algorithm. +.. ocv:function:: void calcOpticalFlowSF( Mat& prev, Mat& next, Mat& flowX, Mat& flowY, int layers, int averaging_block_size, int max_flow) + .. ocv:function:: void calcOpticalFlowSF( Mat& prev, Mat& next, Mat& flowX, Mat& flowY, int layers, int averaging_block_size, int max_flow, double sigma_dist, double sigma_color, int postprocess_window, double sigma_dist_fix, double sigma_color_fix, double occ_thr, int upscale_averaging_radiud, double upscale_sigma_dist, double upscale_sigma_color, double speed_up_thr) :param prev: First 8-bit 3-channel image. diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index 6800c63373..2be030d76d 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -328,6 +328,13 @@ CV_EXPORTS_W Mat estimateRigidTransform( InputArray src, InputArray dst, bool fullAffine); //! computes dense optical flow using Simple Flow algorithm +CV_EXPORTS_W void calcOpticalFlowSF(Mat& from, + Mat& to, + Mat& flow, + int layers, + int averaging_block_size, + int max_flow); + CV_EXPORTS_W void calcOpticalFlowSF(Mat& from, Mat& to, Mat& flow, diff --git a/modules/video/src/simpleflow.cpp b/modules/video/src/simpleflow.cpp index 0cd320d6ee..59fafdcf3d 100644 --- a/modules/video/src/simpleflow.cpp +++ b/modules/video/src/simpleflow.cpp @@ -72,26 +72,27 @@ static void removeOcclusions(const Mat& flow, } static void wd(Mat& d, int top_shift, int bottom_shift, int left_shift, int right_shift, float sigma) { - const float factor = 1.0 / (2.0 * sigma * sigma); for (int dr = -top_shift, r = 0; dr <= bottom_shift; ++dr, ++r) { for (int dc = -left_shift, c = 0; dc <= right_shift; ++dc, ++c) { - d.at(r, c) = -(dr*dr + dc*dc) * factor; + d.at(r, c) = -(dr*dr + dc*dc); } } + d *= 1.0 / (2.0 * sigma * sigma); exp(d, d); } static void wc(const Mat& image, Mat& d, int r0, int c0, int top_shift, int bottom_shift, int left_shift, int right_shift, float sigma) { - const float factor = 1.0 / (2.0 * sigma * sigma); const Vec3b centeral_point = image.at(r0, c0); + int left_border = c0-left_shift, right_border = c0+right_shift; for (int dr = r0-top_shift, r = 0; dr <= r0+bottom_shift; ++dr, ++r) { const Vec3b *row = image.ptr(dr); float *d_row = d.ptr(r); - for (int dc = c0-left_shift, c = 0; dc <= c0+right_shift; ++dc, ++c) { - d_row[c] = -dist(centeral_point, row[dc]) * factor; + for (int dc = left_border, c = 0; dc <= right_border; ++dc, ++c) { + d_row[c] = -dist(centeral_point, row[dc]); } } + d *= 1.0 / (2.0 * sigma * sigma); exp(d, d); } @@ -163,7 +164,7 @@ static void calcOpticalFlowSingleScaleSF(const Mat& prev, Mat diff_storage(averaging_radius*2 + 1, averaging_radius*2 + 1, CV_32F); Mat w_full_window(averaging_radius*2 + 1, averaging_radius*2 + 1, CV_32F); Mat wd_full_window(averaging_radius*2 + 1, averaging_radius*2 + 1, CV_32F); - float w_full_window_sum; + float w_full_window_sum = 1e-9; Mat prev_extended; copyMakeBorder(prev, prev_extended, @@ -197,7 +198,7 @@ static void calcOpticalFlowSingleScaleSF(const Mat& prev, } bool first_flow_iteration = true; - float sum_e, min_e; + float sum_e = 0, min_e = 0; for (int u = min_row_shift; u <= max_row_shift; ++u) { for (int v = min_col_shift; v <= max_col_shift; ++v) { @@ -286,7 +287,7 @@ static Mat upscaleOpticalFlow(int new_rows, int averaging_radius, float sigma_dist, float sigma_color) { - crossBilateralFilter(flow, image, confidence, flow, averaging_radius, sigma_color, sigma_dist, false); + crossBilateralFilter(flow, image, confidence, flow, averaging_radius, sigma_color, sigma_dist, true); Mat new_flow; resize(flow, new_flow, Size(new_cols, new_rows), 0, 0, INTER_NEAREST); new_flow *= 2; @@ -495,13 +496,7 @@ void calcOpticalFlowSF(Mat& from, buildPyramidWithResizeMethod(from, pyr_from_images, layers - 1, INTER_CUBIC); buildPyramidWithResizeMethod(to, pyr_to_images, layers - 1, INTER_CUBIC); - if ((int)pyr_from_images.size() != layers) { - exit(1); - } - - if ((int)pyr_to_images.size() != layers) { - exit(1); - } + CV_Assert((int)pyr_from_images.size() == layers && (int)pyr_to_images.size() == layers); Mat first_from_image = pyr_from_images[layers - 1]; Mat first_to_image = pyr_to_images[layers - 1]; @@ -635,5 +630,15 @@ void calcOpticalFlowSF(Mat& from, mixChannels(&flow, 1, &resulted_flow, 1, from_to, 2); } +CV_EXPORTS_W void calcOpticalFlowSF(Mat& from, + Mat& to, + Mat& flow, + int layers, + int averaging_block_size, + int max_flow) { + calcOpticalFlowSF(from, to, flow, layers, averaging_block_size, max_flow, + 4.1, 25.5, 18, 55.0, 25.5, 0.35, 18, 55.0, 25.5, 10); +} + } diff --git a/modules/video/test/test_simpleflow.cpp b/modules/video/test/test_simpleflow.cpp index 050d595d1c..fe96e7004f 100644 --- a/modules/video/test/test_simpleflow.cpp +++ b/modules/video/test/test_simpleflow.cpp @@ -91,7 +91,7 @@ static bool isFlowCorrect(float u) { } static float calc_rmse(cv::Mat flow1, cv::Mat flow2) { - float sum; + float sum = 0; int counter = 0; const int rows = flow1.rows; const int cols = flow1.cols; @@ -116,8 +116,6 @@ static float calc_rmse(cv::Mat flow1, cv::Mat flow2) { } void CV_SimpleFlowTest::run(int) { - int code = cvtest::TS::OK; - const float MAX_RMSE = 0.6; const string frame1_path = ts->get_data_path() + "optflow/RubberWhale1.png"; const string frame2_path = ts->get_data_path() + "optflow/RubberWhale2.png"; @@ -171,9 +169,7 @@ void CV_SimpleFlowTest::run(int) { fclose(gt_flow_file); cv::Mat flow; - cv::calcOpticalFlowSF(frame1, frame2, - flow, - 3, 4, 2, 4.1, 25.5, 18, 55.0, 25.5, 0.35, 18, 55.0, 25.5, 10); + cv::calcOpticalFlowSF(frame1, frame2, flow, 3, 2, 4); float rmse = calc_rmse(flow_gt, flow); diff --git a/samples/cpp/simpleflow_demo.cpp b/samples/cpp/simpleflow_demo.cpp index 332df7821e..2727fe640a 100644 --- a/samples/cpp/simpleflow_demo.cpp +++ b/samples/cpp/simpleflow_demo.cpp @@ -135,7 +135,7 @@ static bool isFlowCorrect(float u) { } static float calc_rmse(Mat flow1, Mat flow2) { - float sum; + float sum = 0; int counter = 0; const int rows = flow1.rows; const int cols = flow1.cols;