qt uvc摄像头开发

急需在windows环境下的qt对UVC摄像头的开发源码,并且运行环境是64位的,只需实现简单拍照功能即可,但图片要求可以用opencv进行处理和计算。


cam.h  代码

#ifndef __CAM_H_
#define __CAM_H_
#include iostream>
#include sys/ioctl.h>
#include fcntl.h>
#include linux/videodev2.h>
#include sys/mman.h>
#include stdio.h>
#include string.h>
#include errno.h>
#include unistd.h>
#include QTimer>


using namespace std;

#define WEIGHT_DEFAULT 640
#define HEIGHT_DEFAULT 480

#define PROP_WEIGHT 0
#define PROP_HEIGHT 1
#define PROP_FPS 2

#define PROP_BRIGHTNESS 10
#define PROP_CONTRAST 11
#define PROP_HUE 12
#define PROP_GAIN 13
#define PROP_EXPOSURE 14

#define BUFFER_NUMS 2


#define STREAMON  true
#define STREAMOFF false

#define CLEAR(x) memset (&(x), 0, sizeof (x))




typedef unsigned char uchar;//#define uchar unsigned char //

class Opera_Cam
{
public:
Opera_Cam();
Opera_Cam(int which_cam);
Opera_Cam(const string& cam_name);
bool Open(int which_cam=0);
bool Open(const string& cam_name);
bool IsOpened(){return Opened;}
bool Read();//(uchar **data, int& used_len);
bool Set(int propId, int value);
int Get(int propId);
int GetDataLen(){return data_len;};
//Opera_Cam& operator>>(uchar **dst);
virtual ~Opera_Cam();

struct DataInfo
{
uchar *data;
int real_len;
};

DataInfo df;
       int weight,height;

       void Free();

private:
void Init_Prop();
   bool Init_V4l2();
bool Operation(bool on_off);
void GetFrameLoop();
int GetFrameV4l2();

  //unsigned char* rgbbuf[CAM_MAX];
void *vsimg[BUFFER_NUMS] ;
struct v4l2_buffer mybuffer;
struct v4l2_capability mycap;
   struct v4l2_format myfmt;
   struct v4l2_requestbuffers myreq;
   struct v4l2_streamparm mysetfps;
struct timeval timestamp;
int cam_fd,data_len;
bool MmapOK[BUFFER_NUMS];
bool Opened,getframeok;
};


#endif

-------------------------------------------------------------------------------------------------------------------

cam.cpp 的代码

#include "cam.h"

typedef unsigned char uchar;//#define uchar unsigned char //


Opera_Cam::Opera_Cam()
{
Init_Prop();
}

Opera_Cam::Opera_Cam(int which_cam)
{
Init_Prop();
Opened = Open(which_cam);
}

Opera_Cam::Opera_Cam(const string& cam_name)
{
Init_Prop();
Opened = Open(cam_name);
}

