Getting camera image from thread - c++

I am using opencv library to obtain video from the built-in webcam. The following code works perfectly well when i put camera logic code into the main function, but it doesn't when i put it into separate thread. The task1() thread stops at cv::VideoCapture capture(0). Meanwhile both task2() and the main thread are executing correctly.
Could someone explain me why opencv logic doesn't work when put into separate thread?
My code:
#include <iostream>
#include <string.h>
#include <thread>
#include <unistd.h>
#include <opencv2/opencv.hpp>
using namespace std;
void task1 (){
cout<<"1st thread ";
cv::Mat frame;
cv::VideoCapture capture(0);
if ( capture.isOpened() == false )
{
cout<<"Failed to open camera";
}
cv::namedWindow("Test OpenCV",1);
while ( true ){
capture >> frame;
cv::imshow("Test OpenCV", frame );
int key = cv::waitKey(1);
if ( key == 27 )
break;
}
}
void task2 (){
int n = 0;
while (1){
cout<<"2nd thread "<<n<<"\n";
sleep(3);
n++;
}
}
int main(int argc, const char * argv[]) {
// insert code here...
cout << "Hello, World!\n";
thread t1(task1);
thread t2(task2);
//t1.join();
//t2.join();
int n = 0;
while (1){
cout<<"main thread "<<n<<"\n";
sleep(1);
n++;
}
return 0;
}

Your code runs as it should for me (without any modifications) and I get the live feed through the task1 thread (using OpenCV 2.4.5).
I added -std=gnu++0x flag for compiler support (otherwise g++ throws an error).
g++ -std=gnu++0x opencv_thread.cpp -o opencv_thread `pkg-config --cflags --libs opencv`
Check my console output here. I added a cout << "1st thread "<< endl; within the while loop in task1.
I think the issue might be specific to some opencv versions as I have seen similar issues in an older version (don't remember which one) and boost threads.
Can you give details about the version you used?. Also try it with 2.4.5.

Related

Unreliable errors while multithreading in SFML for C++

I am trying to make a basic game in c++ using the SFML library. For this game, I want a thread
drawing at a fixed rate and another thread checking for input as often as possible. The first problem I encountered was that the SFML library does not allow for window to be active on multiple threads. A simple fix for this was found by just deactivating the window in the main thread. The next problem that I have not yet found a fix for is that I cannot seem to check for input on my main thread (In this scenario).
This code is very unreliable. I can get two different error messages, or an infinite loop. What should happen is an infinite loop that can be closed with the escape key, and if you press d it prints a message.
The library I am using is libsfml-dev
My compile arguments are as follows: g++ test.cpp -pthread -lsfml-graphics -lsfml-window -lsfml-system
#include <iostream>
#include <stdio.h>
#include <pthread.h>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
sf::RenderWindow window(sf::VideoMode(800, 800), "");
using namespace std;
void *func(void *threadid) {
cout << "New thread." << endl;
while (window.isOpen()) {
// In the actual implementation, this would be replaced with draw methods
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
window.close();
}
}
pthread_exit(NULL);
}
int main() {
// Needed so that window is only active on a single thread
window.setActive(false);
// Create new thread
pthread_t threads[1];
int val;
val = pthread_create(&threads[0], NULL, func, (void *)1);
cout << "Main thread." << endl;
while (window.isOpen()) {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
cout << "D button pressed." << endl;
}
}
return 0;
}
Error Number 1
PS: XInitThreads doesn't help
Error Number 2
Looks like an error from my X server

OpenCV 3 and threading on Ubuntu

