C++ OpenCV 调用摄像头并调节亮度

正文索引 [隐藏]

VideoCapture

创建一个VideoCapture类的实例,如果传入对应的参数,可以直接打开视频文件或者要调用的摄像头。

VideoCapture::VideoCapture();
VideoCapture::VideoCapture(const string& filename);//filename – 打开的视频文件名。
VideoCapture::VideoCapture(int device); //device – 打开的视频捕获设备id ,如果只有一个摄像头可以填0,表示打开默认的摄像。

视频读帧

read函数结合VideoCapture::grab()和VideoCapture::retrieve()其中之一被调用,用于捕获、解码和返回下一个视频帧。假如没有视频帧被捕获(相机没有连接或者视频文件中没有更多的帧)将返回false。

VideoCapture& VideoCapture::operator>>(Mat& image);
bool VideoCapture::read(Mat& image);

CreateTrackbar

在之前的博文中写到过用Trackbar来滑动调节亮度,在C++中,createTrackbar的函数定义如下:

CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname,int* value, int count,TrackbarCallback onChange = 0, void* userdata = 0);

参数1 trackbarname 是滑动空间的名称,用来给这个滚动条取一个名字。

参数2 winname 是滑动空间用于依附的图像窗口的名称,用来指定你要吧这个滚动条用到那个窗口上。

参数3 value 是用来设置滑块初始值位置,同时记录滑块以后的位置。

参数4 count 是滚动条的刻度范围,用来指定滚动条可以滚动的最大值。

参数5 onChange 是回调函数,用来接收回调函数函数名的,默认值为0。函数定义如下:

void (*TrackbarCallback)(int pos, void* userdata);

pos是当前滑块所在的位置,该值其实就等于createTrackbar()中的value,然后回调函数形参userdata的值就是通过createTrackbar()的userdata直接得到的,

参数6 userdata 是用户传给回调函数的数据,用来处理轨迹条事件,可以不写,默认值为0。

VS中调用摄像头并调节亮度

我的cv.hpp在之前的博文中贴过,这里就不再放代码了。camera.cpp代码如下:

#include "cv.hpp"

static Mat camera, dst;
static int lightness;

static void on_track(int, void*) {
    cv::add(camera, Scalar(lightness, lightness, lightness), dst);
    imshow("摄像头", dst);
}

void TydCV::callCamera() {
    namedWindow("摄像头", WINDOW_NORMAL);
    int max_value = 100;
    lightness = 50;
    createTrackbar("亮度","摄像头", &lightness, max_value, on_track);
    VideoCapture capture(0);
    while(capture.read(camera)) {
        cv::flip(camera, camera, 1);
        on_track(50,0);
        int key = waitKey(10);
        if(key == 27) {  //Esc退出
            break;
        }
    }
    capture.release();
    destroyWindow("摄像头");
}

在main.cpp的主函数中调用摄像头即可,但是这样写出来的窗口有个bug就是:会陷入while死循环,无法用鼠标点击X按钮关闭窗体,只能按Esc退出窗体。折腾了半天决定用QT来写。

Qt中调用摄像头并调节亮度

用QT来写的话就不用while死循环了直接添加计时器,绑定槽函数来调用摄像头。

这里就不放ui_mainwindow.h和mainwindow.h了,camera.cpp代码如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"
using namespace cv;

static Mat ans;
static int brightness;
static QImage image;

void MainWindow::changeBrightness() {
    add(MainWindow::camera, Scalar(brightness, brightness, brightness), ans);
    image = QImage((const uchar*)ans.data,ans.cols,ans.rows,QImage::Format_RGB888).rgbSwapped();
    ui->label->setPixmap(QPixmap::fromImage(image));
}

void MainWindow::on_brightnessSlider_valueChanged(int value)
{
    brightness = value;
    changeBrightness();
}

void MainWindow::readCamera() {
    capture >> camera;
    flip(camera,camera,1);
    changeBrightness();
}

mainwindow.cpp的代码如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"

using namespace cv;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("摄像头");
    video_switch = false;
    camera_timer = new QTimer(this);
    connect(camera_timer,SIGNAL(timeout()),this,SLOT(readCamera()));
    brightnessMin = 0, brightnessMax = 100, brightnessStep = 1;
    ui->brightnessSpinBox->setMinimum(brightnessMin);
    ui->brightnessSpinBox->setMaximum(brightnessMax);
    ui->brightnessSpinBox->setSingleStep(brightnessStep);
    ui->brightnessSlider->setMinimum(brightnessMin);
    ui->brightnessSlider->setMaximum(brightnessMax);
    ui->brightnessSlider->setSingleStep(brightnessStep);
    connect(ui->brightnessSpinBox, SIGNAL(valueChanged(int)), ui->brightnessSlider, SLOT(setValue(int)));
    connect(ui->brightnessSlider, SIGNAL(valueChanged(int)), ui->brightnessSpinBox, SLOT(setValue(int)));
    ui->brightnessSlider->setValue(50);
}

MainWindow::~MainWindow()
{
    camera_timer->stop();
    capture.release();
    delete ui;
}

void MainWindow::on_cameraButton_clicked()
{
    if(video_switch) {
        video_switch = false;
        ui->cameraButton->setText("打开摄像头");
        camera_timer->stop();
        capture.release();
    } else {
        video_switch = true;
        ui->cameraButton->setText("关闭摄像头");
        capture.open(0);
        camera_timer->start(10);
    }
}

界面暂时有点丑。