前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCv4.4.0+Qt:摄像头控制

OpenCv4.4.0+Qt:摄像头控制

作者头像
何其不顾四月天
发布2023-03-10 13:15:03
2.4K0
发布2023-03-10 13:15:03
举报
文章被收录于专栏:Opencv四月天的专栏

OpenCv4.4.0+Qt:摄像头控制

简介

在上一篇中讲解了 OpenCv4.4.0+Qt5.12.2+OpenCv-Contrib-4.4.0 的 安装与测试例程,这篇中讲解摄像头的控制,摄像头列表的选择,参数控制,拍照,视频录制。

OpenCv中摄像头的相关的主要有两个模块, VideoCapture / VideoWrite 视频捕捉与视频写入模块。

思路

利用思路利用Qt自带的QCamera相关类以及QLabel,利用OpenCv 的 VideoCapture 和 VideoWriter 负责视频捕捉以及录制。

摄像头选择

利用QCameraInfo 类提供的接口获取摄像头列表,列表ID即为OpenCv摄像头ID号。博主本人测试过两个摄像头,未测试3个以上。获取摄像头列表后与QComBox绑定,来设置选择摄像头。

视频捕捉

利用VideoCapture 打开摄像头,read定时获取当前帧,输出到QLabel显示视频。

参数设置

QCamera与QCameraInfo获取摄像头支持分辨率,帧率,编码格式支持列表,与QComBox绑定,来设置相关参数。

利用get与set获取 清晰度,白平衡,对比度,亮度,色调,增益等相关属性值并进行设置。

拍照

利用QImage将当前帧保存。

录像

利用VideoWrite 将视频帧挨个写入视频文件。

API接口详解

只解释说明关键性接口。

OpenCv

代码语言:javascript
复制
    /** @brief  Opens a video file or a capturing device or an IP video stream for video capturing.
    @overload
    Parameters are same as the constructor VideoCapture(const String& filename, int apiPreference = CAP_ANY)
    @return `true` if the file has been successfully opened
     */
    CV_WRAP virtual bool open(const String& filename, int apiPreference = CAP_ANY);

上述接口,打开一个视频捕捉驱动或者视频流URL串。

代码语言:javascript
复制
    /** @brief  Opens a camera for video capturing
    @overload
    Parameters are same as the constructor VideoCapture(int index, int apiPreference = CAP_ANY)
    @return `true` if the camera has been successfully opened.
    */
    CV_WRAP virtual bool open(int index, int apiPreference = CAP_ANY);

上述接口。打开一个摄像头。其中Index为当摄像头设备接入PC时,底层驱动给做的一个设备排序。笔记本自带摄像头通常为 0,外接设备从1开始排序。通常大家都是使用DirtShow或者修改底层源码。在这里笔者使用了QCameraInfo来获取摄像头ID,笔者为笔记本,外接一个USB摄像头设备,驱动ID是正确的。三个及三个以上手头设备有限未做测试,留待以后。

代码语言:javascript
复制
    /** @brief Closes video file or capturing device.
    The method is automatically called by subsequent VideoCapture::open and by VideoCapture
    destructor.
    The C function also deallocates memory and clears \*capture pointer.
     */
    CV_WRAP virtual void release();

上述接口,关闭摄像头驱动或者视频文件,也可以清除已使用内存和清除摄像头节点。

代码语言:javascript
复制
   /** @brief Grabs, decodes and returns the next video frame.

    @param [out] image the video frame is returned here. If no frames has been grabbed the image will be empty.
    @return `false` if no frames has been grabbed

    The method/function combines VideoCapture::grab() and VideoCapture::retrieve() in one call. This is the
    most convenient method for reading video files or capturing data from decode and returns the just
    grabbed frame. If no frames has been grabbed (camera has been disconnected, or there are no more
    frames in video file), the method returns false and the function returns empty image (with %cv::Mat, test it with Mat::empty()).

    @note In @ref videoio_c "C API", functions cvRetrieveFrame() and cv.RetrieveFrame() return image stored inside the video
    capturing structure. It is not allowed to modify or release the image! You can copy the frame using
    cvCloneImage and then do whatever you want with the copy.
     */
    CV_WRAP virtual bool read(OutputArray image);

上述接口,用来读取下一个视频帧。如果视频帧为空则为获取失败或者返回false.