bool Opera_Cam::Open(int which_cam)
{
char cam_name[80];
sprintf(cam_name, "/dev/video", which_cam);
string str = cam_name;
return Open(str);
}
#if 1
bool Opera_Cam::Open(const string& cam_name)
{
if(IsOpened())
Free();
string str = cam_name;
if(0!=access(str.c_str(),F_OK))
{
       return false;
      
    }
cam_fd = open(str.c_str(),O_RDWR | O_NONBLOCK,0);

if(cam_fd<0)
return false;

if(!Init_V4l2())
return false;

data_len = weight*height*2;
Opened = true;
    return Opened;
}
#endif
void Opera_Cam::Init_Prop()
{
    cam_fd = -1;
Opened = false;
weight = WEIGHT_DEFAULT;
height = HEIGHT_DEFAULT;
data_len = -1;
for(int i=0;i
MmapOK[i] = false;
}

bool Opera_Cam::Init_V4l2()
{

    CLEAR(mybuffer);

    CLEAR(mycap);
   if(ioctl(cam_fd,VIDIOC_QUERYCAP,&mycap)<0)
    {
return false;
    }
    CLEAR(myfmt);
    myfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   myfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;//V4L2_PIX_FMT_MJPEG;//V4L2_PIX_FMT_YUYV;//
    myfmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
    myfmt.fmt.pix.width = weight;
    myfmt.fmt.pix.height = height;
   if(ioctl(cam_fd,VIDIOC_S_FMT,&myfmt)<0)
    {
printf("VIDIOC_S_FMT is failed!\n");
return false;
    }
    myfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   ioctl(cam_fd,VIDIOC_G_FMT,&myfmt);
   if(myfmt.fmt.pix.pixelformat&V4L2_PIX_FMT_YUYV)//V4L2_PIX_FMT_YUYV)

    CLEAR(myreq);
    myreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    myreq.memory = V4L2_MEMORY_MMAP;
    myreq.count = BUFFER_NUMS;
   if(ioctl(cam_fd,VIDIOC_REQBUFS,&myreq)<0)
    {
       return false;
    }

    for(int i = 0; i< (int)myreq.count;i++)
    {
       CLEAR(mybuffer);

       mybuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
       mybuffer.memory = V4L2_MEMORY_MMAP;
       mybuffer.index = i;
      if(ioctl(cam_fd,VIDIOC_QUERYBUF,&mybuffer)<0)
       {
           return false;
       }

       vsimg[i] = mmap(0,mybuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,cam_fd,mybuffer.m.offset);
       if(vsimg[i]  == MAP_FAILED)
       {
           return false;
       }
MmapOK[i] = true;
    }

    for(int i = 0;i< (int)myreq.count;i++)
    {
       CLEAR(mybuffer);
       mybuffer.index = i;
       mybuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
       mybuffer.memory = V4L2_MEMORY_MMAP;
      if(ioctl(cam_fd,VIDIOC_QBUF,&mybuffer)<0)
       {
     for(int i=0;i
{
if(MmapOK[i])
munmap(vsimg[i] ,mybuffer.length);
}
           return false;
       }
    }

    mybuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

   if(ioctl(cam_fd,VIDIOC_STREAMON,&(mybuffer.type))<0)
    {
      if(ioctl(cam_fd,VIDIOC_STREAMOFF,&(mybuffer.type))<0)
;
for(int i=0;i
{
if(MmapOK[i])
munmap(vsimg[i] ,mybuffer.length);
}
       close(cam_fd);
       return false;
    }
   


    mybuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    mybuffer.memory = V4L2_MEMORY_MMAP;
return true;
}

bool Opera_Cam::Read()//(uchar **data,int& used_len)
{
GetFrameLoop();

if(!getframeok)
return false;


df.real_len = mybuffer.bytesused;  //used_len = mybuffer.bytesused;//mybuffer.length;
//data_len = mybuffer.length;
df.data = (uchar *)vsimg[mybuffer.index];/
          printf ("VIDIOC_DQBUF FAILED\n");
          return 1;
       }
   }

   //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
   //  buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);

   if (-1==ioctl (cam_fd, VIDIOC_QBUF, &mybuffer))
      printf("VIDIOC_QBUF FAILED\n");

   getframeok = true; 

   timestamp = mybuffer.timestamp;
   return 2;
}

void Opera_Cam::Free()
{

   Operation(STREAMOFF);

for(int i=0;i
{
if(MmapOK[i])
munmap(vsimg[i] ,mybuffer.length);
}

    Opened = false;
    if(cam_fd>0)
       close(cam_fd);
}

Opera_Cam::~Opera_Cam()
{
Free();
}

-------------------------------------------------------------------------------------------------------------------

qt部分代码  widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include QWidget>
#include QPixmap>
#include QImage>
#include "cam.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT
    
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    unsigned char *jpeg_buf = NULL;
    
private slots:
    void on_pushButton_clicked();
    void flush_cam();

private:
    Ui::Widget *ui;
    Opera_Cam ope;
    QTimer *timer;
    QPixmap mp;
    QImage image;

};

#endif // WIDGET_H



-----------------------------------------------------------------------------------------------------------------



widget.cpp 代码
#include "widget.h"
#include "ui_widget.h"
 #include QDebug>

int ii = 0;

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
   ui->setupUi(this);

    timer = new QTimer();
   connect(timer,SIGNAL(timeout()),this,SLOT(flush_cam()));

   ui->label->setGeometry(10,10,320,240);
   ui->label->setScaledContents(true);
   ui->pushButton->setGeometry(320,530,30,20);


}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
   qDebug()<<"111111111111";
   ope.Open("/dev/video0");
    usleep(100*1000);
    ii = 0;
   timer->start(20);
}

void Widget::flush_cam()
{

    ii++;

    ope.Read();
    jpeg_buf = (unsigned char *)malloc(ope.df.real_len);
    memcpy(jpeg_buf, ope.df.data, ope.df.real_len);
   image.loadFromData(jpeg_buf,ope.df.real_len,"jpg");
    mp = mp.fromImage(image);
   ui->label->setPixmap(mp);
   ui->label->show();
    free(jpeg_buf);

    if(ii == 200)
    {
       timer->stop();
       ope.Free();
    }
}

#ifdef Q_CC_MSVC
#include "Windows.h"
#include "dshow.h"
#include "strmif.h"
#include "ks.h"
#include "ksproxy.h"
#include "ksmedia.h"
#  pragma comment(lib, "strmiids.lib")
#  pragma comment(lib, "ole32.lib")
#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
#endif // Q_CC_MSVC
#ifdef Q_CC_MSVC
    IBaseFilter* srcFilter;
