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.
์ง๋ฌธ ์์ต๋๋ค.
ReplyDeleteVLC ํ๋ ์ด์ด๋ฅผ ํตํด ์คํธ๋ฆผ์ ์งํํ ํ
opencv๋ฅผ ์ด์ฉํด ํด๋ผ์ด์ธํธ ์์์ ์์์ ๊ฐ์ ธ์ค๋ ค๊ณ ํ๋๋ฐ
์์๋ถํฐ uri ์ ์์ด ์๋๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฆ string streamUri = "rtsp://192.168.0.21:554/onvif/profile2/media.smp";
VideoCapture stream(streamUri);
์ด ๋ถ๋ถ์์ open์ด ๋์ง ์๊ณ ์๋๋ฐ ํน์ ์ด ๋ถ๋ถ์ ๋ํด์ ์์๋ ๊ฒ์ด ์์ผ์ ๊ฐ์?
vlc๋ก๋ ํด๋น ์ฃผ์๊ฐ ์คํฐ๋ฆฌ๋ฐ ๋๋์?
Deleteopencv๋ก rtsp๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ฐ์ ์ ์ด ์๋์?