在虚拟机搭建好系统后,真正的使用才刚刚开始。
在使用摄像头的时候,首先看自己的摄像头插上去是显示jpeg的还是yuv的
yuv的要实现UVC转QImage转IplImage这样的流程才能使用,jpeg的好多人不会用说没用其实最好用了。一点不卡。yuv的有点卡。
我用的也是yuv以前朋友用的jpeg的摄像头。
代码是用的网上的一个代码修改的
1. [文件] videodevice.h ?
#ifndef VIDEODEVICE_H #define VIDEODEVICE_H #include <string.h> #include <stdlib.h> #include <errno.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <asm/types.h> #include <linux/videodev2.h> #include <QString> #include <QObject> #define CLEAR(x) memset(&(x), 0, sizeof(x)) class VideoDevice : public QObject { Q_OBJECT public : VideoDevice(QString dev_name); //VideoDevice(); int open_device(); int close_device(); int init_device(); int start_capturing(); int stop_capturing(); int uninit_device(); int get_frame( void **, size_t *); int unget_frame(); private : int init_mmap(); struct buffer { void * start; size_t length; }; QString dev_name; int fd; buffer* buffers; unsigned int n_buffers; int index; signals: void display_error(QString); }; #endif // VIDEODEVICE_H |
2. [文件] videodevice.cpp
#include "videodevice.h" VideoDevice::VideoDevice(QString dev_name) { this ->dev_name = dev_name; this ->fd = -1; this ->buffers = NULL; this ->n_buffers = 0; this ->index = -1; } int VideoDevice::open_device() { fd = open(dev_name.toStdString().c_str(), O_RDWR /*|O_NONBLOCK*/ , 0); // fd = open(dev_name.toStdString().c_str(), O_RDWR|O_NONBLOCK, 0); if (-1 == fd) { emit display_error(tr( "open: %1" ).arg(QString( strerror ( errno )))); return -1; } return 0; } int VideoDevice::close_device() { if (-1 == close(fd)) { emit display_error(tr( "close: %1" ).arg(QString( strerror ( errno )))); return -1; } return 0; } int VideoDevice::init_device() { v4l2_capability cap; v4l2_cropcap cropcap; v4l2_crop crop; v4l2_format fmt; if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) { if (EINVAL == errno ) { emit display_error(tr( "%1 is no V4l2 device" ).arg(dev_name)); } else { emit display_error(tr( "VIDIOC_QUERYCAP: %1" ).arg(QString( strerror ( errno )))); } return -1; } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { emit display_error(tr( "%1 is no video capture device" ).arg(dev_name)); return -1; } if (!(cap.capabilities & V4L2_CAP_STREAMING)) { emit display_error(tr( "%1 does not support streaming i/o" ).arg(dev_name)); return -1; } CLEAR(cropcap); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (0 == ioctl(fd, VIDIOC_CROPCAP, &cropcap)) { CLEAR(crop); crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; if (-1 == ioctl(fd, VIDIOC_S_CROP, &crop)) { if (EINVAL == errno ) { // emit display_error(tr("VIDIOC_S_CROP not supported")); } else { emit display_error(tr( "VIDIOC_S_CROP: %1" ).arg(QString( strerror ( errno )))); return -1; } } } else { emit display_error(tr( "VIDIOC_CROPCAP: %1" ).arg(QString( strerror ( errno )))); return -1; } CLEAR(fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = 640; fmt.fmt.pix.height = 480; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (-1 == ioctl(fd, VIDIOC_S_FMT, &fmt)) { emit display_error(tr( "VIDIOC_S_FMT" ).arg(QString( strerror ( errno )))); return -1; } if (-1 == init_mmap()) { return -1; } return 0; } int VideoDevice::init_mmap() { v4l2_requestbuffers req; CLEAR(req); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (-1 == ioctl(fd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno ) { emit display_error(tr( "%1 does not support memory mapping" ).arg(dev_name)); return -1; } else { emit display_error(tr( "VIDIOC_REQBUFS %1" ).arg(QString( strerror ( errno )))); return -1; } } if (req.count < 2) { emit display_error(tr( "Insufficient buffer memory on %1" ).arg(dev_name)); return -1; } buffers = (buffer*) calloc (req.count, sizeof (*buffers)); if (!buffers) { emit display_error(tr( "out of memory" )); return -1; } for (n_buffers = 0; n_buffers < req.count; ++n_buffers) { v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffers; if (-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf)) { emit display_error(tr( "VIDIOC_QUERYBUF: %1" ).arg(QString( strerror ( errno )))); return -1; } buffers[n_buffers].length = buf.length; buffers[n_buffers].start = mmap(NULL, // start anywhere buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (MAP_FAILED == buffers[n_buffers].start) { emit display_error(tr( "mmap %1" ).arg(QString( strerror ( errno )))); return -1; } } return 0; } int VideoDevice::start_capturing() { unsigned int i; for (i = 0; i < n_buffers; ++i) { v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory =V4L2_MEMORY_MMAP; buf.index = i; // fprintf(stderr, "n_buffers: %d\n", i); if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) { emit display_error(tr( "VIDIOC_QBUF: %1" ).arg(QString( strerror ( errno )))); return -1; } } v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) { emit display_error(tr( "VIDIOC_STREAMON: %1" ).arg(QString( strerror ( errno )))); return -1; } return 0; } int VideoDevice::stop_capturing() { v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) { emit display_error(tr( "VIDIOC_STREAMOFF: %1" ).arg(QString( strerror ( errno )))); return -1; } return 0; } int VideoDevice::uninit_device() { unsigned int i; for (i = 0; i < n_buffers; ++i) { if (-1 == munmap(buffers[i].start, buffers[i].length)) { emit display_error(tr( "munmap: %1" ).arg(QString( strerror ( errno )))); return -1; } } free (buffers); return 0; } int VideoDevice::get_frame( void **frame_buf, size_t * len) { v4l2_buffer queue_buf; CLEAR(queue_buf); queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; queue_buf.memory = V4L2_MEMORY_MMAP; if (-1 == ioctl(fd, VIDIOC_DQBUF, &queue_buf)) { switch ( errno ) { case EAGAIN: // perror("dqbuf"); return -1; case EIO: return -1 ; default : emit display_error(tr( "VIDIOC_DQBUF: %1" ).arg(QString( strerror ( errno )))); return -1; } } *frame_buf = buffers[queue_buf.index].start; *len = buffers[queue_buf.index].length; index = queue_buf.index; return 0; } int VideoDevice::unget_frame() { if (index != -1) { v4l2_buffer queue_buf; CLEAR(queue_buf); queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; queue_buf.memory = V4L2_MEMORY_MMAP; queue_buf.index = index; if (-1 == ioctl(fd, VIDIOC_QBUF, &queue_buf)) { emit display_error(tr( "VIDIOC_QBUF: %1" ).arg(QString( strerror ( errno )))); return -1; } return 0; } return -1; } |
3. [文件] processImage.h
#ifndef PROCESSIMAGE_H #define PROCESSIMAGE_H #include <QtGui> #include "videodevice.h" class ProcessImage : public QWidget { Q_OBJECT public : ProcessImage(QWidget *parent=0); ~ProcessImage(); private : QPainter *painter; QLabel *label; QImage *frame; //QPixmap *frame; QTimer *timer; int rs; uchar *pp; uchar * p; unsigned int len; int convert_yuv_to_rgb_pixel( int y, int u, int v); int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height); VideoDevice *vd; private slots: void paintEvent(QPaintEvent *); void display_error(QString err); }; #endif |
4. [文件] processImage.cpp
#include <QtGui> #include "processImage.h" #include "videodevice.h" extern "C" { #include <stdio.h> #include <stdlib.h> } ProcessImage::ProcessImage(QWidget *parent):QWidget(parent) { pp = (unsigned char *) malloc (640 * 480 /*QWidget::width()*QWidget::height()*/ * 3 * sizeof ( char )); painter = new QPainter( this ); frame = new QImage(pp,640,480,QImage::Format_RGB888); // frame = new QPixmap(640,320); label = new QLabel(); vd = new VideoDevice(tr( "/dev/video0" )); connect(vd, SIGNAL(display_error(QString)), this ,SLOT(display_error(QString))); rs = vd->open_device(); if (-1==rs) { QMessageBox::warning( this ,tr( "error" ),tr( "open /dev/dsp error" ),QMessageBox::Yes); vd->close_device(); } rs = vd->init_device(); if (-1==rs) { QMessageBox::warning( this ,tr( "error" ),tr( "init failed" ),QMessageBox::Yes); vd->close_device(); } rs = vd->start_capturing(); if (-1==rs) { QMessageBox::warning( this ,tr( "error" ),tr( "start capture failed" ),QMessageBox::Yes); vd->close_device(); } if (-1==rs) { QMessageBox::warning( this ,tr( "error" ),tr( "get frame failed" ),QMessageBox::Yes); vd->stop_capturing(); } timer = new QTimer( this ); connect(timer,SIGNAL(timeout()), this ,SLOT(update())); timer->start(30); QHBoxLayout *hLayout = new QHBoxLayout(); hLayout->addWidget(label); setLayout(hLayout); setWindowTitle(tr( "Capture" )); } ProcessImage::~ProcessImage() { rs = vd->stop_capturing(); rs = vd->uninit_device(); rs = vd->close_device(); } void ProcessImage::paintEvent(QPaintEvent *) { rs = vd->get_frame(( void **)&p,&len); convert_yuv_to_rgb_buffer(p,pp,640,480 /*QWidget::width(),QWidget::height()*/ ); frame->loadFromData((uchar *)pp, /*len*/ 640 * 480 * 3 * sizeof ( char )); // painter->begin(this); // painter->drawImage(0,0,*frame); // painter->end(); // rs = vd->unget_frame(); // frame->load("./img3.jpg"); label->setPixmap(QPixmap::fromImage(*frame,Qt::AutoColor)); // label->show(); rs = vd->unget_frame(); // label->drawFrame(); // QPixmap *pixImage = new QPixmap(); // pixImage->loadFromData((uchar *)pp,sizeof(pp),0,Qt::AutoColor); // QPainter painter(this); // painter.begin(this); // painter.drawPixmap(0,0,QWidget::width(),QWidget::height(),*pixImage); // painter.end(); } void ProcessImage::display_error(QString err) { QMessageBox::warning( this ,tr( "error" ), err,QMessageBox::Yes); } /*yuv格式转换为rgb格式*/ int ProcessImage::convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height) { unsigned int in, out = 0; unsigned int pixel_16; unsigned char pixel_24[3]; unsigned int pixel32; int y0, u, y1, v; for (in = 0; in < width * height * 2; in += 4) { pixel_16 = yuv[in + 3] << 24 | yuv[in + 2] << 16 | yuv[in + 1] << 8 | yuv[in + 0]; y0 = (pixel_16 & 0x000000ff); u = (pixel_16 & 0x0000ff00) >> 8; y1 = (pixel_16 & 0x00ff0000) >> 16; v = (pixel_16 & 0xff000000) >> 24; pixel32 = convert_yuv_to_rgb_pixel(y0, u, v); pixel_24[0] = (pixel32 & 0x000000ff); pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; rgb[out++] = pixel_24[0]; rgb[out++] = pixel_24[1]; rgb[out++] = pixel_24[2]; pixel32 = convert_yuv_to_rgb_pixel(y1, u, v); pixel_24[0] = (pixel32 & 0x000000ff); pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; rgb[out++] = pixel_24[0]; rgb[out++] = pixel_24[1]; rgb[out++] = pixel_24[2]; } return 0; } int ProcessImage::convert_yuv_to_rgb_pixel( int y, int u, int v) { unsigned int pixel32 = 0; unsigned char *pixel = (unsigned char *)&pixel32; int r, g, b; r = y + (1.370705 * (v-128)); g = y - (0.698001 * (v-128)) - (0.337633 * (u-128)); b = y + (1.732446 * (u-128)); if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; pixel[0] = r * 220 / 256; pixel[1] = g * 220 / 256; pixel[2] = b * 220 / 256; return pixel32; } /*yuv格式转换为rgb格式*/ |
5. [文件] main.cpp
#include <QtGui> #include "processImage.h" int main( int argc, char *argv[]) { QApplication app(argc,argv); ProcessImage process; process.resize(640,480); process.show(); return app.exec(); } |
可以复制也可以到我的资源里去找有的我上传了字库的移植,还有这个代码。
先在虚拟机上跑起来一般没问题 记得设备号在虚拟机为/dev/video0 至于虚拟机用摄像头看我别的博文
跑好了再交叉编译记得改设备号为/dev/video2具体的看你自己插拔摄像头在dev里是哪个。
然后有的人直接可以使用了,但是有的一堆问题的我就是
第一个问题::s3c-fimc: invalid target size
把这句话添加进去就没有问题了
fmt.fmt.pix.priv=1;
这句话加在cpp里的有个地方差不多全是这种。
第二个问题就是 :: segmentation fault
我够倒霉的全遇到了 解决花了一周。最后没办法我单步调试的
在in=155644的时候就会出现我看了下大小计算发现问题出在640*480上面,容易内存溢出,我改成320*240就不会超过155644了这样问题就解决了。
当时还有点小激动呢。图片小了你可以用opencv再放大的。
最后开发板图像出来了 这里不拍照随便拿个把
需要的到我资源里下载代码 字库什么的