代码语言:javascript
复制
    /** @brief Sets a property in the VideoCapture.

    @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
    or one from @ref videoio_flags_others
    @param value Value of the property.
    @return `true` if the property is supported by backend used by the VideoCapture instance.
    @note Even if it returns `true` this doesn't ensure that the property
    value has been accepted by the capture device. See note in VideoCapture::get()
     */
    CV_WRAP virtual bool set(int propId, double value);

上述接口,用来设置摄像头的一个相关属性。

代码语言:javascript
复制
    /** @brief Returns the specified VideoCapture property

    @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
    or one from @ref videoio_flags_others
    @return Value for the specified property. Value 0 is returned when querying a property that is
    not supported by the backend used by the VideoCapture instance.
    
    @note Reading / writing properties involves many layers. Some unexpected result might happens
    along this chain.
    @code{.txt}
    VideoCapture -> API Backend -> Operating System -> Device Driver -> Device Hardware
    @endcode
    The returned value might be different from what really used by the device or it could be encoded
    using device dependent rules (eg. steps or percentage). Effective behaviour depends from device
    driver and API Backend
    */
    CV_WRAP virtual double get(int propId) const;

类比于ser,get使用来获取一个属性的当前的设置值。

代码语言:javascript
复制
/** @brief %VideoCapture generic properties identifier.

 Reading / writing properties involves many layers. Some unexpected result might happens along this chain.
 Effective behaviour depends from device hardware, driver and API Backend.
 @sa videoio_flags_others, VideoCapture::get(), VideoCapture::set()
*/
enum VideoCaptureProperties {
       CAP_PROP_POS_MSEC       =0, //!< Current position of the video file in milliseconds.
       CAP_PROP_POS_FRAMES     =1, //!< 0-based index of the frame to be decoded/captured next.
       CAP_PROP_POS_AVI_RATIO  =2, //!< Relative position of the video file: 0=start of the film, 1=end of the film.
       CAP_PROP_FRAME_WIDTH    =3, //!< Width of the frames in the video stream.
       CAP_PROP_FRAME_HEIGHT   =4, //!< Height of the frames in the video stream.
       CAP_PROP_FPS            =5, //!< Frame rate.
       CAP_PROP_FOURCC         =6, //!< 4-character code of codec. see VideoWriter::fourcc .
       CAP_PROP_FRAME_COUNT    =7, //!< Number of frames in the video file.
       CAP_PROP_FORMAT         =8, //!< Format of the %Mat objects (see Mat::type()) returned by VideoCapture::retrieve().
                                   //!< Set value -1 to fetch undecoded RAW video streams (as Mat 8UC1).
       CAP_PROP_MODE           =9, //!< Backend-specific value indicating the current capture mode.
       CAP_PROP_BRIGHTNESS    =10, //!< Brightness of the image (only for those cameras that support).
       CAP_PROP_CONTRAST      =11, //!< Contrast of the image (only for cameras).
       CAP_PROP_SATURATION    =12, //!< Saturation of the image (only for cameras).
       CAP_PROP_HUE           =13, //!< Hue of the image (only for cameras).
       CAP_PROP_GAIN          =14, //!< Gain of the image (only for those cameras that support).
       CAP_PROP_EXPOSURE      =15, //!< Exposure (only for those cameras that support).
       CAP_PROP_CONVERT_RGB   =16, //!< Boolean flags indicating whether images should be converted to RGB. <br/>
                                   //!< *GStreamer note*: The flag is ignored in case if custom pipeline is used. It's user responsibility to interpret pipeline output.
       CAP_PROP_WHITE_BALANCE_BLUE_U =17, //!< Currently unsupported.
       CAP_PROP_RECTIFICATION =18, //!< Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently).
       CAP_PROP_MONOCHROME    =19,
       CAP_PROP_SHARPNESS     =20,
       CAP_PROP_AUTO_EXPOSURE =21, //!< DC1394: exposure control done by camera, user can adjust reference level using this feature.
       CAP_PROP_GAMMA         =22,
       CAP_PROP_TEMPERATURE   =23,
       CAP_PROP_TRIGGER       =24,
       CAP_PROP_TRIGGER_DELAY =25,
       CAP_PROP_WHITE_BALANCE_RED_V =26,
       CAP_PROP_ZOOM          =27,
       CAP_PROP_FOCUS         =28,
       CAP_PROP_GUID          =29,
       CAP_PROP_ISO_SPEED     =30,
       CAP_PROP_BACKLIGHT     =32,
       CAP_PROP_PAN           =33,
       CAP_PROP_TILT          =34,
       CAP_PROP_ROLL          =35,
       CAP_PROP_IRIS          =36,
       CAP_PROP_SETTINGS      =37, //!< Pop up video/camera filter dialog (note: only supported by DSHOW backend currently. The property value is ignored)
       CAP_PROP_BUFFERSIZE    =38,
       CAP_PROP_AUTOFOCUS     =39,
       CAP_PROP_SAR_NUM       =40, //!< Sample aspect ratio: num/den (num)
       CAP_PROP_SAR_DEN       =41, //!< Sample aspect ratio: num/den (den)
       CAP_PROP_BACKEND       =42, //!< Current backend (enum VideoCaptureAPIs). Read-only property
       CAP_PROP_CHANNEL       =43, //!< Video input or Channel Number (only for those cameras that support)
       CAP_PROP_AUTO_WB       =44, //!< enable/ disable auto white-balance
       CAP_PROP_WB_TEMPERATURE=45, //!< white-balance color temperature
       CAP_PROP_CODEC_PIXEL_FORMAT =46,    //!< (read-only) codec's pixel format. 4-character code - see VideoWriter::fourcc . Subset of [AV_PIX_FMT_*](https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/raw.c) or -1 if unknown
       CAP_PROP_BITRATE       =47, //!< (read-only) Video bitrate in kbits/s
#ifndef CV_DOXYGEN
       CV__CAP_PROP_LATEST
#endif
     };

