Ask Your Question

Revision history [back]

OpenCV Video Capture nonfunctional as class member (C++)

Question is cross-posted from https://stackoverflow.com/questions/64764106/opencv-video-capture-nonfunctional-as-class-member-c

My application requires that the OpenCV VideoCapture object be used as a member variable. There is no way around this requirement.

I am experiencing strange behavior when using cv::VideoCapture as a member of a user-defined class. I've run the following code:

define int64 opencv_broken_int

include <opencv2 opencv.hpp="">

undef int64

class Foo { public: Foo() = default; void run(void) { cv::VideoCapture* cap = new cv::VideoCapture(); cv::VideoCapture g_cap = *cap; if (not g_cap.open(0)) { std::cerr << "Cannot open camera 0" << std::endl; exit(-1); } for (int i = 0; i < 10; i++) { if (not g_cap.isOpened()) std::cerr << "Video capture is not open here!" << std::endl; cv::Mat f; g_cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Foo_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } };

};

int main(void) { cv::VideoCapture cap;

if (not cap.open(0)) { std::cerr << "Cannot open camera 0" << std::endl; return -1; }

for (int i =0; i < 10; i++) { cv::Mat frame; cap >> frame; if (frame.empty()) { std::cerr << "frame is empty" << std::endl; break; } // Else write the image to a file std::string filename = "test_" + std::to_string(i) + ".tiff"; bool res = cv::imwrite(filename, frame); if (not res) std::cerr << "Error in writing image" << std::endl;

}

cap.release();

Foo f; f.run();

return 0; }

which only produced test_N.tiff for N = [0,9], i.e., the only images produced are coming from the cv::VideoCapture object in main( ) and not from within class Foo.

I tried to instantiate a global variable g_cap of type cv::VideoCapture and still I only can read/write images from the object within the main function. As shown in the above code I also tried to instantiate the VideoCapture object as a pointer (a hail mary, if you will) and that does not work either. Note however that setting cap declared in main( ) to be a reference to g_cap (obviously when g_cap was in global scope) gave the same output - getting images from within main( ) but not from within Foo::run( ) as needed.

Note another strange behavior is that no error messages appear in the console. That would indicate that Foo's member of type VideoCapture is in fact open and that loading an image frame into f of type cv::Mat did not return an empty frame. Similarly the imwrite function does not return false indicating that the operation was successful. However, as previously stated, no files of name Foo_test_N.tiff were produced.

How could this behavior be explained? Is there some requirement that cv::VideoCapture be in some different scope perhaps? If the images are not saved or the video stream is not opened correctly would this not produce an error message as the above code is written?

Edit 20201110_1: In response to Viktor Latypov's comment below: I've implemented the proposed changes and am still observing the same behavior. Edits:

class Foo { public: Foo() = default; void run(void) { cv::VideoCapture* cap = new cv::VideoCapture(); //cv::VideoCapture g_cap = *cap; if (not cap -> open(0)) { std::cerr << "Cannot open camera 0" << std::endl; exit(-1); } for (int i = 0; i < 10; i++) { if (not cap -> isOpened()) std::cerr << "Video capture is not open here!" << std::endl; cv::Mat f; *cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Foo_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } cap -> release(); };

};

Edit 20201110_2: OpenCV Version is 4.2.0

I tried to capture image frames from (a) within a function and (b) passing the OpenCV VideoCapture object instantiated in main( ) to a parameterized constructor both as a copy and passing the pointer with still the same results. Complete code is shown below:

define int64 opencv_broken_int

include <opencv2 opencv.hpp="">

undef int64

class Foo { public: Foo() = default; void run(void) { cv::VideoCapture* cap = new cv::VideoCapture(); //cv::VideoCapture g_cap = *cap; if (not cap -> open(0)) { std::cerr << "Cannot open camera 0" << std::endl; exit(-1); } for (int i = 0; i < 10; i++) { if (not cap -> isOpened()) std::cerr << "Video capture is not open here!" << std::endl; cv::Mat f; *cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Foo_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } cap -> release(); };

};

class Bar { public: Bar(cv::VideoCapture* c) : cap(c) {};