Can OpenCV be made to work with the following code, modified from here:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <thread>
using namespace cv;
using namespace std;
void showWindow(std::string const &name, cv::Mat const &img)
{
cv::namedWindow(name, cv::WINDOW_AUTOSIZE);
cv::imshow(name, img);
}
int main( int argc, char** argv )
{
if( argc != 2)
{
cout <<" Usage: display_image ImageToLoadAndDisplay" << endl;
return -1;
}
Mat image;
image = imread(argv[1], CV_LOAD_IMAGE_COLOR);
if(! image.data )
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
std::thread t1(showWindow, "Display window", image);
t1.join();
waitKey(0);
return 0;
}
Compiled with g++ -std=c++11 -g opencv.cpp -o app `pkg-config --cflags --libs opencv`. My actual example is much more complex, but this is a MCVE.
The program hangs, and pressing CTRL+C in gdb gives me:
Program received signal SIGINT, Interrupt.
0x00007ffff6a7dd4d in nanosleep () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0 0x00007ffff6a7dd4d in nanosleep () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007ffff6aaefd4 in usleep (useconds=<optimised out>) at ../sysdeps/unix/sysv/linux/usleep.c:32
#2 0x00007ffff7bafe1e in cvWaitKey () from /usr/local/lib/libopencv_highgui.so.3.2
#3 0x00007ffff7baa2c6 in cv::waitKey(int) () from /usr/local/lib/libopencv_highgui.so.3.2
#4 0x0000000000401970 in main (argc=3, argv=0x7fffffffd418) at opencv.cpp:31
I tried rebuilding with WITH_TBB=ON but it made no difference.

C++ Delay For-Loop without pausing Console

I am trying to create a function that will be done many times over and over but with a pause in between each cycle.
I have tried to use "sleep" but that pauses the console. And I have searched online and only found answers that paused the console during usual.
Code:
int i;
for(i=0; i<500; i++) {
std::cout << "Hello" << std::endl;
}
How can I make it print "Hello" 500 times and as well allow the user to use the console while it is doing the said function?
As some people commented, you need to create an async task in order to do some work while still handling user input.
The following is a minimal, working example about how to acomplish this task by using a thread. It is based on boost so you'll have to link it using -lboost_thread lboost_system:
g++ test.cpp -lboost_thread -lboost_system -o test
The code has several comments in order to explain what you should do:
#include <queue>
#include <iostream>
#include <boost/thread.hpp>
// set by the main thread when the user enters 'quit'
bool stop = false;
boost::mutex stopMutex; // protect the flag!
// the function that runs in a new thread
void thread_function() {
// the following is based on the snippet you wrote
int i;
for(i=0; i<500; i++) {
// test if I have to stop on each loop
{
boost::mutex::scoped_lock lock(stopMutex);
if (stop) {
break;
}
}
// your task
std::cout << "Hello" << std::endl;
// sleep a little
::usleep(1000000);
}
}
int main() {
std::string str;
boost::thread t(thread_function);
while(true) {
std::cout << "Type 'quit' to exit: ";
// will read user input
std::getline(std::cin, str);
if (str == "quit") {
// the user wants to quit the program, set the flag
boost::mutex::scoped_lock lock(stopMutex);
stop = true;
break;
}
}
// wait for the async task to finish
t.join();
return 0;
}

Can we use pthread library for opencv C++ programming?

