在jetson nano这样的嵌入式设备上,用opencv拉流,并在实时视频上面,显示汉字。
关于使用opencv/c++显示中文,网上文章分为两种:
本人没有学过qt,因此找到一种取巧的办法,在win上生成中文图片,再将该图片蒙皮到视频帧,形成视频上有中文的效果。
在windows上打开ppt,创建空白页面,选择“插入”–>“文本框”,选择“横排文本框”,创建一个文本框,里面填入你需要的中文。
将文本框的背景设置为白色,字体设置为红色(后面展示的字体就是红色的)。然后右键文本框,将该文本框保存为hanzi.png图片。
其中,需要注意的是,
蒙皮简易代码参考博客:《opencv3/C++视频中叠加透明图片的实现》
mkdir ~/test_rtsp
cd test_rtsp
将上述文本框图片hanzi.png复制到该项目目录下。
在项目目录test_rtsp下创建 CMakeLists.txt 和 test_rtsp.cpp,
touch CMakeLists.txt
touch test_rtsp.cpp
在CMakeLists.txt中添加如下内容:
cmake_minimum_required(VERSION 2.12)
project(DisplayRTSP)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenCV REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
add_executable(test_rtsp test_rtsp.cpp)
target_link_libraries(test_rtsp ${OpenCV_LIBS})
在test_rtsp.cpp中添加如下内容:
// video_test.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "time.h"
static std::mutex mut;
static std::atomic_bool isOpen;
using namespace cv;
using namespace std;
static void frame_get(cv::Mat* pFrame, const std::string& adm, const std::string& pwd, const std::string& ip)
{
cv::VideoCapture capture("rtsp://"+adm+":"+pwd+"@"+ip);
if (!capture.isOpened()) {
std::cout << "------reconnecting---------" << ip << std::endl;
isOpen = false;
}
cv::Mat frame;
while (isOpen) {
capture >> frame;
if (mut.try_lock()) {
frame.copyTo(*pFrame);
mut.unlock();
}
cv::waitKey(5);
}
capture.release();
}
int main(int argc, char* argv[])
{
cv::setNumThreads(1);
isOpen = true;
cv::Mat frame, temp_frame;
// 填入摄像头账号,我的为admin
std::string adm = "admin";
//填入摄像头密码,
std::string pwd = "xxx";
//填入摄像头ip
std::string ip = "192.168.20.22";
std::thread t(frame_get, &frame, adm, pwd, ip);
//视频窗口设置
cv::namedWindow(ip, cv::WINDOW_NORMAL);
//cv::setWindowProperty(ip, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
cv::moveWindow(ip, 10, 10);
cv::resizeWindow(ip, 1900, 1000);
//给显示窗口分配一个线程,确保其正常运行
cv::startWindowThread();
//filename为hanzi.png的绝对路径
std::string filename = "/home/aaeon/work/wangxin/test_rtsp1/hanzi.png";
//cv::Mat png = cv::imread(filename);
//以下过程为蒙皮的准备过程,filename为hanzi.png的绝对路径
//imread(filename, 0),其中0为取图片的灰度图
cv::Mat graypng = cv::imread(filename, 0);
//cv::threshold中的150为区别hanzi.png中的红色字体和白色背景的阈值;红色的灰度值为255/2.0
//此时graypng中,汉字为黑色,背景为白色
cv::threshold(graypng, graypng, 150, 255, cv::THRESH_BINARY);
//此时mask中,汉字为白色,背景为黑色
cv::Mat mask = 255 - graypng;
//png为hanzi.png原图
cv::Mat png = cv::imread(filename);
cv::Mat imROI;
while (isOpen) {
mut.lock();
frame.copyTo(temp_frame);
mut.unlock();
if (temp_frame.empty()) {
continue;
}
std::cout << "cols: " << temp_frame.cols << ", rows: " << temp_frame.rows << "\n";
// 以下两行代码为蒙皮的处理过程
imROI = temp_frame(cv::Rect(100, 100, png.cols, png.rows));
//cv::imshow("imROI", imROI);
png.copyTo(imROI, mask);
cv::imshow(ip, temp_frame);
cv::waitKey(100);
if (cv::waitKey(1) == 'q') {
break;
}
}
cv::destroyAllWindows();
isOpen = false;
t.join();
return 0;
}
aaeon@aaeon-desktop:~/work/wangxin/test_rtsp1$ vim test_rtsp.cpp
if (mut.try_lock()) {
frame.copyTo(*pFrame);
mut.unlock();
}
cv::waitKey(5);
}
capture.release();
}
其中,我做注释的地方,都需要注意下,尤其是涉及摄像头账号、密码、ip等信息,需要你自己填写。
在项目目录test_rtsp下,
cd ~/test_rtsp
mkdir build
cd build
cmake ..
make
./test_rtsp