    void run(void) {
            //cv::VideoCapture* cap = new cv::VideoCapture();
            //cv::VideoCapture g_cap = *cap;
            if (not cap -> open(0)) {
                    std::cerr << "Cannot open camera 0" << std::endl;
                    exit(-1);
            }
            for (int i = 0; i < 10; i++) {
                    if (not cap -> isOpened())
                            std::cerr << "Video capture is not

open here!" << std::endl; cv::Mat f; *cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Bar_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } cap -> release(); };

    cv::VideoCapture* cap; };

void test(void) { cv::VideoCapture cap(0);

    if (not cap.open(0)) {
            std::cerr << "Cannot open camera 0" << std::endl;
            exit(-1);
    }

    for (int i =0; i < 10; i++) {
            cv::Mat frame;
            cap >> frame;
            if (frame.empty()) {
                    std::cerr << "frame is empty" << std::endl;
                    break;
            }
            // Else write the image to a file
            std::string filename = "testFunc_test_" + std::to_string(i) +

".tiff"; bool res = cv::imwrite(filename, frame); if (not res) std::cerr << "Error in writing image" << std::endl;

    }

    cap.release(); }

int main(void) { cv::VideoCapture cap;

    if (not cap.open(0)) {
            std::cerr << "Cannot open camera 0" << std::endl;
            return -1;
    }

    for (int i =0; i < 10; i++) {
            cv::Mat frame;
            cap >> frame;
            if (frame.empty()) {
                    std::cerr << "frame is empty" << std::endl;
                    break;
            }
            // Else write the image to a file
            std::string filename = "main_test_" + std::to_string(i) +

".tiff"; bool res = cv::imwrite(filename, frame); if (not res) std::cerr << "Error in writing image" << std::endl;

    }

    cap.release();

    Bar b(&cap); b.run();

    Foo f; f.run();

    test();

    return 0; }

The output from this program is shown: Output from OpenCVTest Executable Note that no images are saved from within the class member functions of either Foo or Bar!

OpenCV Video Capture nonfunctional as class member (C++)

Question is cross-posted from https://stackoverflow.com/questions/64764106/opencv-video-capture-nonfunctional-as-class-member-c

My application requires that the OpenCV VideoCapture object be used as a member variable. There is no way around this requirement.

I am experiencing strange behavior when using cv::VideoCapture as a member of a user-defined class. I've run the following code:

define
 #define int64 opencv_broken_int

include <opencv2 opencv.hpp="">

undef int64

opencv_broken_int #include <opencv2/opencv.hpp> #undef int64 class Foo { public: Foo() = default; void run(void) { cv::VideoCapture* cap = new cv::VideoCapture(); cv::VideoCapture g_cap = *cap; if (not g_cap.open(0)) { std::cerr << "Cannot open camera 0" << std::endl; exit(-1); } for (int i = 0; i < 10; i++) { if (not g_cap.isOpened()) std::cerr << "Video capture is not open here!" << std::endl; cv::Mat f; g_cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Foo_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } };

};

}; }; int main(void) { cv::VideoCapture cap;

cap; if (not cap.open(0)) { std::cerr << "Cannot open camera 0" << std::endl; return -1; }

} for (int i =0; i < 10; i++) { cv::Mat frame; cap >> frame; if (frame.empty()) { std::cerr << "frame is empty" << std::endl; break; } // Else write the image to a file std::string filename = "test_" + std::to_string(i) + ".tiff"; bool res = cv::imwrite(filename, frame); if (not res) std::cerr << "Error in writing image" << std::endl;

}

cap.release();

std::endl; } cap.release(); Foo f; f.run();

f.run(); return 0; }

}

which only produced test_N.tiff for N = [0,9], i.e., the only images produced are coming from the cv::VideoCapture object in main( ) and not from within class Foo.

I tried to instantiate a global variable g_cap of type cv::VideoCapture and still I only can read/write images from the object within the main function. As shown in the above code I also tried to instantiate the VideoCapture object as a pointer (a hail mary, if you will) and that does not work either. Note however that setting cap declared in main( ) to be a reference to g_cap (obviously when g_cap was in global scope) gave the same output - getting images from within main( ) but not from within Foo::run( ) as needed.

