手上有一块RK3568板子,正好官方SDK提供了opencv和QT的环境,就整个QT+OPENCV的简单应用玩玩。老铁们可以从整个简单示例开始叠加复杂功能了。
配置编译文件
直接在qt的配置文件中添加opencv库即可。
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = usbcamera_gui
TEMPLATE = app
#LIBS += -L. -ljpeg
CONFIG +=gnu++11 -Wl,--allow-shlib-undefined
LIBS += -L. -lopencv_core -lopencv_objdetect -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgproc -lopencv_imgcodecs -lrknn_api -lOpenCL -lpthread
QTPLUGIN += qjpeg
LIBS += -L../../../../../../tools/pack/chips/sun8iw11p1/hal/gpu/fbdev/lib/ -lGLESv2
SOURCES += main.cpp\
camera.cpp
HEADERS += camera.h
FORMS += camera.ui
处理图像
这里直接使用USB采集的图像进行处理。通过ioctl配置参数。就取了个640*480分辨来看看效果。
int camera::camera_init()
{
int ret=0,i=0,count=0;
struct v4l2_capability cap;
struct v4l2_fmtdesc fmtdesc;
struct v4l2_format format;
struct v4l2_requestbuffers reqbuf;
struct v4l2_buffer buf;
fmtdesc.index = 0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ::ioctl(fd, VIDIOC_G_FMT, &format);
if(ret < 0){
perror("VIDIOC_G_FMT");
exit(1);
}
printf("width:%d\n", format.fmt.pix.width);
printf("height:%d\n", format.fmt.pix.height);
printf("pixelformat:%x\n", format.fmt.pix.pixelformat);
printf("field:%x\n", format.fmt.pix.field);
printf("bytesperline:%d\n", format.fmt.pix.bytesperline);
printf("sizeimage:%d\n", format.fmt.pix.sizeimage);
printf("colorspace:%d\n", format.fmt.pix.colorspace);
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = 640;
format.fmt.pix.height = 480;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
ret = ::ioctl(fd, VIDIOC_S_FMT, &format);
if(ret < 0){
fprintf(stderr, "Not support jepg");
perror("VIDIOC_S_FMT");
exit(1);
}
reqbuf.count = 3;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
ret = ::ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
if(ret < 0){
perror("VIDIOC_REQBUFS");
exit(1);
}
bufinf = (struct bufinfor *)calloc(reqbuf.count, sizeof(struct bufinfor));
if(!bufinf){
perror("calloc");
exit(1);
}
for(count = 0; count < reqbuf.count; count++){
buf.index = count;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ::ioctl(fd, VIDIOC_QUERYBUF, &buf);
if(ret < 0){
perror("VIDIOC_REQBUFS");
exit(1);
}
bufinf[buf.index].length = buf.length;
bufinf[buf.index].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if(!(bufinf[buf.index].start)){
perror("mmap");
exit(1);
}
}
for(i = 0; i < reqbuf.count; i++){
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ::ioctl(fd, VIDIOC_QBUF, &buf);
if(ret < 0){
perror("VIDIOC_QBUF");
exit(1);
}
}
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ::ioctl(fd, VIDIOC_STREAMON, &type);
if(ret < 0){
perror("VIDIOC_STREAMON");
exit(1);
}
return 0;
}
还是通过ioctl映射出原始的图像数据,这里将图像的YUV数据转为bgr。在opencv中一般输入的是bgr图像进行处理。
unsigned char *bgr=new unsigned char [640 * 480 *3];
struct v4l2_buffer buf;
fd_set readset;
FD_ZERO(&readset);
FD_SET(fd, &readset);
ret = select(fd + 1, &readset, NULL, NULL, NULL);
if(ret < 0){
perror("select");
exit(1);
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_DQBUF, &buf);
if(ret < 0){
perror("VIDIOC_DQBUF");
exit(1);
}
convert_yuv_to_bgr_buffer((unsigned char *)bufinf[buf.index].start,bgr,640,480);
ret = ioctl(fd, VIDIOC_QBUF, &buf);
if(ret < 0){
perror("VIDIOC_QBUF");
exit(1);
}
处理图像
将bgr数据导入Mat数据,注意opencv中使用的是行和列,即cols和rows,cols就是图像的宽度width,rows就是图像的高度height。所以这里是480, 640。下面就是opencv的常规操作了。
Mat img = Mat(480, 640, CV_8UC3, bgr, 0);
Mat dstImage, edge, grayImage;
dstImage.create(img.size(), img.type() );
cvtColor(img, grayImage, CV_BGR2GRAY);
blur(grayImage, edge, Size(3,3) );
Canny(edge, edge, 10, 30, 3 );
cvtColor(edge, dstImage, CV_GRAY2BGR);
addWeighted(img, 1, dstImage, 0.5, 1, img);
putText(img, "QT+OPENCV", Point(120,100),FONT_HERSHEY_TRIPLEX,2,0,2,8);
显示图像
QT一般使用的是RGB图像,所以注意得转换一下,不然那颜色就反了。将Mat图像数据转为QImage即可。
cvtColor(img, dstImage, CV_BGR2RGB);
QImage *mage = new QImage(dstImage.data,640,480,QImage::Format_RGB888);
QImage resultimg=mage->scaled(ui->label->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation);
ui->label->setPixmap(QPixmap::fromImage(resultimg, Qt::AutoColor));
如此一个简易的QT+Opencv应用就完成了。工程附上,老铁们可以开始进阶了。文章来源:https://www.toymoban.com/news/detail-533663.html
QT+Opencv的应用示例文章来源地址https://www.toymoban.com/news/detail-533663.html
到了这里,关于ARM应用之瑞芯微RK3568上使用QT+Opencv的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!