我想直接使用 Gstreamer 管道和 OpenCV 來管理來自相機的影像采集。目前我沒有相機,所以我一直在嘗試從 URI 和本地檔案中獲取視頻。我正在使用帶有 L4T(ubuntu 18.04)的 Jetson AGX Xavier,我的 OpenCV 構建包括 Gstreamer,并且兩個庫似乎都可以獨立作業。
我遇到的問題是,當我使用 cv2.CAP_GSTREAMER 將定義管道的字串傳遞給 VideoCapture 類時,我收到一些警告,如下所示:
[警告:0] 全域 /home/nvidia/opencv/modules/videoio/src/cap_gstreamer.cpp (854) 打開 OpenCV | GStreamer 警告:打開 bin 時出錯:無法將 playbin0 鏈接到我定義的任何接收器
[警告:0] 全域 /home/nvidia/opencv/modules/videoio/src/cap_gstreamer.cpp (597) isPipelinePlaying OpenCV | GStreamer 警告:GStreamer:尚未創建管道
我嘗試了幾個選項,您可以在下一個代碼中看到它們:
bool receiver(const char* context)
{
VideoCapture cap(context, CAP_GSTREAMER);
int fail = 0;
while(!cap.isOpened())
{
cout<<"VideoCapture not opened"<<endl;
fail ;
if (fail > 10){
return false;
}
continue;
}
Mat frame;
while(true) {
cap.read(frame);
if(frame.empty())
return true;
imshow("Receiver", frame);
if(waitKey(1) == 'r')
return false;
}
destroyWindow("Receiver");
return true;
}
int main(int argc, char *argv[])
{
GstElement *pipeline;
const char* context = "gstlaunch v udpsrc port=5000 caps=\"application/xrtp\" ! rtph264depay ! ffdec_h264 ! ffmpegcolorspace ! ximagesink sync=false"; //Command for the camera that I don't have yet
const char* test_context = "gstlaunch playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm";
const char* thermal_context = "playbin uri=file:///home/nvidia/repos/vidtest/thermalVideo.avi ! appsink name=thermalsink";
const char* local_context = "playbin uri=file:///home/nvidia/repos/flir/Video.avi";
// gst_init(&argc, &argv);
// pipeline = gst_parse_launch(test_context, NULL);
bool correct_execution = receiver(thermal_context);
if(correct_execution){
cout << "openCV - gstreamer works!" << endl;
} else {
cout << "openCV - gstreamer FAILED" << endl;
}
}
對于我測驗過的命令,錯誤是PipelinePlaying OpenCV | GStreamer 警告:GStreamer:管道尚未創建是持久的,如果我沒有定義 AppSink,上面顯示的錯誤會更改為打開 OpenCV | GStreamer 警告:在手動管道中找不到應用程式。從警告中我可以理解管道不完整或未正確創建但我不知道為什么,我遵循了我在網上找到的示例,它們不包含任何其他步驟。
此外,當直接使用 Gstreamer 管道可視化流時,當我嘗試打開本地視頻時,一切似乎都作業正常,但第一幀被凍結并且不顯示視頻,它只是停留在第一幀。你知道為什么會這樣嗎?使用 playbin uri 指向一個互聯網地址,一切正常......代碼是下一個:
#include <gst/gst.h>
#include <unistd.h> // for sleep function
#include <iostream>
using namespace std;
int main (int argc, char *argv[])
{
GstElement *pipeline;
GstBus *bus;
GstMessage *msg;
const char* context = "gstlaunch v udpsrc port=5000 caps=\"application/xrtp\" ! rtph264depay ! ffdec_h264 ! ffmpegcolorspace ! ximagesink sync=false";
const char* local_context = "gst-launch-1.0 -v playbin uri=file:///home/nvidia/repos/APPIDE/vidtest/THERMAL/thermalVideo.avi";
const char* test_context = "gstlaunch playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm";
// Initialize gstreamer
gst_init (&argc, &argv);
// Create C pipeline from terminal command (context)
pipeline = gst_parse_launch(local_context, NULL);
// Start the pipeline
gst_element_set_state(pipeline, GST_STATE_PLAYING);
// Wait until error or EOS
bus = gst_element_get_bus (pipeline);
gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));
/* Free resources */
if (msg != NULL)
gst_message_unref (msg);
// g_print(msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
}
uj5u.com熱心網友回復:
對于使用 gstreamer 后端,opencv VideoCapture 需要從源到應用程式接收器的有效管道字串(顏色的 BGR 格式)。
您的管道字串不正確,主要是因為它們以二進制命令(gstlaunch for gst-launch-1.0,playbin)開頭,您將在 shell 中使用它來運行這些命令。
您可以嘗試使用此管道從 RTP/UDP 讀取 H264 編碼的視頻,使用專用 HW NVDEC 解碼,然后在轉換為 BGRx 格式時從 NVMM 記憶體復制到系統記憶體,然后使用基于 CPU 的視頻轉換為 BGR 格式,如預期的那樣opencv 應用程式:
const char* context = "udpsrc port=5000 caps=application/x-rtp,media=video,encoding-name=H264 ! rtph264depay ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,format=BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink drop=1";
或者對于 uridecodebin,如果選擇了 NV 解碼器,則輸出可能在 NVMM 記憶體中,否則在系統記憶體中,因此以下 nvvidconv 實體首先復制到 NVMM 記憶體,然后第二個 nvvidconv 使用 HW 轉換為 BGRx 并輸出到系統記憶體:
const char* local_context = "uridecodebin uri=file:///home/nvidia/repos/APPIDE/vidtest/THERMAL/thermalVideo.avi ! nvvidconv ! video/x-raw(memory:NVMM) ! nvvidconv ! video/x-raw,format=BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink drop=1";
注意高解析度:
- 基于 CPU 的視頻轉換可能是一個瓶頸。啟用所有內核并提升時鐘。
- 根據您的 OpenCv 構建的圖形后端(GTK、QT4、QT5..),OpenCv imshow 可能不會那么快。在這種情況下,解決方案是使用 OpenCv Videowriter 使用 gstreamer 后端輸出到 gstreamer 視頻接收器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/420207.html
標籤:
上一篇:OpenCV深度繪圖