Note another strange behavior is that no error messages appear in the console. That would indicate that Foo's member of type VideoCapture is in fact open and that loading an image frame into f of type cv::Mat did not return an empty frame. Similarly the imwrite function does not return false indicating that the operation was successful. However, as previously stated, no files of name Foo_test_N.tiff were produced.

How could this behavior be explained? Is there some requirement that cv::VideoCapture be in some different scope perhaps? If the images are not saved or the video stream is not opened correctly would this not produce an error message as the above code is written?

Edit 20201110_1: In response to Viktor Latypov's comment below: I've implemented the proposed changes and am still observing the same behavior. Edits:

 class Foo { public:
 Foo() = default;
 void run(void) {
  cv::VideoCapture* cap = new cv::VideoCapture();
 //cv::VideoCapture g_cap = *cap;
  if (not cap -> open(0)) {
 std::cerr << "Cannot open camera 0" << std::endl;
 exit(-1);
 }
  for (int i = 0; i < 10; i++) {
 if (not cap -> isOpened())
 std::cerr << "Video capture is not
 open here!" << std::endl;
 cv::Mat f;
  *cap >> f;
  if (f.empty()) std::cerr << "Frame was empty" <<
 std::endl; break;
  std::string filename = "Foo_test_" +
 std::to_string(i) + ".tiff";
  bool b = cv::imwrite(filename, f);
 if (not b) std::cerr << "Error in writing image"
 << std::endl;
 //cv::waitKey(25);
 }
  cap -> release();
 };

};

}; };

Edit 20201110_2: OpenCV Version is 4.2.0

I tried to capture image frames from (a) within a function and (b) passing the OpenCV VideoCapture object instantiated in main( ) to a parameterized constructor both as a copy and passing the pointer with still the same results. Complete code is shown below:

define

#define int64 opencv_broken_int

include opencv_broken_int #include <opencv2 opencv.hpp="">

undef opencv.hpp=""> #undef int64

class Foo { public: Foo() = default; void run(void) { cv::VideoCapture* cap = new cv::VideoCapture(); //cv::VideoCapture g_cap = *cap; if (not cap -> open(0)) { std::cerr << "Cannot open camera 0" << std::endl; exit(-1); } for (int i = 0; i < 10; i++) { if (not cap -> isOpened()) std::cerr << "Video capture is not open here!" << std::endl; cv::Mat f; *cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Foo_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } cap -> release(); };

};

 class Bar { public:
 Bar(cv::VideoCapture* c) : cap(c) {};

{};
 void run(void) {
  //cv::VideoCapture* cap = new cv::VideoCapture();
 //cv::VideoCapture g_cap = *cap;
  if (not cap -> open(0)) {
 std::cerr << "Cannot open camera 0" << std::endl;
 exit(-1);
 }
  for (int i = 0; i < 10; i++) {
 if (not cap -> isOpened())
 std::cerr << "Video capture is not

open here!" << std::endl; cv::Mat f; *cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Bar_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } cap -> release(); };

};
 cv::VideoCapture* cap; };

void test(void) { cv::VideoCapture cap(0);

cap(0);
 if (not cap.open(0)) {
 std::cerr << "Cannot open camera 0" << std::endl;
 exit(-1);
 }
  for (int i =0; i < 10; i++) {
 cv::Mat frame;
  cap >> frame;
 if (frame.empty()) {
 std::cerr << "frame is empty" << std::endl;
 break;
 }
  // Else write the image to a file
 std::string filename = "testFunc_test_" + std::to_string(i) +

".tiff"; bool res = cv::imwrite(filename, frame); if (not res) std::cerr << "Error in writing image" << std::endl;

std::endl;
 }
  cap.release(); }

int main(void) { cv::VideoCapture cap;

cap;
 if (not cap.open(0)) {
 std::cerr << "Cannot open camera 0" << std::endl;
 return -1;
 }
  for (int i =0; i < 10; i++) {
 cv::Mat frame;
  cap >> frame;
 if (frame.empty()) {
 std::cerr << "frame is empty" << std::endl;
 break;
 }
  // Else write the image to a file
 std::string filename = "main_test_" + std::to_string(i) +

".tiff"; bool res = cv::imwrite(filename, frame); if (not res) std::cerr << "Error in writing image" << std::endl;

std::endl;
 }
 cap.release();
  Bar b(&cap); b.run();
 Foo f; f.run();
 test();
  return 0; }

The output from this program is shown: Output from OpenCVTest Executable Note that no images are saved from within the class member functions of either Foo or Bar!

OpenCV Video Capture nonfunctional as class member (C++)

Question is cross-posted from https://stackoverflow.com/questions/64764106/opencv-video-capture-nonfunctional-as-class-member-c

My application requires that the OpenCV VideoCapture object be used as a member variable. There is no way around this requirement.

I am experiencing strange behavior when using cv::VideoCapture as a member of a user-defined class. I've run the following code:

 #define int64 opencv_broken_int
 #include <opencv2/opencv.hpp>
 #undef int64


 class Foo { public:    Foo() = default;
    void run(void) {        cv::VideoCapture*
 cap = new cv::VideoCapture();
        cv::VideoCapture g_cap = *cap;      if
 (not g_cap.open(0)) {          std::cerr <<
 "Cannot open camera 0" << std::endl;
            exit(-1);       }       for (int i = 0; i <
 10; i++) {             if (not
 g_cap.isOpened())
                std::cerr << "Video capture is not open here!" << std::endl;            cv::Mat
 f;             g_cap >> f;             if (f.empty())
 std::cerr << "Frame was empty" <<
 std::endl; break;          std::string
 filename = "Foo_test_" +
 std::to_string(i) + ".tiff";           bool b
 = cv::imwrite(filename, f);
            if (not b) std::cerr << "Error in writing image" << std::endl;
            //cv::waitKey(25);      }   };

 };

 int main(void) {   cv::VideoCapture
 cap;

    if (not cap.open(0)) {      std::cerr <<
 "Cannot open camera 0" << std::endl;
        return -1;  }

    for (int i =0; i < 10; i++) {
        cv::Mat frame;          cap >> frame;       if
 (frame.empty()) {          std::cerr <<
 "frame is empty" << std::endl;
            break;      }       // Else write the
 image to a file        std::string filename
 = "test_" + std::to_string(i) + ".tiff";       bool res =
 cv::imwrite(filename, frame);      if
 (not res)              std::cerr << "Error in
 writing image" << std::endl;

    }

    cap.release();

    Foo f;  f.run();

    return 0; }

which only produced test_N.tiff for N = [0,9], i.e., the only images produced are coming from the cv::VideoCapture object in main( ) and not from within class Foo.

I tried to instantiate a global variable g_cap of type cv::VideoCapture and still I only can read/write images from the object within the main function. As shown in the above code I also tried to instantiate the VideoCapture object as a pointer (a hail mary, if you will) and that does not work either. Note however that setting cap declared in main( ) to be a reference to g_cap (obviously when g_cap was in global scope) gave the same output - getting images from within main( ) but not from within Foo::run( ) as needed.

Note another strange behavior is that no error messages appear in the console. That would indicate that Foo's member of type VideoCapture is in fact open and that loading an image frame into f of type cv::Mat did not return an empty frame. Similarly the imwrite function does not return false indicating that the operation was successful. However, as previously stated, no files of name Foo_test_N.tiff were produced.

How could this behavior be explained? Is there some requirement that cv::VideoCapture be in some different scope perhaps? If the images are not saved or the video stream is not opened correctly would this not produce an error message as the above code is written?

Edit 20201110_1: In response to Viktor Latypov's comment below: I've implemented the proposed changes and am still observing the same behavior. Edits:

 class Foo { public:
         Foo() = default;
         void run(void) {
                 cv::VideoCapture* cap = new cv::VideoCapture();
                 //cv::VideoCapture g_cap = *cap;
                 if (not cap -> open(0)) {
                         std::cerr << "Cannot open camera 0" << std::endl;
                         exit(-1);
                 }
                 for (int i = 0; i < 10; i++) {
                         if (not cap -> isOpened())
                                 std::cerr << "Video capture is not
 open here!" << std::endl;
                         cv::Mat f;
                         *cap >> f;
                         if (f.empty()) std::cerr << "Frame was empty" <<
 std::endl; break;
                         std::string filename = "Foo_test_" +
 std::to_string(i) + ".tiff";
                        bool b = cv::imwrite(filename, f);
                        if (not b) std::cerr << "Error in writing image"
 << std::endl;
                        //cv::waitKey(25);
                 }
                 cap -> release();
         };

 };

Edit 20201110_2: OpenCV Version is 4.2.0

I tried to capture image frames from (a) within a function and (b) passing the OpenCV VideoCapture object instantiated in main( ) to a parameterized constructor both as a copy and passing the pointer with still the same results. Complete code is shown below:

 #define int64 opencv_broken_int
#include <opencv2 opencv.hpp="">
<opencv2/opencv.hpp>
 #undef int64

int64 class Foo { public: Foo() = default; void run(void) { cv::VideoCapture* cap = new cv::VideoCapture(); //cv::VideoCapture g_cap = *cap; if (not cap -> open(0)) { std::cerr << "Cannot open camera 0" << std::endl; exit(-1); } for (int i = 0; i < 10; i++) { if (not cap -> isOpened()) std::cerr << "Video capture is not open here!" << std::endl; cv::Mat f; *cap >> f; if (f.empty()) std::cerr << "Frame was empty" << std::endl; break; std::string filename = "Foo_test_" + std::to_string(i) + ".tiff"; bool b = cv::imwrite(filename, f); if (not b) std::cerr << "Error in writing image" << std::endl; //cv::waitKey(25); } cap -> release(); };

};

};
};
 class Bar { public:
  Bar(cv::VideoCapture* c) : cap(c) {};
 void run(void) {
  //cv::VideoCapture* cap = new cv::VideoCapture();
 //cv::VideoCapture g_cap = *cap;
  if (not cap -> open(0)) {
 std::cerr << "Cannot open camera 0" << std::endl;
 exit(-1);
 }
  for (int i = 0; i < 10; i++) {
 if (not cap -> isOpened())
 std::cerr << "Video capture is not
 open here!" << std::endl;
 cv::Mat f;
  *cap >> f;
  if (f.empty()) std::cerr << "Frame was empty" <<
 std::endl; break;
  std::string filename = "Bar_test_" +
 std::to_string(i) + ".tiff";
  bool b = cv::imwrite(filename, f);
 if (not b) std::cerr << "Error in writing image"
 << std::endl;
 //cv::waitKey(25);
 }
  cap -> release();
 };
  cv::VideoCapture* cap; };
 void test(void) {
 cv::VideoCapture cap(0);
  if (not cap.open(0)) {
 std::cerr << "Cannot open camera 0" << std::endl;
 exit(-1);
 }
  for (int i =0; i < 10; i++) {
 cv::Mat frame;
  cap >> frame;
 if (frame.empty()) {
 std::cerr << "frame is empty" << std::endl;
 break;
 }
  // Else write the image to a file
 std::string filename = "testFunc_test_" + std::to_string(i) +
 ".tiff";
  bool res = cv::imwrite(filename, frame);
 if (not res)
  std::cerr << "Error in writing image" << std::endl;
 }
  cap.release(); }
  int main(void) {
 cv::VideoCapture cap;
  if (not cap.open(0)) {
 std::cerr << "Cannot open camera 0" << std::endl;
 return -1;
 }
  for (int i =0; i < 10; i++) {
 cv::Mat frame;
  cap >> frame;
 if (frame.empty()) {
 std::cerr << "frame is empty" << std::endl;
 break;
 }
  // Else write the image to a file
 std::string filename = "main_test_" + std::to_string(i) +
 ".tiff";
  bool res = cv::imwrite(filename, frame);
 if (not res)
  std::cerr << "Error in writing image" << std::endl;
 }
 cap.release();
  Bar b(&cap); b.run();
 Foo f; f.run();
 test();
  return 0; }

The output from this program is shown: Output from OpenCVTest Executable Note that no images are saved from within the class member functions of either Foo or Bar!