VideoCapture枚举属性列表。

代码语言:javascript
复制
    /** @brief Initializes or reinitializes video writer.

    The method opens video writer. Parameters are the same as in the constructor
    VideoWriter::VideoWriter.
    @return `true` if video writer has been successfully initialized

    The method first calls VideoWriter::release to close the already opened file.
     */
    CV_WRAP virtual bool open(const String& filename, int fourcc, double fps,
                      Size frameSize, bool isColor = true);

    /** @overload
     */
    CV_WRAP bool open(const String& filename, int apiPreference, int fourcc, double fps,
                      Size frameSize, bool isColor = true);

    /** @overload
     */
    CV_WRAP bool open(const String& filename, int fourcc, double fps, const Size& frameSize,
                      const std::vector<int>& params);

    /** @overload
     */
    CV_WRAP bool open(const String& filename, int apiPreference, int fourcc, double fps,
                      const Size& frameSize, const std::vector<int>& params);

设置视频保存属性-名称-帧率-编码-分辨率

代码语言:javascript
复制
    /** @brief Concatenates 4 chars to a fourcc code

    @return a fourcc code

    This static method constructs the fourcc code of the codec to be used in the constructor
    VideoWriter::VideoWriter or VideoWriter::open.
     */
    CV_WRAP static int fourcc(char c1, char c2, char c3, char c4);
// FIXIT OpenCV 4.0: make inline
    int VideoWriter::fourcc(char c1, char c2, char c3, char c4)
    {
        return (c1 & 255) + ((c2 & 255) << 8) + ((c3 & 255) << 16) + ((c4 & 255) << 24);
    }

获取视频编码格式对应的枚举ID值

编码对应ID以及音视频支持格式

编码列表

代码语言:javascript
复制
//! Macro to construct the fourcc code of the codec. Same as CV_FOURCC()
#define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24))

/** @brief Constructs the fourcc code of the codec function

Simply call it with 4 chars fourcc code like `CV_FOURCC('I', 'Y', 'U', 'V')`

List of codes can be obtained at [Video Codecs by FOURCC](http://www.fourcc.org/codecs.php) page.
FFMPEG backend with MP4 container natively uses other values as fourcc code:
see [ObjectType](http://mp4ra.org/#/codecs).
*/
CV_INLINE int CV_FOURCC(char c1, char c2, char c3, char c4)
{
    return CV_FOURCC_MACRO(c1, c2, c3, c4);
}
//! (Windows only) Open Codec Selection Dialog
#define CV_FOURCC_PROMPT -1
//! (Linux only) Use default codec for specified filename
#define CV_FOURCC_DEFAULT CV_FOURCC('I', 'Y', 'U', 'V')

查看源代码**fourcc(char c1, char c2, char c3, char c4)**与 **CV_FOURCC(char c1, char c2, char c3, char c4)**相同,支持通用,建议还是不要设置为 -1,仅支持Windows,还是采用 返回值形式来设置编码格式。 例如:int fourcc = cv::VideoWriter::fourcc(‘M’, ‘J’, ‘P’, ‘G’)

Qt

QCameraInfo::availableCameras():返回位于本地所有有效的摄像头列表

