3/23/2016

OpenCV RTSP receiving test

To get the RTSP video and showing is easy when we use VideoCapture function in OpenCV.
http://study.marearts.com/2015/05/opencv300-rc1-videocapture-example.html
http://study.marearts.com/2013/09/opencv-video-writer-example-source-code.html

But the video looks even broken video stream is shifted a bit.
So I use VLC library for stable receiving and show.
http://study.marearts.com/2015/09/opencv-rtsp-connection-using-vlc-library.html
This method is also good.
But It is cumbersome because it requires additional library file of VLC.

So again, let's solve this problem in OpenCV.
The method is to separately manage the RTSP receving part and drawing part.

New review code.

1. normal method. (This is not stable)
...
#include "opencv2/opencv.hpp"
#include < string>

using namespace std;
using namespace cv;

int main()
{

 string streamUri = "rtsp://192.168.0.21:554/onvif/profile2/media.smp";
 VideoCapture stream(streamUri);
 if (!stream.isOpened()){
  cout << "error" << endl;
  return 0;
 }

 Mat image;
 while (1){
  stream >> image;
  imshow("test", image);
  if (waitKey(30) >= 0)
   break;

 }

 return 0;
}
..

2. Receiving part threading(stable)
...
#include "opencv2/opencv.hpp"
#include < string>
#include < list>
#include < thread>

using namespace std;
using namespace cv;



// RTSP receive buffer list
list< Mat> frames;
cv::VideoCapture stream2;
bool isRun;

// thread function for video getting and show
void StreamThread(bool &isRun)
{
 cv::Mat image;
 while (isRun){
  stream2 >> image;
  frames.push_back(image.clone());
  printf("%d mat stacked \n", frames.size());
 }
}


int main(int, char)
{
 //rtsp address 
 string streamUri = "rtsp://192.168.0.21:554/onvif/profile2/media.smp";
 stream2.open(streamUri);

 //open check
 if (!stream2.isOpened()){
  cerr << "Stream open failed : " << streamUri << endl;
  return EXIT_FAILURE;
 }

 isRun = true;
 // thread run
 thread(StreamThread, isRun).detach();


 //Mat draw only in the main function.
 while (isRun){

  if (frames.size()>1){

   Mat image = frames.front();
   imshow("test", image);
   frames.pop_front();

   if (waitKey(30) >= 0)
    break;
  }
 }

 isRun = false;

 return 0;
}
...


3. Drawing part threading

...
#include "opencv2/opencv.hpp"
#include < string>
#include < list>
#include < thread>

using namespace std;
using namespace cv;



// RTSP receive buffer list
list< Mat> frames;
bool isRun;

// thread function for video show
void drawFrame(bool &isRun)
{
 while (isRun){
  if (frames.size()>1){
   Mat image = frames.front();
   imshow("test", image);
   waitKey(1);
   frames.pop_front();
  }
 }
}


int main(int, char)
{
 //rtsp address 
 string streamUri = "rtsp://192.168.0.21:554/onvif/profile2/media.smp";
 VideoCapture stream(streamUri);

 //open check
 if (!stream.isOpened()){
  cerr << "Stream open failed : " << streamUri << endl;
  return EXIT_FAILURE;
 }

 isRun = true;
 // thread run
 thread(drawFrame, isRun).detach();

 cv::Mat image;
 //Mat get only in the main function.
 while (isRun){

  stream >> image;
  frames.push_back(image.clone());
  printf("%d mat stacked \n", frames.size());
 }

 isRun = false;

 return 0;
}
...




Github
https://github.com/MareArts/OpenCV-RTSP-receiving-Test-in-thread-and-while-processing

Thank you.

2 comments:

  1. 질문 μžˆμŠ΅λ‹ˆλ‹€.
    VLC ν”Œλ ˆμ΄μ–΄λ₯Ό 톡해 μŠ€νŠΈλ¦Όμ„ μ§„ν–‰ν•œ ν›„
    opencvλ₯Ό μ΄μš©ν•΄ ν΄λΌμ΄μ–ΈνŠΈ μƒμ—μ„œ μ˜μƒμ„ κ°€μ Έμ˜€λ €κ³  ν•˜λŠ”λ°
    μ‹œμž‘λΆ€ν„° uri 접속이 μ•ˆλ˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.
    즉 string streamUri = "rtsp://192.168.0.21:554/onvif/profile2/media.smp";
    VideoCapture stream(streamUri);
    이 λΆ€λΆ„μ—μ„œ open이 λ˜μ§€ μ•Šκ³  μžˆλŠ”λ° ν˜Ήμ‹œ 이 뢀뢄에 λŒ€ν•΄μ„œ μ•„μ‹œλŠ” 것이 μžˆμœΌμ‹ κ°€μš”?

    ReplyDelete
    Replies
    1. vlcλ‘œλŠ” ν•΄λ‹Ή μ£Όμ†Œκ°€ μŠ€ν‹°λ¦¬λ° λ˜λ‚˜μš”?
      opencv둜 rtspλ₯Ό μ„±κ³΅μ μœΌλ‘œ 받은 적이 μžˆλ‚˜μš”?

      Delete