I have implemented a openCV program which can capture frames from video file and process it and create a new file. That is doing for single in file . Now I want for multiple files . then I have an idea about POSIX thread pthread library . Is that is a good or bad idea . Actually when I implement pthreads in opencv program I got some errors like following :
OpenCV Error: Assertion failed (_src.sameSize(_dst) && dcn == scn) in
accumulate, file
/home/satinder/opencv_installation/OpenCV/opencv/modules/imgproc/src/accum.cpp,
line 915
what():
/home/satinder/opencv_installation/OpenCV/opencv/modules/imgproc/src/accum.cpp:915:
error: (-215) _src.sameSize(_dst) && dcn == scn in function accumulate
Aborted (core dumped)
corrupted double-linked list: 0x00007fcd048f73d0 ***
Aborted (core dumped)
seg fault also some time .
Is there any possible way how I can implement multi-threading or equivalent my goal make a program which can get more that one input files for same processing.
FOllowing is my code snapshot :
#include "opencv2/highgui/highgui.hpp"
#include <sys/types.h>
#include <pthread.h>
#include <iostream>
using namespace cv;
using namespace std;
void * VideoCap(void *);
void * VideoCap(void *arg)
{
VideoCapture cap((char *)arg); // open the video file for reading
if ( !cap.isOpened() ) // if not success, exit program
{
cout << "Cannot open the video file" << endl;
exit(1);
}
//cap.set(CV_CAP_PROP_POS_MSEC, 300); //start the video at 300ms
double fps = cap.get(CV_CAP_PROP_FPS); //get the frames per seconds of the video
cout << "Frame per seconds : " << fps << endl;
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
while(1)
{
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read the frame from video file" << endl;
break;
}
imshow("MyVideo", frame); //show the frame in "MyVideo" window
if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
}
int main(int argc, char* argv[])
{
int ret ;
pthread_t th[2];
ret = pthread_create(&th[0] , NULL , VideoCap , (void *)"cctv3.mp4");
if(0 == ret)
{
cout << "Thread 1 is created successfull" << endl;
}
ret = pthread_create(&th[1] , NULL , VideoCap , (void *)"cctv10.mp4");
if(0 == ret)
{
cout << "Thread 2 is created successfull" << endl;
}
pthread_join(th[0] , NULL);
pthread_join(th[1] , NULL);
return 0;
}
There are some problems with your code
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
You are creating two threads, so the windows should have different identifiers.
namedWindow((char *)arg, CV_WINDOW_AUTOSIZE);
...
imshow((char *)arg, frame);
Since this question was posted with linux tag, I'm guessing that gtk is relevant. After inserting the directives
#include <gdk/gdk.h>
#include <gtk/gtkmain.h>
at the beginning of the file and then in the main()
pthread_t th[2];
gtk_disable_setlocale();
gtk_init(&argc, &argv);
gdk_threads_init();
New linker / compiler flags are probably needed,
g++ -O -Wall test.cpp -lopencv_highgui -lopencv_core `pkg-config --libs --cflags gdk-2.0 gtk+-2.0`
After these changes there was still an occasional crash, so I added gdk_threads_enter() and gdk_threads_leave(); calls to test if they would help:
gdk_threads_enter();
namedWindow ((char *) arg, CV_WINDOW_AUTOSIZE);
gdk_threads_leave();
Since the crashing was not reproducible, it is hard to tell if those lines have any effect.

opencv VideoCapture is blocked in thread

I need some some help with the usage of opencv VideoCapture in another thread.
When I use the VideoCapture in the main thread, it is perfectly fine and it shows the video smoothly. But once I put the code in another thread and expect it do the same thing, it seems the VideoCapture does not work at all.
I made some attempts: if I initialize the VideoCapture with 0 (the default one) as parameter, it gets blocked. But if I don't initialize it
VideoCapture cap;
or use another number
VideoCapture cap(1);
it prints out error message and exits but does not get blocked.
Here is the code:
#include <iostream>
#include <thread>
#include <functional>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
class MyClass {
public:
// display the video
static void display(int i) {
VideoCapture cap(0);
if (!cap.isOpened()) {
cout << "cannot access webcame" << endl;
exit(-1);
}
Mat imgOriginal;
namedWindow("Original", WINDOW_AUTOSIZE);
while (true) {
bool success = cap.read(imgOriginal);
if (!success) {
cout << "fail to read video into mat" << endl;
break;
}
imshow("Original", imgOriginal);
if (waitKey(30) == 27) {
break;
}
}
}
};
int main()
{
//cout << "Hello World!" << endl;
thread myThread(bind(MyClass::display, 0));
myThread.join();
return 0;
}
Very appreciated if anyone can point out where I got it wrong. Thank you.