代码语言:javascript
复制
[static] QList<QCameraInfo> QCameraInfo::availableCameras(QCamera::Position position = QCamera::UnspecifiedPosition)
Returns a list of available cameras on the system which are located at position.
If position is not specified or if the value is QCamera::UnspecifiedPosition, a list of all available cameras will be returned.

QList supportedViewfinderResolutions(const QCameraViewfinderSettings &settings = QCameraViewfinderSettings()) :返回摄像头支持分辨率列表。

代码语言:javascript
复制
QList<QSize> QCamera::supportedViewfinderResolutions(const QCameraViewfinderSettings &settings = QCameraViewfinderSettings()) const
Returns a list of supported viewfinder resolutions.
This is a convenience function which retrieves unique resolutions from the supported settings.
If non null viewfinder settings are passed, the returned list is reduced to resolutions supported with partial settings applied.
The camera must be loaded before calling this function, otherwise the returned list is empty.

QList supportedViewfinderFrameRateRanges(const QCameraViewfinderSettings &settings = QCameraViewfinderSettings()) :返回摄像头支持的帧率范围。

代码语言:javascript
复制
QList<QCamera::FrameRateRange> QCamera::supportedViewfinderFrameRateRanges(const QCameraViewfinderSettings &settings = QCameraViewfinderSettings()) const
Returns a list of supported viewfinder frame rate ranges.
This is a convenience function which retrieves unique frame rate ranges from the supported settings.
If non null viewfinder settings are passed, the returned list is reduced to frame rate ranges supported with partial settings applied.
The camera must be loaded before calling this function, otherwise the returned list is empty.

QList< QVideoFrame::PixelFormat> supportedViewfinderPixelFormats(const QCameraViewfinderSettings &settings = QCameraViewfinderSettings()):返回摄像头支持格式。

代码语言:javascript
复制
QList<QVideoFrame::PixelFormat> QCamera::supportedViewfinderPixelFormats(const QCameraViewfinderSettings &settings = QCameraViewfinderSettings()) const
Returns a list of supported viewfinder pixel formats.
This is a convenience function which retrieves unique pixel formats from the supported settings.
If non null viewfinder settings are passed, the returned list is reduced to pixel formats supported with partial settings applied.
The camera must be loaded before calling this function, otherwise the returned list is empty.

源码详解

摄像头列表

获取摄像头列表

代码语言:javascript
复制
void MainWindow::GetCameraList()
{
    formatmeta = QMetaEnum::fromType<PixelFormat>();
    cameras = QCameraInfo::availableCameras();
    foreach(const QCameraInfo &cameraInfo, cameras)
    {
        ui->comboBox_name->addItem(cameraInfo.description());
        GetCameraInfo(cameraInfo);
        COUT << cameraInfo.description() <<cameraInfo.deviceName() << cameraInfo.orientation();
    }
}

选择摄像头

代码语言:javascript
复制
    connect(ui->comboBox_name,SIGNAL(activated(int)),this,SLOT(slot_SetIndexCaptureCamera(int))); //信号槽连接
代码语言:javascript
复制
void MainWindow::slot_SetIndexCaptureCamera(int index) //摄像头选择
{
    if(cap.isOpened())
    {
        timer.stop();
        cap.release();
    }
    cap.open(index,cv::CAP_DSHOW);

    if(!cap.isOpened())
    {
        COUT << cameras.at(index).description() << "打开失败";
        return;
    }
    SetComboxValue(index); //默认值显示

    timer.start(20); //定时器启动
}

帧读取

代码语言:javascript
复制
void MainWindow::slot_CaptureImage()
{
    cv::Mat frame,image;
    cap.read(frame);
    if(frame.empty())
        return;
    emit signal_MatImage(frame);
}
代码语言:javascript
复制
    connect(&timer,&QTimer::timeout,this,&MainWindow::slot_CaptureImage); //定时器信号槽绑定

帧显示

代码语言:javascript
复制
    connect(this,&MainWindow::signal_MatImage,this,&MainWindow::slot_LabelShowImg);
代码语言:javascript
复制
void MainWindow::slot_LabelShowImg(cv::Mat image)
{
    cv::Mat out_image;
    cv::cvtColor(image,out_image,cv::COLOR_BGR2RGB); //转为Qt显示RGB值
    QImage qImg = QImage((const unsigned char*)(out_image.data),out_image.cols,out_image.rows,out_image.step,QImage::Format_RGB888); //转为QImage
    ui->label_video->setPixmap(QPixmap::fromImage(qImg.mirrored(true,false)));
    ui->label_video->resize(qImg.size());
    ui->label_video->show();
    //拍照相关设置
    if(isSaveImage){
        QString image_name = QString("%1.png").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss"));
        if(qImg.save(image_name))
        {
            COUT << "拍照成功!" << image_name;
            isSaveImage = false;
        }
        else {
            COUT << "保存图片失败!"  << image_name;
        }
    }
}

