技术专栏
nvidia xavier nx平台OpenCV对接硬件编码器
1. 前言
尝试在xavier nx平台做图像处理应用
应用摘要如下
1.捕捉摄像头设备
2.颜色转换格式
3.图像处理
4.编码与HW编码器
1~3使用OpenCV实现
我想实现的是通过图像处理的结果(例如。覆盖图像与边框)到HW编码器。
我引用了jetson_multimedia_api_reference,但是混淆了
HW: JetsonNX开发工具包,SW: Jetpack4.4
2. 参考python示例 & patch
import sys
import cv2
def read_cam():
cap = cv2.VideoCapture("filesrc location=/home/nvidia/sample_1080p_h264.mp4 ! qtdemux ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw, format=BGRx ! videoconvert ! video/x-raw,format=BGR ! appsink ")
w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
print('Src opened, %dx%d @ %d fps' % (w, h, fps))
gst_out = "appsrc ! video/x-raw, format=BGR ! queue ! videoconvert ! video/x-raw,format=BGRx ! nvvidconv ! nvv4l2h264enc ! h264parse ! matroskamux ! filesink location=test.mkv "
out = cv2.VideoWriter(gst_out, cv2.CAP_GSTREAMER, 0, float(fps), (int(w), int(h)))
if not out.isOpened():
print("Failed to open output")
exit()
if cap.isOpened():
while True:
ret_val, img = cap.read();
if not ret_val:
break;
out.write(img);
cv2.waitKey(1)
else:
print "pipeline open failed"
print("successfully exit")
cap.release()
out.release()
if __name__ == '__main__':
read_cam()
但现在需要拿编码器输出的数据进行后期处理
考虑使用多媒体api
参考以下patch
diff --git a/multimedia_api/ll_samples/samples/13_multi_camera/main.cpp b/multimedia_api/ll_samples/samples/13_multi_camera/main.cpp
index 49a9ab8..0613f0b 100644
--- a/multimedia_api/ll_samples/samples/13_multi_camera/main.cpp
+++ b/multimedia_api/ll_samples/samples/13_multi_camera/main.cpp
@@ -39,6 +39,8 @@
#include <stdio.h>
#include <stdlib.h>
+#include <opencv2/opencv.hpp>
+
using namespace Argus;
using namespace EGLStream;
@@ -259,7 +261,7 @@ bool ConsumerThread::threadInitialize()
input_params.width = STREAM_SIZE.width();
input_params.height = STREAM_SIZE.height();
input_params.layout = NvBufferLayout_Pitch;
- input_params.colorFormat = NvBufferColorFormat_NV12;
+ input_params.colorFormat = NvBufferColorFormat_ABGR32;
input_params.nvbuf_tag = NvBufferTag_VIDEO_CONVERT;
NvBufferCreateEx (&m_compositedFrame, &input_params);
@@ -333,8 +335,8 @@ bool ConsumerThread::threadExecute()
if (!m_dmabufs[i])
{
m_dmabufs[i] = iNativeBuffer->createNvBuffer(iEglOutputStreams[i]->getResolution(),
- NvBufferColorFormat_YUV420,
- NvBufferLayout_BlockLinear);
+ NvBufferColorFormat_ABGR32,
+ NvBufferLayout_Pitch);
if (!m_dmabufs[i])
CONSUMER_PRINT("\tFailed to create NvBuffer\n");
}
@@ -349,7 +351,21 @@ bool ConsumerThread::threadExecute()
{
// Composite multiple input to one frame
NvBufferComposite(m_dmabufs, m_compositedFrame, &m_compositeParam);
- g_renderer->render(m_compositedFrame);
+ void *pdata = NULL;
+
+ NvBufferMemMap(m_compositedFrame, 0, NvBufferMem_Read, &pdata);
+ NvBufferMemSyncForCpu(m_compositedFrame, 0, &pdata);
+
+ cv::Mat imgbuf = cv::Mat(STREAM_SIZE.height(),
+ STREAM_SIZE.width(),
+ CV_8UC4, pdata);
+ cv::Mat display_img;
+ cvtColor(imgbuf, display_img, CV_RGBA2BGR);
+
+ NvBufferMemUnMap(m_compositedFrame, 0, &pdata);
+
+ cv::imshow("img", display_img);
+ cv::waitKey(1);
}
else
g_renderer->render(m_dmabufs[0]);
Makefile:
+CPPFLAGS+=`pkg-config --cflags opencv`
+LDFLAGS+=`pkg-config --libs opencv`
3. OpenCV安装方法
1不要通过Jetpack安装OpenCV 3.3.1。默认安装。请取消勾选OpenCV 3.3.1
2 Jetpack将禁止安装样例包,如果你不选中OpenCV,请从
https://developer.nvidia.com/embedded/dlc/multimedia-api-r2821 2
3获取脚本https://github.com/AastaNV/JEP/blob/master/script/install_opencv3.4.0_TX2.sh
4执行脚本
mkdir OpenCV
$ ./install_opencv3.4.0_TX2.sh OpenCV
5应用补丁并重建09_camera_jpeg_capture
6运行
$ export DISPLAY=:0
09_camera_jpeg_capture$ ./camera_jpeg_capture --disable-jpg --cap-time 10
4. V4L2架构参考sample
参考12_camera_v4l2_cuda。
该示例用于v4l2采集
5. gstreamer示例
在opencv中,可以像VideoWriter一样使用gstreamer管道
/ Get resolution and framerate from capture
unsigned int width = cap.get (cv::CAP_PROP_FRAME_WIDTH);
unsigned int height = cap.get (cv::CAP_PROP_FRAME_HEIGHT);
unsigned int fps = cap.get (cv::CAP_PROP_FPS);
// Create the writer with gstreamer pipeline encoding into H264, muxing into mkv container and saving to file
cv::VideoWriter gst_nvh264_writer("appsrc ! queue ! videoconvert ! video/x-raw,format=BGRx ! nvvidconv ! nvv4l2h264enc ! video/x-h264,format=byte-stream ! h264parse ! matroskamux ! filesink location=test-nvh264-writer.mkv ", 0, fps, cv::Size (width, height));
if (!gst_nvh264_writer.isOpened ()) {
std::cout << "Failed to open gst_nvh264 writer." << std::endl;
return (-6);
}
在循环中,使用以下命令推送处理过的帧(每个捕获帧一个):
gst_nvh264_writer.write(frame);
6. NvVideoEncoder
考虑在MMAPI中使用NvVideoEncoder
需要创建NvBuffer和复制cv::Mat数据到它。
方法如下:
1. 创建导入cv::Mat(ARGB32)的NvBuffer
2. 为YUV420M创建匹配编码器 输入格式的NvBuffer。
3. 创建NvVideoEncoder
4. 编码器输出平面缓冲区的出队列
5. 将ARGB转换为YUV420M
尝试将cv::Mat转换成NvBuffer
如果par.num_planes = 1,这是正确的
但这种方法似乎是无效的
cv::Mat src = cv::Mat::zeros(height, width, CV_8UC4);
ret = NvBufferGetParams(fd, par); //fd is V4L2_PIX_FMT_ABGR32
for( unsigned int plane = 0; plane < par.num_planes; plane++){
ret = NvBufferMemMap(fd, plane, NvBufferMem_Write, &vaddr); // vaddr is void*
if(ret == 0){
for( unsigned int i = 0; i < par.height[plane]; i++){
memcpy((uint8_t *)vaddr + i *par.pitch[plane], src.data[ i * src.step], src.width * sizeof((uint8_t)) * 4);
}
}
NvBufferMemSyncForDevice (fd, plane, &vaddr);
}
7. CUDA过滤器
因为OpenCV的主要格式是BGR,在Jetson平台上并不支持BGR。
在处理之后,需要将其转换为RGBA,复制到NvBuffer,转换到YUV420并进行编码。
它可能不会带来好的性能。
有CUDA过滤器可以应用于RGBA缓冲区。
如果能在用例中使用CUDA过滤器,性能会更好
函数调用如下:
//CUDA postprocess
{
EGLImageKHR egl_image;
egl_image = NvEGLImageFromFd(egl_display, dmabuf_fd);
CUresult status;
CUeglFrame eglFrame;
CUgraphicsResource pResource = NULL;
cudaFree(0);
status = cuGraphicsEGLRegisterImage(&pResource,
egl_image,
CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
if (status != CUDA_SUCCESS)
{
printf("cuGraphicsEGLRegisterImage failed: %d \n",status);
}
status = cuGraphicsResourceGetMappedEglFrame(&eglFrame, pResource, 0, 0);
status = cuCtxSynchronize();
if (create_filter) {
filter = cv::cuda::createSobelFilter(CV_8UC4, CV_8UC4, 1, 0, 3, 1, cv::BORDER_DEFAULT);
//filter = cv::cuda::createGaussianFilter(CV_8UC4, CV_8UC4, cv::Size(31,31), 0, 0, cv::BORDER_DEFAULT);
create_filter = false;
}
cv::cuda::GpuMat d_mat(h, w, CV_8UC4, eglFrame.frame.pPitch[0]);
filter->apply (d_mat, d_mat);
status = cuCtxSynchronize();
status = cuGraphicsUnregisterResource(pResource);
NvDestroyEGLImage(egl_display, egl_image);
}
dmabuf_fd是RGBA格式。
经过处理后,可以将其转换回NV12并发送给硬件编码器。
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包
92
5
评论
打赏
- 分享
- 举报
评论
0个
手气红包
暂无数据
相关专栏
-
浏览量:8590次2021-05-14 14:43:43
-
浏览量:9457次2021-05-26 14:17:15
-
浏览量:7420次2021-05-11 17:51:48
-
浏览量:9413次2021-04-27 17:56:41
-
浏览量:5907次2021-05-28 13:52:17
-
浏览量:10853次2021-05-06 16:22:01
-
2021-05-06 16:03:00
-
浏览量:5250次2021-05-10 17:48:42
-
浏览量:7088次2021-05-11 17:04:57
-
浏览量:9390次2021-05-25 17:31:40
-
浏览量:7912次2021-05-25 15:32:16
-
浏览量:7086次2021-05-20 16:37:42
-
浏览量:9224次2021-05-19 17:32:00
-
浏览量:7485次2021-05-20 17:08:14
-
浏览量:621次2023-10-30 15:19:41
-
浏览量:11395次2020-12-12 18:07:34
-
2021-04-23 15:54:21
-
浏览量:6455次2021-04-21 17:42:58
-
浏览量:7941次2021-06-04 16:25:58
切换马甲
上一页
下一页
打赏用户
共 1 位
我要创作
分享技术经验,可获取创作收益
分类专栏
-
178篇
热门专栏
- AI 艺术画廊 —— 用 AI 诠释艺术与音乐 十三
- 在1080p屏幕上开启4K!DSR技术及使用详解
- xavier nx 平台 EQOS LAN端口连接异常问题调试1
- NVIDIA GRID成为Synergy大会热门话题
- TITAN BLACK梦幻作品!GeForce Garage交叉书桌打造日志
- nvidia xavier nx平台修改CAN时钟调试
- nvidia nx平台局域网唤醒问题2
- 初创加速 | NVIDIA GPU加速AI智能数据处理,助力数字化医、药、险联动
- NVIDIA入选道琼斯可持续发展指数榜单前五名
- NVIDIA Tegra K1设备包揽Futuremark 12月GPU榜单前三甲!
置顶时间设置
结束时间
删除原因
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
打赏作者
free-jdx
您的支持将鼓励我继续创作!
打赏金额:
¥1
¥5
¥10
¥50
¥100
支付方式:
微信支付
打赏成功!
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
审核成功
发布时间设置
发布时间:
请选择发布时间设置
是否关联周任务-专栏模块
审核失败
失败原因
请选择失败原因
备注
请输入备注