C++下开发Opencv需要进行一些额外的配置,先看一下opencv的文件位置。Jetson Nano预装的Opencv4.1.1的头文件位置如下图所示:
库文件位置如下图所示:
只需要在Qt的pro文件中将上述两个目录包含进来。另外注意头文件和lib文件的添加方法。
QT的pro文件如下:
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
CONFIG += C++11 # 添加对C++11的支持
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
INCLUDEPATH += /usr/include/opencv4 #添加头文件路径
LIBS += -L/usr/lib/aarch64-linux-gnu -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_objdetect #添加需要链接的库
SOURCES += main.cpp
重新生成整个项目,然后将test.jpeg和haarcascade_frontalface_default.xml文件放置在编译生成的build-QTtest-unknown-Debug文件夹中,运行项目效果图如下所示:
使用C++编程读取CSI摄像头,可以看到已经可以正常的显示视频流图像了,但是由于树莓派摄像头本身的原因,其图像中还有很多的噪点,颜色也有些失真(真实工业场景中建议购买更好的摄像头)。C++版本的main.cpp文件如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
string gstreamer_pipeline (int capture_width, int capture_height, int display_width, int display_height, int framerate, int flip_method)
{
return "nvarguscamerasrc ! video/x-raw(memory:NVMM), width=(int)" + to_string(capture_width) + ", height=(int)" +
to_string(capture_height) + ", format=(string)NV12, framerate=(fraction)" + to_string(framerate) +
"/1 ! nvvidconv flip-method=" + to_string(flip_method) + " ! video/x-raw, width=(int)" + to_string(display_width) + ", height=(int)" +
to_string(display_height) + ", format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink";
}
int main( int argc, char** argv )
{
int capture_width = 1280 ;
int capture_height = 720 ;
int display_width = 1280 ;
int display_height = 720 ;
int framerate = 60 ;
int flip_method = 0 ;
//创建管道
string pipeline = gstreamer_pipeline(capture_width,
capture_height,
display_width,
display_height,
framerate,
flip_method);
std::cout << "使用gstreamer管道: \n\t" << pipeline << "\n";
//管道与视频流绑定
VideoCapture cap(pipeline, CAP_GSTREAMER);
if(!cap.isOpened())
{
std::cout<<"打开摄像头失败."<<std::endl;
return (-1);
}
//创建显示窗口
namedWindow("CSI Camera", WINDOW_AUTOSIZE);
Mat img;
//逐帧显示
while(true)
{
if (!cap.read(img))
{
std::cout<<"捕获失败"<<std::endl;
break;
}
int new_width,new_height,width,height,channel;
width=img.cols;
height=img.rows;
channel=img.channels();
//调整图像大小
new_width=640;
if(width>800)
{
new_height=int(new_width*1.0/width*height);
}
resize(img, img, cv::Size(new_width, new_height));
imshow("CSI Camera",img);
int keycode = cv::waitKey(30) & 0xff ; //ESC键退出
if (keycode == 27) break ;
}
cap.release();
destroyAllWindows() ;
}
其中需要额外的添加opencv用于视频处理的头文件#include
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
CONFIG += C++11 # 添加对C++11的支持
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
INCLUDEPATH += /usr/include/opencv4 #添加头文件路径
LIBS += -L/usr/lib/aarch64-linux-gnu -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_objdetect -lopencv_videoio #添加需要链接的库
SOURCES += main.cpp
本小节将使用Opencv实现二维码检测和识读功能。在opencv4.0以后,已经集成了二维码识读模块,因此,我们可以采用最新的opencv来实现二维码检测和识读。二维码检测和识别主要分为3步:使用QRCodeDetector()函数创建二维码检测器;使用detectAndDecode函数对图像进行二维码检测和识别;将检测结果输出。main.cpp文件如下
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
string gstreamer_pipeline (int capture_width, int capture_height, int display_width, int display_height, int framerate, int flip_method)
{
return "nvarguscamerasrc ! video/x-raw(memory:NVMM), width=(int)" + to_string(capture_width) + ", height=(int)" +
to_string(capture_height) + ", format=(string)NV12, framerate=(fraction)" + to_string(framerate) +
"/1 ! nvvidconv flip-method=" + to_string(flip_method) + " ! video/x-raw, width=(int)" + to_string(display_width) + ", height=(int)" +
to_string(display_height) + ", format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink";
}
int main( int argc, char** argv )
{
int capture_width = 1280 ;
int capture_height = 720 ;
int display_width = 1280 ;
int display_height = 720 ;
int framerate = 60 ;
int flip_method = 0 ;
//创建管道
string pipeline = gstreamer_pipeline(capture_width,
capture_height,
display_width,
display_height,
framerate,
flip_method);
std::cout << "使用gstreamer管道: \n\t" << pipeline << "\n";
//管道与视频流绑定
VideoCapture cap(pipeline, CAP_GSTREAMER);
if(!cap.isOpened())
{
std::cout<<"打开摄像头失败."<<std::endl;
return (-1);
}
//创建显示窗口
namedWindow("CSI Camera", WINDOW_AUTOSIZE);
Mat img;
//创建二维码检测器
QRCodeDetector qrDecoder = QRCodeDetector();
//逐帧显示
while(true)
{
if (!cap.read(img))
{
std::cout<<"捕获失败"<<std::endl;
break;
}
int new_width,new_height,width,height,channel;
width=img.cols;
height=img.rows;
channel=img.channels();
//调整图像大小
new_width=640;
if(width>800)
{
new_height=int(new_width*1.0/width*height);
}
resize(img, img, cv::Size(new_width, new_height));
//二维码检测和识读
Mat bbox, rectifiedImage;
std::string data = qrDecoder.detectAndDecode(img, bbox, rectifiedImage);
if(data.length()>0)
{
cout << "解码数据: " << data << endl;
int n = bbox.rows;
for(int i = 0 ; i < n ; i++)
{
line(img, Point2i(bbox.at<float>(i,0),bbox.at<float>(i,1)), Point2i(bbox.at<float>((i+1) % n,0), bbox.at<float>((i+1) % n,1)), Scalar(255,0,0), 3);
}
}
else
cout << "没有检测到二维码" << endl;
imshow("CSI Camera",img);
int keycode = cv::waitKey(30) & 0xff ; //ESC键退出
if (keycode == 27) break ;
}
cap.release();
destroyAllWindows() ;
}