Qt支持相关属性列表

代码语言:javascript
复制
void MainWindow::GetCameraInfo(QCameraInfo info)
{
    QCamera * camera = new QCamera(info);
    camera->start();
    GetCameraResolution(camera);
    GetCameraFormat(camera);
    GetCameraFrameRate(camera);
    camera->stop();
    delete camera;
    camera = nullptr;
}

分辨率列表

代码语言:javascript
复制
void MainWindow::GetCameraResolution(QCamera *camera)
{
    QStringList resolutions;
    QList<QSize> resSize = camera->supportedViewfinderResolutions();
    for(auto it : resSize)
    {
        resolutions.push_back(QString("%1X%2").arg(it.width()).arg(it.height()));
        COUT << QString("%1X%2").arg(it.width()).arg(it.height());
    }
    camerasresolution.push_back(resolutions);
}

帧编码格式列表

代码语言:javascript
复制
void MainWindow::GetCameraFormat(QCamera *camera)
{
    QStringList formats;
    QList<QVideoFrame::PixelFormat> formatlist = camera->supportedViewfinderPixelFormats();

    for(auto it : formatlist)
    {
        COUT << formatmeta.valueToKey(it) ;
        formats.push_back(formatmeta.valueToKey(it));
    }
    camerasformat.push_back(formats);
}

帧率列表

代码语言:javascript
复制
void MainWindow::GetCameraFrameRate(QCamera *camera)
{
    QStringList frames;
    QList<QCamera::FrameRateRange> framerate = camera->supportedViewfinderFrameRateRanges();

    for(auto it : framerate)
    {
        frames.push_back(QString("%1").arg(it.minimumFrameRate));
    }
    camerasframerate.push_back(frames);
}

参数设置

参数初始化设置

