test_backgroundsubtractor_lsbp.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. #include "test_precomp.hpp"
  5. #include <set>
  6. namespace opencv_test { namespace {
  7. static string getDataDir() { return TS::ptr()->get_data_path(); }
  8. static string getLenaImagePath() { return getDataDir() + "shared/lena.png"; }
  9. // Simple synthetic illumination invariance test
  10. TEST(BackgroundSubtractor_LSBP, IlluminationInvariance)
  11. {
  12. RNG rng;
  13. Mat input(100, 100, CV_32FC3);
  14. rng.fill(input, RNG::UNIFORM, 0.0f, 0.1f);
  15. Mat lsv1, lsv2;
  16. cv::bgsegm::BackgroundSubtractorLSBPDesc::calcLocalSVDValues(lsv1, input);
  17. input *= 10;
  18. cv::bgsegm::BackgroundSubtractorLSBPDesc::calcLocalSVDValues(lsv2, input);
  19. ASSERT_LE(cv::norm(lsv1, lsv2), 0.04f);
  20. }
  21. TEST(BackgroundSubtractor_LSBP, Correctness)
  22. {
  23. Mat input(3, 3, CV_32FC3);
  24. float n = 0;
  25. for (int i = 0; i < 3; ++i)
  26. for (int j = 0; j < 3; ++j) {
  27. input.at<Point3f>(i, j) = Point3f(n, n, n);
  28. ++n;
  29. }
  30. Mat lsv;
  31. bgsegm::BackgroundSubtractorLSBPDesc::calcLocalSVDValues(lsv, input);
  32. EXPECT_LE(std::abs(lsv.at<float>(1, 1) - 0.0903614f), 0.001f);
  33. input = 1;
  34. bgsegm::BackgroundSubtractorLSBPDesc::calcLocalSVDValues(lsv, input);
  35. EXPECT_LE(std::abs(lsv.at<float>(1, 1) - 0.0f), 0.001f);
  36. }
  37. TEST(BackgroundSubtractor_LSBP, Discrimination)
  38. {
  39. Point2i LSBPSamplePoints[32];
  40. for (int i = 0; i < 32; ++i) {
  41. const double phi = i * CV_2PI / 32.0;
  42. LSBPSamplePoints[i] = Point2i(int(4 * std::cos(phi)), int(4 * std::sin(phi)));
  43. }
  44. Mat lena = imread(getLenaImagePath());
  45. Mat lsv;
  46. lena.convertTo(lena, CV_32FC3);
  47. bgsegm::BackgroundSubtractorLSBPDesc::calcLocalSVDValues(lsv, lena);
  48. Scalar mean, var;
  49. meanStdDev(lsv, mean, var);
  50. EXPECT_GE(mean[0], 0.02);
  51. EXPECT_LE(mean[0], 0.04);
  52. EXPECT_GE(var[0], 0.03);
  53. Mat desc;
  54. bgsegm::BackgroundSubtractorLSBPDesc::computeFromLocalSVDValues(desc, lsv, LSBPSamplePoints);
  55. Size sz = desc.size();
  56. std::set<int> distinctive_elements;
  57. for (int i = 0; i < sz.height; ++i)
  58. for (int j = 0; j < sz.width; ++j)
  59. distinctive_elements.insert(desc.at<int>(i, j));
  60. EXPECT_GE(distinctive_elements.size(), 35000U);
  61. }
  62. static double scoreBitwiseReduce(const Mat& mask, const Mat& gtMask, uchar v1, uchar v2) {
  63. Mat result;
  64. cv::bitwise_and(mask == v1, gtMask == v2, result);
  65. return cv::countNonZero(result);
  66. }
  67. template<typename T>
  68. static double evaluateBGSAlgorithm(Ptr<T> bgs) {
  69. Mat background = imread(getDataDir() + "shared/fruits.png");
  70. Mat object = imread(getDataDir() + "shared/baboon.png");
  71. cv::resize(object, object, Size(100, 100), 0, 0, INTER_LINEAR_EXACT);
  72. Ptr<bgsegm::SyntheticSequenceGenerator> generator = bgsegm::createSyntheticSequenceGenerator(background, object);
  73. double f1_mean = 0;
  74. unsigned total = 0;
  75. for (int frameNum = 1; frameNum <= 400; ++frameNum) {
  76. Mat frame, gtMask;
  77. generator->getNextFrame(frame, gtMask);
  78. Mat mask;
  79. bgs->apply(frame, mask);
  80. Size sz = frame.size();
  81. EXPECT_EQ(sz, gtMask.size());
  82. EXPECT_EQ(gtMask.size(), mask.size());
  83. EXPECT_EQ(mask.type(), gtMask.type());
  84. EXPECT_EQ(mask.type(), CV_8U);
  85. // We will give the algorithm some time for the proper background model inference.
  86. // Almost all background subtraction algorithms have a problem with cold start and require some time for background model initialization.
  87. // So we will not count first part of the frames in the score.
  88. if (frameNum > 300) {
  89. const double tp = scoreBitwiseReduce(mask, gtMask, 255, 255);
  90. const double fp = scoreBitwiseReduce(mask, gtMask, 255, 0);
  91. const double fn = scoreBitwiseReduce(mask, gtMask, 0, 255);
  92. if (tp + fn + fp > 0) {
  93. const double f1_score = 2.0 * tp / (2.0 * tp + fn + fp);
  94. f1_mean += f1_score;
  95. ++total;
  96. }
  97. }
  98. }
  99. f1_mean /= total;
  100. return f1_mean;
  101. }
  102. TEST(BackgroundSubtractor_LSBP, Accuracy)
  103. {
  104. EXPECT_GE(evaluateBGSAlgorithm(bgsegm::createBackgroundSubtractorGSOC()), 0.9);
  105. EXPECT_GE(evaluateBGSAlgorithm(bgsegm::createBackgroundSubtractorLSBP()), 0.25);
  106. }
  107. }} // namespace