Merge remote-tracking branch 'upstream/3.4' into merge-3.4
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Tue, 10 Mar 2020 22:44:14 +0000 (22:44 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Tue, 10 Mar 2020 22:49:51 +0000 (22:49 +0000)
1  2 
modules/core/include/opencv2/core/operations.hpp
modules/core/src/parallel.cpp
modules/dnn/CMakeLists.txt
modules/dnn/include/opencv2/dnn/version.hpp
modules/dnn/src/op_inf_engine.cpp
modules/dnn/test/test_darknet_importer.cpp
modules/ts/src/ts.cpp
modules/videoio/include/opencv2/videoio.hpp
modules/videoio/src/cap_ffmpeg_impl.hpp
modules/videoio/test/test_ffmpeg.cpp

Simple merge
Simple merge
index 152c8b2,0000000..f5c7424
mode 100644,000000..100644
--- /dev/null
@@@ -1,21 -1,0 +1,21 @@@
- #define OPENCV_DNN_API_VERSION 20200128
 +// This file is part of OpenCV project.
 +// It is subject to the license terms in the LICENSE file found in the top-level directory
 +// of this distribution and at http://opencv.org/license.html.
 +
 +#ifndef OPENCV_DNN_VERSION_HPP
 +#define OPENCV_DNN_VERSION_HPP
 +
 +/// Use with major OpenCV version only.
++#define OPENCV_DNN_API_VERSION 20200310
 +
 +#if !defined CV_DOXYGEN && !defined CV_STATIC_ANALYSIS && !defined CV_DNN_DONT_ADD_INLINE_NS
 +#define CV__DNN_INLINE_NS __CV_CAT(dnn4_v, OPENCV_DNN_API_VERSION)
 +#define CV__DNN_INLINE_NS_BEGIN namespace CV__DNN_INLINE_NS {
 +#define CV__DNN_INLINE_NS_END }
 +namespace cv { namespace dnn { namespace CV__DNN_INLINE_NS { } using namespace CV__DNN_INLINE_NS; }}
 +#else
 +#define CV__DNN_INLINE_NS_BEGIN
 +#define CV__DNN_INLINE_NS_END
 +#endif
 +
 +#endif  // OPENCV_DNN_VERSION_HPP
Simple merge
Simple merge
@@@ -1425,6 -1433,8 +1425,8 @@@ double CvCapture_FFMPEG::getProperty( i
          if (rawMode)
              return -1;
          break;
 -    case CV_FFMPEG_CAP_PROP_BITRATE:
++    case CAP_PROP_BITRATE:
+         return static_cast<double>(get_bitrate());
      default:
          break;
      }
@@@ -230,107 -353,288 +230,173 @@@ INSTANTIATE_TEST_CASE_P(/**/, videoio_s
  
  //==========================================================================
  
 -//////////////////////////////// Parallel VideoWriters and VideoCaptures ////////////////////////////////////
 -
 -class CreateVideoWriterInvoker :
 -    public ParallelLoopBody
 +static void generateFrame(Mat &frame, unsigned int i, const Point &center, const Scalar &color)
  {
 -public:
 -    const static Size FrameSize;
 -    static std::string TmpDirectory;
 +    frame = Scalar::all(i % 255);
 +    stringstream buf(ios::out);
 +    buf << "frame #" << i;
 +    putText(frame, buf.str(), Point(50, center.y), FONT_HERSHEY_SIMPLEX, 5.0, color, 5, CV_AA);
 +    circle(frame, center, i + 2, color, 2, CV_AA);
 +}
  
 -    CreateVideoWriterInvoker(std::vector< cv::Ptr<VideoWriter> >& _writers, std::vector<std::string>& _files) :
 -        writers(_writers), files(_files)
 +TEST(videoio_ffmpeg, parallel)
 +{
 +    if (!videoio_registry::hasBackend(CAP_FFMPEG))
 +        throw SkipTestException("FFmpeg backend was not found");
 +
 +    const int NUM = 4;
 +    const int GRAN = 4;
 +    const Range R(0, NUM);
 +    const Size sz(1020, 900);
 +    const int frameNum = 300;
 +    const Scalar color(Scalar::all(0));
 +    const Point center(sz.height / 2, sz.width / 2);
 +
 +    // Generate filenames
 +    vector<string> files;
 +    for (int i = 0; i < NUM; ++i)
      {
 +        ostringstream stream;
 +        stream << i << ".avi";
 +        files.push_back(tempfile(stream.str().c_str()));
      }
 -
 -    virtual void operator() (const Range& range) const CV_OVERRIDE
 +    // Write videos
      {
 -        for (int i = range.start; i != range.end; ++i)
 +        vector< Ptr<VideoWriter> > writers(NUM);
 +        auto makeWriters = [&](const Range &r)
          {
 -            std::ostringstream stream;
 -            stream << i << ".avi";
 -            std::string fileName = tempfile(stream.str().c_str());
 -
 -            files[i] = fileName;
 -            writers[i] = makePtr<VideoWriter>(fileName, CAP_FFMPEG, VideoWriter::fourcc('X','V','I','D'), 25.0f, FrameSize);
 -
 -            CV_Assert(writers[i]->isOpened());
 +            for (int i = r.start; i != r.end; ++i)
 +                writers[i] = makePtr<VideoWriter>(files[i],
 +                                                  CAP_FFMPEG,
 +                                                  VideoWriter::fourcc('X','V','I','D'),
 +                                                  25.0f,
 +                                                  sz);
 +        };
 +        parallel_for_(R, makeWriters, GRAN);
 +        for(int i = 0; i < NUM; ++i)
 +        {
 +            ASSERT_TRUE(writers[i]);
 +            ASSERT_TRUE(writers[i]->isOpened());
          }
 -    }
 -
 -private:
 -    std::vector< cv::Ptr<VideoWriter> >& writers;
 -    std::vector<std::string>& files;
 -};
 -
 -std::string CreateVideoWriterInvoker::TmpDirectory;
 -const Size CreateVideoWriterInvoker::FrameSize(1020, 900);
 -
 -class WriteVideo_Invoker :
 -    public ParallelLoopBody
 -{
 -public:
 -    enum { FrameCount = 300 };
 -
 -    static const Scalar ObjectColor;
 -    static const Point Center;
 -
 -    WriteVideo_Invoker(const std::vector< cv::Ptr<VideoWriter> >& _writers) :
 -        ParallelLoopBody(), writers(&_writers)
 -    {
 -    }
 -
 -    static void GenerateFrame(Mat& frame, unsigned int i)
 -    {
 -        frame = Scalar::all(i % 255);
 -
 -        std::string text = to_string(i);
 -        putText(frame, text, Point(50, Center.y), FONT_HERSHEY_SIMPLEX, 5.0, ObjectColor, 5, CV_AA);
 -        circle(frame, Center, i + 2, ObjectColor, 2, CV_AA);
 -    }
 -
 -    virtual void operator() (const Range& range) const CV_OVERRIDE
 -    {
 -        for (int j = range.start; j < range.end; ++j)
 +        auto writeFrames = [&](const Range &r)
          {
 -            VideoWriter* writer = writers->operator[](j);
 -            CV_Assert(writer != NULL);
 -            CV_Assert(writer->isOpened());
 -
 -            Mat frame(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
 -            for (unsigned int i = 0; i < FrameCount; ++i)
 +            for (int j = r.start; j < r.end; ++j)
              {
 -                GenerateFrame(frame, i);
 -                writer->operator<< (frame);
 +                Mat frame(sz, CV_8UC3);
 +                for (int i = 0; i < frameNum; ++i)
 +                {
 +                    generateFrame(frame, i, center, color);
 +                    writers[j]->write(frame);
 +                }
              }
 -        }
 -    }
 -
 -protected:
 -    static std::string to_string(unsigned int i)
 -    {
 -        std::stringstream stream(std::ios::out);
 -        stream << "frame #" << i;
 -        return stream.str();
 -    }
 -
 -private:
 -    const std::vector< cv::Ptr<VideoWriter> >* writers;
 -};
 -
 -const Scalar WriteVideo_Invoker::ObjectColor(Scalar::all(0));
 -const Point WriteVideo_Invoker::Center(CreateVideoWriterInvoker::FrameSize.height / 2,
 -    CreateVideoWriterInvoker::FrameSize.width / 2);
 -
 -class CreateVideoCaptureInvoker :
 -    public ParallelLoopBody
 -{
 -public:
 -    CreateVideoCaptureInvoker(std::vector< cv::Ptr<VideoCapture> >& _readers, const std::vector<std::string>& _files) :
 -        ParallelLoopBody(), readers(&_readers), files(&_files)
 -    {
 +        };
 +        parallel_for_(R, writeFrames, GRAN);
      }
 -
 -    virtual void operator() (const Range& range) const CV_OVERRIDE
 +    // Read videos
      {
 -        for (int i = range.start; i != range.end; ++i)
 +        vector< Ptr<VideoCapture> > readers(NUM);
 +        auto makeCaptures = [&](const Range &r)
          {
 -            readers->operator[](i) = makePtr<VideoCapture>(files->operator[](i), CAP_FFMPEG);
 -            CV_Assert(readers->operator[](i)->isOpened());
 +            for (int i = r.start; i != r.end; ++i)
 +                readers[i] = makePtr<VideoCapture>(files[i], CAP_FFMPEG);
 +        };
 +        parallel_for_(R, makeCaptures, GRAN);
 +        for(int i = 0; i < NUM; ++i)
 +        {
 +            ASSERT_TRUE(readers[i]);
 +            ASSERT_TRUE(readers[i]->isOpened());
          }
 -    }
 -private:
 -    std::vector< cv::Ptr<VideoCapture> >* readers;
 -    const std::vector<std::string>* files;
 -};
 -
 -class ReadImageAndTest :
 -    public ParallelLoopBody
 -{
 -public:
 -    ReadImageAndTest(const std::vector< cv::Ptr<VideoCapture> >& _readers, cvtest::TS* _ts) :
 -        ParallelLoopBody(), readers(&_readers), ts(_ts)
 -    {
 -    }
 -
 -    virtual void operator() (const Range& range) const CV_OVERRIDE
 -    {
 -        for (int j = range.start; j < range.end; ++j)
 +        auto readFrames = [&](const Range &r)
          {
 -            VideoCapture* capture = readers->operator[](j).get();
 -            CV_Assert(capture != NULL);
 -            CV_Assert(capture->isOpened());
 -
 -            const static double eps = 23.0;
 -            unsigned int frameCount = static_cast<unsigned int>(capture->get(CAP_PROP_FRAME_COUNT));
 -            CV_Assert(frameCount == WriteVideo_Invoker::FrameCount);
 -            Mat reference(CreateVideoWriterInvoker::FrameSize, CV_8UC3);
 -
 -            for (unsigned int i = 0; i < frameCount && next; ++i)
 +            for (int j = r.start; j < r.end; ++j)
              {
 -                SCOPED_TRACE(cv::format("frame=%d/%d", (int)i, (int)frameCount));
 -
 -                Mat actual;
 -                (*capture) >> actual;
 -
 -                WriteVideo_Invoker::GenerateFrame(reference, i);
 -
 -                EXPECT_EQ(reference.cols, actual.cols);
 -                EXPECT_EQ(reference.rows, actual.rows);
 -                EXPECT_EQ(reference.depth(), actual.depth());
 -                EXPECT_EQ(reference.channels(), actual.channels());
 -
 -                double psnr = cvtest::PSNR(actual, reference);
 -                if (psnr < eps)
 +                Mat reference(sz, CV_8UC3);
 +                for (int i = 0; i < frameNum; ++i)
                  {
 -    #define SUM cvtest::TS::SUMMARY
 -                    ts->printf(SUM, "\nPSNR: %lf\n", psnr);
 -                    ts->printf(SUM, "Video #: %d\n", range.start);
 -                    ts->printf(SUM, "Frame #: %d\n", i);
 -    #undef SUM
 -                    ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
 -                    ts->set_gtest_status();
 -
 -                    Mat diff;
 -                    absdiff(actual, reference, diff);
 -
 -                    EXPECT_EQ(countNonZero(diff.reshape(1) > 1), 0);
 -
 -                    next = false;
 +                    Mat actual;
 +                    EXPECT_TRUE(readers[j]->read(actual));
 +                    EXPECT_FALSE(actual.empty());
 +                    generateFrame(reference, i, center, color);
 +                    EXPECT_EQ(reference.size(), actual.size());
 +                    EXPECT_EQ(reference.depth(), actual.depth());
 +                    EXPECT_EQ(reference.channels(), actual.channels());
 +                    EXPECT_GE(cvtest::PSNR(actual, reference), 35.0) << "cap" << j << ", frame " << i;
                  }
              }
 -        }
 +        };
 +        parallel_for_(R, readFrames, GRAN);
      }
 -
 -    static bool next;
 -
 -private:
 -    const std::vector< cv::Ptr<VideoCapture> >* readers;
 -    cvtest::TS* ts;
 -};
 -
 -bool ReadImageAndTest::next;
 -
 -TEST(Videoio_Video_parallel_writers_and_readers, accuracy)
 -{
 -    const unsigned int threadsCount = 4;
 -    cvtest::TS* ts = cvtest::TS::ptr();
 -
 -    // creating VideoWriters
 -    std::vector< cv::Ptr<VideoWriter> > writers(threadsCount);
 -    Range range(0, threadsCount);
 -    std::vector<std::string> files(threadsCount);
 -    CreateVideoWriterInvoker invoker1(writers, files);
 -    parallel_for_(range, invoker1);
 -
 -    // write a video
 -    parallel_for_(range, WriteVideo_Invoker(writers));
 -
 -    // deleting the writers
 -    writers.clear();
 -
 -    std::vector<cv::Ptr<VideoCapture> > readers(threadsCount);
 -    CreateVideoCaptureInvoker invoker2(readers, files);
 -    parallel_for_(range, invoker2);
 -
 -    ReadImageAndTest::next = true;
 -
 -    parallel_for_(range, ReadImageAndTest(readers, ts));
 -
 -    // deleting tmp video files
 -    for (std::vector<std::string>::const_iterator i = files.begin(), end = files.end(); i != end; ++i)
 +    // Remove files
 +    for(int i = 0; i < NUM; ++i)
      {
 -        int code = remove(i->c_str());
 -        if (code == 1)
 -            std::cerr << "Couldn't delete " << *i << std::endl;
 +        remove(files[i].c_str());
      }
 -
 -    // delete the readers
 -    readers.clear();
  }
  
 -#endif
+ typedef std::pair<VideoCaptureProperties, double> cap_property_t;
+ typedef std::vector<cap_property_t> cap_properties_t;
+ typedef std::pair<std::string, cap_properties_t> ffmpeg_cap_properties_param_t;
+ typedef testing::TestWithParam<ffmpeg_cap_properties_param_t> ffmpeg_cap_properties;
+ #ifdef _WIN32
+ namespace {
+ ::testing::AssertionResult IsOneOf(double value, double expected1, double expected2)
+ {
+     // internal floating point class is used to perform accurate floating point types comparison
+     typedef ::testing::internal::FloatingPoint<double> FloatingPoint;
+     FloatingPoint val(value);
+     if (val.AlmostEquals(FloatingPoint(expected1)) || val.AlmostEquals(FloatingPoint(expected2)))
+     {
+         return ::testing::AssertionSuccess();
+     }
+     else
+     {
+         return ::testing::AssertionFailure()
+                << value << " is neither  equal to " << expected1 << " nor " << expected2;
+     }
+ }
+ }
+ #endif
+ TEST_P(ffmpeg_cap_properties, can_read_property)
+ {
++    if (!videoio_registry::hasBackend(CAP_FFMPEG))
++        throw SkipTestException("FFmpeg backend was not found");
++
+     ffmpeg_cap_properties_param_t parameters = GetParam();
+     const std::string path = parameters.first;
+     const cap_properties_t properties = parameters.second;
+     VideoCapture cap(findDataFile(path), CAP_FFMPEG);
+     ASSERT_TRUE(cap.isOpened()) << "Can not open " << findDataFile(path);
+     for (std::size_t i = 0; i < properties.size(); ++i)
+     {
+         const cap_property_t& prop = properties[i];
+         const double actualValue = cap.get(static_cast<int>(prop.first));
+     #ifndef _WIN32
+         EXPECT_DOUBLE_EQ(actualValue, prop.second)
+             << "Property " << static_cast<int>(prop.first) << " has wrong value";
+     #else
+         EXPECT_TRUE(IsOneOf(actualValue, prop.second, 0.0))
+             << "Property " << static_cast<int>(prop.first) << " has wrong value";
+     #endif
+     }
+ }
+ cap_properties_t loadBigBuckBunnyFFProbeResults() {
+     cap_property_t properties[] = { cap_property_t(CAP_PROP_BITRATE, 5851.),
+                                     cap_property_t(CAP_PROP_FPS, 24.),
+                                     cap_property_t(CAP_PROP_FRAME_HEIGHT, 384.),
+                                     cap_property_t(CAP_PROP_FRAME_WIDTH, 672.) };
+     return cap_properties_t(properties, properties + sizeof(properties) / sizeof(cap_property_t));
+ }
+ const ffmpeg_cap_properties_param_t videoio_ffmpeg_properties[] = {
+     ffmpeg_cap_properties_param_t("video/big_buck_bunny.avi", loadBigBuckBunnyFFProbeResults())
+ };
+ INSTANTIATE_TEST_CASE_P(videoio, ffmpeg_cap_properties, testing::ValuesIn(videoio_ffmpeg_properties));
  }} // namespace