代码语言:javascript
复制
void MainWindow::SetComboxValue(int index)
{
    ui->comboBox_resolution->clear();
    ui->comboBox_resolution->addItems(camerasresolution.at(index));
    QString resolution = QString("%1X%2").arg(cap.get(cv::CAP_PROP_FRAME_WIDTH)).arg(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
    ui->comboBox_resolution->setCurrentIndex(ui->comboBox_resolution->findText(resolution));
    COUT << "resolution:" <<resolution;

    ui->comboBox_format->clear();
    ui->comboBox_format->addItems(camerasformat.at(index));
    QString format = QString("%1").arg(cap.get(cv::CAP_PROP_FORMAT));
    COUT << "format:" << format;

    ui->comboBox_framerate->clear();
    ui->comboBox_framerate->addItems(camerasframerate.at(index));
    QString framerate = QString("%1").arg(cap.get(cv::CAP_PROP_FPS));
    ui->comboBox_framerate->setCurrentIndex(ui->comboBox_framerate->findText(framerate));
    COUT << "framerate:" << framerate;

    QString pixelformat = QString("%1").arg(cap.get(cv::CAP_PROP_CODEC_PIXEL_FORMAT));
    COUT << "pixelformat:" << pixelformat;

    QString gain = QString("%1").arg(cap.get(cv::CAP_PROP_GAIN));
    COUT << "gain:" << gain;

    ui->spinBox_brightness->setValue(DoubleToInt(cap.get(cv::CAP_PROP_BRIGHTNESS))); //显示默认亮度
    ui->spinBox_contrast->setValue(DoubleToInt(cap.get(cv::CAP_PROP_CONTRAST))); //显示默认对比度
    ui->spinBox_exposure->setValue(DoubleToInt(cap.get(cv::CAP_PROP_EXPOSURE))); //显示默认曝光
    ui->spinBox_hue->setValue(DoubleToInt(cap.get(cv::CAP_PROP_HUE))); //显示默认色调
    ui->spinBox_saturation->setValue(DoubleToInt(cap.get(cv::CAP_PROP_SATURATION))); //显示默认饱和度
    ui->spinBox_wb->setValue(DoubleToInt(cap.get(cv::CAP_PROP_WHITE_BALANCE_BLUE_U))); //显示默认白平衡
    ui->spinBox_gain->setValue(DoubleToInt(cap.get(cv::CAP_PROP_GAIN))); //显示自动增益
    ui->checkBox_autoexposure->setCheckState((cap.get(cv::CAP_PROP_AUTO_EXPOSURE))?Qt::CheckState::Checked:Qt::CheckState::Unchecked); //是否自动曝光
    ui->checkBox_autowb->setCheckState((cap.get(cv::CAP_PROP_AUTO_WB))?Qt::CheckState::Checked:Qt::CheckState::Unchecked);
} //是否自动白平衡

参数设置相关信号槽绑定

代码语言:javascript
复制
    connect(ui->comboBox_resolution,SIGNAL(activated(int)),this,SLOT(slot_SetIndexCameraResolution(int)));//分辨率
    connect(ui->comboBox_framerate,SIGNAL(activated(int)),this,SLOT(slot_SetIndexCameraFrameRate(int)));//帧率
    connect(ui->spinBox_brightness,SIGNAL(valueChanged(int)),this,SLOT(slot_SetCameraBrightness(int)));//亮度
    connect(ui->spinBox_contrast,SIGNAL(valueChanged(int)),this,SLOT(slot_SetCameraContrast(int)));//对比度
    connect(ui->spinBox_exposure,SIGNAL(valueChanged(int)),this,SLOT(slot_SetCameraExposure(int)));//曝光
    connect(ui->spinBox_hue,SIGNAL(valueChanged(int)),this,SLOT(slot_SetCameraHue(int)));//色调
    connect(ui->spinBox_saturation,SIGNAL(valueChanged(int)),this,SLOT(slot_SetCameraSaturation(int)));//饱和度
    connect(ui->spinBox_gain,SIGNAL(valueChanged(int)),this,SLOT(slot_SetCameraGain(int)));//增益
    connect(ui->spinBox_wb,SIGNAL(valueChanged(int)),this,SLOT(slot_SetCameraWhilteBalance(int)));//白平衡
    connect(ui->checkBox_autoexposure,&QCheckBox::stateChanged,this,&MainWindow::slot_SetCameraAutoExposure);//自动曝光
    connect(ui->checkBox_autowb,&QCheckBox::stateChanged,this,&MainWindow::slot_SetCameraAutoWb);//自动白平衡
    connect(ui->pushButton_setting,&QPushButton::clicked,this,&MainWindow::slot_SetCameraPram);//OpenCv自带参数设置

分辨率

代码语言:javascript
复制
void MainWindow::slot_SetIndexCameraResolution(int index)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    QString resolution = ui->comboBox_resolution->itemText(index);
    double width = resolution.split("X").at(0).toDouble();
    double height = resolution.split("X").at(1).toDouble();
    COUT << cap.get(cv::CAP_PROP_FRAME_WIDTH) << cap.get(cv::CAP_PROP_FRAME_HEIGHT);
    cap.set(cv::CAP_PROP_FRAME_WIDTH,width);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT,height);
}

帧率

代码语言:javascript
复制
void MainWindow::slot_SetIndexCameraFrameRate(int index)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    QString framerate = ui->comboBox_framerate->itemText(index);
    cap.set(cv::CAP_PROP_FPS,framerate.toDouble());
}

亮度

代码语言:javascript
复制
void MainWindow::slot_SetCameraBrightness(int value)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_BRIGHTNESS,value);
}

饱和度

代码语言:javascript
复制
void MainWindow::slot_SetCameraSaturation(int value)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_SATURATION,value);
}

色调

代码语言:javascript
复制
void MainWindow::slot_SetCameraHue(int value)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_HUE,value);
}

曝光

代码语言:javascript
复制
void MainWindow::slot_SetCameraExposure(int value)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_EXPOSURE,value);
    COUT << "CAP_PROP_EXPOSURE:" << QString("%1").arg(cap.get(cv::CAP_PROP_EXPOSURE));
}

对比度

代码语言:javascript
复制
void MainWindow::slot_SetCameraContrast(int value)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_CONTRAST,value);
}

增益

代码语言:javascript
复制
void MainWindow::slot_SetCameraGain(int value)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_GAIN,value);
}

白平衡

代码语言:javascript
复制
void MainWindow::slot_SetCameraWhilteBalance(int value)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_WHITE_BALANCE_BLUE_U,value);
}

自动白平衡

代码语言:javascript
复制
void MainWindow::slot_SetCameraAutoWb(int status)
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_AUTO_WB,(status == Qt::CheckState::Checked) ? -1 : cap.get(cv::CAP_PROP_EXPOSURE));
    ui->spinBox_wb->setDisabled(status);
}