#endif
bool deviceFilter(const QString &device)
{
#ifdef Q_CC_MSVC
    srcFilter = nullptr;
    ICreateDevEnum* pDevEnum = nullptr;
    IEnumMoniker* pEnum = nullptr;
    // Create the System device enumerator
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr,
                                  CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
                                  reinterpret_cast<void**>(&pDevEnum));
    if (SUCCEEDED(hr)) {
        // Create the enumerator for the video capture category
        hr = pDevEnum->CreateClassEnumerator(
            CLSID_VideoInputDeviceCategory, &pEnum, 0);
        if (S_OK == hr) {
            pEnum->Reset();
            // go through and find all video capture devices
            IMoniker* pMoniker = nullptr;
            IMalloc *mallocInterface = 0;
            CoGetMalloc(1, (LPMALLOC*)&mallocInterface);
            while (pEnum->Next(1, &pMoniker, nullptr) == S_OK) {
                BSTR strName = 0;
                hr = pMoniker->GetDisplayName(nullptr, nullptr, &strName);
                if (SUCCEEDED(hr)) {
                    QString output(QString::fromWCharArray(strName));
                    mallocInterface->Free(strName);

                    IPropertyBag *pPropBag;
                    hr = pMoniker->BindToStorage(nullptr, nullptr, IID_IPropertyBag,
                                                 reinterpret_cast<void**>(&pPropBag));
                    if (SUCCEEDED(hr)) {
                        // Find the description
                        VARIANT varName;
                        varName.vt = VT_BSTR;
                        hr = pPropBag->Read(L"FriendlyName", &varName, 0);
                        if (SUCCEEDED(hr)) {
                            output = QString::fromWCharArray(varName.bstrVal);
                        }
                        pPropBag->Release();

//                        qDebug() << output << device;
                        if( output == device ) {
                            hr = pMoniker->BindToObject(0,
                                                        0,
                                                        IID_IBaseFilter,
                                                        reinterpret_cast<void**>(&srcFilter));
                            qDebug() << "get device control:" << output;
                        }
                    }
                }
                pMoniker->Release();
            }
            mallocInterface->Release();
            pEnum->Release();
        }
        pDevEnum->Release();
    }

    if( srcFilter == nullptr ) {
        return false;
    }
#endif
    return true;
}
bool UVControl(const LONG &value)
{
#ifdef Q_CC_MSVC
    if( srcFilter == nullptr ) {
        return false;
    }

    IKsControl *pCtl = nullptr;
    HRESULT hr;
    hr = srcFilter->QueryInterface(IID_IKsControl, reinterpret_cast<void **>(&pCtl));
    if( FAILED(hr) ) {
        return false;
    }

    KSPROPERTY property;
    ZeroMemory(&property, sizeof(property));
    property.Set = PROPSETID_VIDCAP_CAMERACONTROL;
    property.Id = KSPROPERTY_CAMERACONTROL_ZOOM;
    property.Flags = KSPROPERTY_TYPE_SET;

    ULONG valueSize = 0;
    ULONG ksLength = 0;
    ULONG dataLength = 0;

    KSPROPERTY_CAMERACONTROL_S devCtl;
    ZeroMemory(&devCtl, sizeof(devCtl));
    ksLength = sizeof(devCtl);
    dataLength = sizeof(devCtl);

    devCtl.Property = property;
    devCtl.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
    devCtl.Capabilities = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
    devCtl.Value = value;
    hr = pCtl->KsProperty((PKSPROPERTY)&devCtl, ksLength, &devCtl, dataLength, &valueSize);

    SAFE_RELEASE(pCtl);
#endif
    return true;
}

最好是打包来的,有库文件直接可以编译的

前2个回答应该就是调用摄像头的源码,我就不再赘述。但是要保证图片可以被opencv使用,还需要保证文件的类型为opencv支持的图片类型
OpenCV目前支持的图像格式包括:

Windows位图文件 - BMP, DIB;
JPEG文件 - JPEG, JPG, JPE;
便携式网络图片 - PNG;
便携式图像格式 - PBM,PGM,PPM;
Sun rasters - SR,RAS;
TIFF文件 - TIFF,TIF;
OpenEXR HDR 图片 - EXR;
JPEG 2000 图片- jp2。

这里有一个开源代码,可以看一下,希望对你有帮助。

下面也是一个简单例子:

最下面这个是linux下的,可以参考:

你可以试试下面的开源项目
https://github.com/erikmwerner/QUVCView

直接用开源的网页即可

UVC摄像头 是什么协议呀

OpenCV目前支持的图像格式包括:

Windows位图文件 - BMP, DIB;
JPEG文件 - JPEG, JPG, JPE;
便携式网络图片 - PNG;
便携式图像格式 - PBM,PGM,PPM;
Sun rasters - SR,RAS;
TIFF文件 - TIFF,TIF;
OpenEXR HDR 图片 - EXR;
JPEG 2000 图片- jp2。

你可以试试下面的开源项目https://github.com/erikmwerner/1UVCView

这个开源项目不错,看过了,挺适合的 https://github.com/erikmwerner/QUVCView

https://blog.csdn.net/Kevin_Mr/article/details/51470215?spm=1005.2026.3001.5635&utm_medium=distribute.pc_relevant_ask_down.none-task-blog-2~default~OPENSEARCH~Rate-9.pc_feed_download_top3ask&depth_1-utm_source=distribute.pc_relevant_ask_down.none-task-blog-2~default~OPENSEARCH~Rate-9.pc_feed_download_top3ask