ARM应用之瑞芯微RK3568上使用QT+Opencv

手上有一块RK3568板子,正好官方SDK提供了opencv和QT的环境,就整个QT+OPENCV的简单应用玩玩。老铁们可以从整个简单示例开始叠加复杂功能了。

  1. 配置编译文件

直接在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

  1. 处理图像

这里直接使用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);
    }
  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);
  1. 显示图像

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应用就完成了。工程附上,老铁们可以开始进阶了。

QT+Opencv的应用示例

猜你喜欢

转载自blog.csdn.net/huntenganwei/article/details/129533303