自动曝光

代码语言:javascript
复制
void MainWindow::slot_SetCameraAutoExposure(int status)
{
    COUT << "设置自动曝光" << status;
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    if(status == Qt::CheckState::Checked)
    {
        cap.set(cv::CAP_PROP_AUTO_EXPOSURE,0);
        cv::VideoCaptureProperties();
    }
    else
    {
        cap.set(cv::CAP_PROP_AUTO_EXPOSURE,1);
        cap.set(cv::CAP_PROP_EXPOSURE,cap.get(cv::CAP_PROP_EXPOSURE));
    }
    ui->spinBox_exposure->setDisabled(status);
    COUT << "自动曝光:" << cap.get(cv::CAP_PROP_AUTO_EXPOSURE);
    COUT << "曝光:" << cap.get(cv::CAP_PROP_EXPOSURE);
}

设置参数属性-OpenCv

代码语言:javascript
复制
void MainWindow::slot_SetCameraPram()
{
    COUT << "设置摄像头参数";
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }
    cap.set(cv::CAP_PROP_SETTINGS, 1);
    COUT << "自动曝光:" << cap.get(cv::CAP_PROP_AUTO_EXPOSURE);
    COUT << "曝光:" << cap.get(cv::CAP_PROP_EXPOSURE);
    COUT << "自动白平衡:" << cap.get(cv::CAP_PROP_AUTO_WB);
    COUT << "白平衡:" << cap.get(cv::CAP_PROP_WHITE_BALANCE_BLUE_U);
}

拍照

思路,按下拍照按钮时,将保存标志位置为True,将下一帧转为QImage类型,保存下一帧。

代码语言:javascript
复制
    connect(ui->pushButton_photo,&QPushButton::clicked,this,&MainWindow::slot_Photograph);
代码语言:javascript
复制
void MainWindow::slot_Photograph()
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }

    isSaveImage = true; //当标志位为True时,启动保存当前帧
}

视频录制

代码语言:javascript
复制
    connect(ui->pushButton_recordvideo,&QPushButton::clicked,this,&MainWindow::slot_RecordVideo);
    connect(this,&MainWindow::signal_MatImage,this,&MainWindow::slot_SaveVideo);
代码语言:javascript
复制
void MainWindow::slot_RecordVideo()
{
    if(!cap.isOpened())
    {
        COUT << "摄像头设备未打开!";
        return;
    }

    if(!videorecord.isOpened() && isRecordVideo == false)
    {
        QString resolution = ui->comboBox_resolution->currentText();
        int width = resolution.split("X").at(0).toInt();
        int height = resolution.split("X").at(1).toInt();
        COUT << "video size:" << width << " " << height;
        cv::Size _size = cv::Size(width,height);

        QString video_name = QString("%1.mp4").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss"));

        videorecord.open(video_name.toStdString(),cv::VideoWriter::fourcc('M', 'J', 'P', 'G'),30,_size,true);//设置保存属性-编码-名字-分辨率
        if(videorecord.isOpened())
        {
            isRecordVideo = true;
            COUT << "开始视频录制";
            ui->pushButton_recordvideo->setText("结束录制");
        }
    }
    else if(videorecord.isOpened() && isRecordVideo)
    {
        ui->pushButton_recordvideo->setText("视频录制");
        videorecord.release();
        isRecordVideo = false;
        COUT << "视频录制完成";
    }
}
代码语言:javascript
复制
void MainWindow::slot_SaveVideo(cv::Mat image) //写入帧文件
{
    if(isRecordVideo)
    {
       videorecord.write(image);
    }
}

头文件

代码语言:javascript
复制
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QCamera>
#include <QCameraInfo>
#include <opencv2/opencv.hpp>
#include <QList>
#include <QTimer>
#include <QMetaEnum>
#include <QDebug>

#define COUT qDebug()<< __TIME__ << __FUNCTION__ << __LINE__ << " : " //日志输出,方便自己调试做的设置

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    enum PixelFormat
    {
        Format_Invalid,
        Format_ARGB32,
        Format_ARGB32_Premultiplied,
        Format_RGB32,
        Format_RGB24,
        Format_RGB565,
        Format_RGB555,
        Format_ARGB8565_Premultiplied,
        Format_BGRA32,
        Format_BGRA32_Premultiplied,
        Format_BGR32,
        Format_BGR24,
        Format_BGR565,
        Format_BGR555,
        Format_BGRA5658_Premultiplied,

        Format_AYUV444,
        Format_AYUV444_Premultiplied,
        Format_YUV444,
        Format_YUV420P,
        Format_YV12,
        Format_UYVY,
        Format_YUYV,
        Format_NV12,
        Format_NV21,
        Format_IMC1,
        Format_IMC2,
        Format_IMC3,
        Format_IMC4,
        Format_Y8,
        Format_Y16,

        Format_Jpeg,

        Format_CameraRaw,
        Format_AdobeDng,
    };
    Q_ENUM(PixelFormat)

private:
    Ui::MainWindow *ui;
    QList<QCameraInfo> cameras;
    QList<QStringList> camerasresolution;
    QList<QStringList> camerasformat;
    QList<QStringList> camerasframerate;
    QTimer timer;
    QMetaEnum formatmeta;
    cv::VideoCapture cap;
    cv::VideoWriter videorecord;
    bool isSaveImage;
    bool isRecordVideo;
    void CamerasInit();
    void GetCameraList();
    void GetCameraInfo(QCameraInfo info);
    void GetCameraResolution(QCamera *camera);
    void GetCameraFormat(QCamera *camera);
    void GetCameraFrameRate(QCamera *camera);
    void SetComboxValue(int index);
public slots:
    void slot_SetIndexCaptureCamera(int index);
    void slot_CaptureImage();
    void slot_LabelShowImg(cv::Mat image);
    void slot_SetIndexCameraResolution(int index);
    void slot_SetIndexCameraFrameRate(int index);
    void slot_SetCameraBrightness(int value);
    void slot_SetCameraSaturation(int value);
    void slot_SetCameraHue(int value);
    void slot_SetCameraExposure(int value);
    void slot_SetCameraContrast(int value);
    void slot_SetCameraGain(int value);
    void slot_SetCameraWhilteBalance(int value);
    void slot_SetCameraAutoWb(int status);
    void slot_SetCameraAutoExposure(int status);
    void slot_SetCameraPram();
    void slot_Photograph();
    void slot_RecordVideo();
    void slot_SaveVideo(cv::Mat image);

signals:
    void signal_MatImage(cv::Mat);
};

#endif // MAINWINDOW_H

运行结果

UI界面

有点乱不想放图片的-----

运行界面

运行结果

源码

GitHub

问题

OpenCv设置自动曝光是,取消自动曝光设置是成功的,但是设置为自动曝光没有生效。UI界面的自适应没有做很好,但是不想浪费精力还有代码的优化,还可以优化很多,但是都是工作量了,不做进一步改进。目前这个代码结构,基本的设置或者工程应用应该是足够的,更加复杂的场景,暂时没有涉及到也不做相关建议了。

UI自适应思路:根据Label大小,将窗口resize,来实现自动缩放。

代码优化定时器时间设置:这一块不够严谨,应该时间设置为,1000/rate ,笔者设置为了固定值,20ms,相当于50帧,在时序比较严谨的场景中,会导致帧率错位或者帧时间不匹配的问题。还有视频录制相关。相关代码和分辨率设置差不多,也不做添加了。

自动曝光设置:准备查看源码,但是第一遍搜索的时候,没有找到相关,如果有建议,欢迎留言。

设置参数:摄像头没有打开时,所有设置参数属性控件都是可以点击的,可以默认为disable,在打开摄像头在设置为enable。在每次进行摄像头参数设置时,都有一个摄像头是否打开判断,其实没有必要,在外边随定时器进行判断就好,不好的点是浪费了性能,但是这样设置保证安全,但是代码有些冗余看个人选择了。

有其他问题,欢迎探讨。

下一章节

OpenCv 文字识别或者大家有什么建议吗?学习方向还是没整理好。

更新

2021.04.29 代码放在github了,之前没有想着放在git上边,就当自己随手写的一个小Demo,有点不规范。以后所有代码都会放在github上边。尽量会做到规范,

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • OpenCv4.4.0+Qt:摄像头控制
    • 简介
      • 思路
        • API接口详解
          • 源码详解
            • 摄像头列表
            • 参数设置
            • 拍照
            • 视频录制
            • 头文件
          • 运行结果
            • 源码
              • 问题
                • 下一章节
                  • 更新
                  相关产品与服务
                  文字识别
                  文字识别(Optical Character Recognition,OCR)基于腾讯优图实验室的深度学习技术,将图片上的文字内容,智能识别成为可编辑的文本。OCR 支持身份证、名片等卡证类和票据类的印刷体识别,也支持运单等手写体识别,支持提供定制化服务,可以有效地代替人工录入信息。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档