第七天:
实现用板子上的摄像头抓取一张实时图片,并存取到一个已经定义好的路径中
首先在界面设计中定义一个抓取按钮(PushButton)Take,和显示图片的按钮label。
然后在.pro文件中添加Opencv的文件
ps:要实现实时的抓取,必须使用QTimer
INCLUDEPATH += /usr/include \
/usr/include/opencv \
/usr/include/opencv2
LIBS += -L/usr/lib \
-lopencv_core \
-lopencv_highgui \
-lopencv_imgproc
然后在头文件.h添加头文件
#include "imgproc/imgproc.hpp"
#include "highgui/highgui.hpp"
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "imgproc/imgproc.hpp" //opencv的头文件
#include "highgui/highgui.hpp"
#define VIDEO_WIDTH 640 //定义图片的宽高
#define VIDEO_HEIGHT 480
#include <QTimer>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
bool InitCamera(); //初始化摄像头
bool ShowImage(); //显示图片函数
private:
Ui::Dialog *ui;
CvCapture* m_Capture;
IplImage* m_Frame;
uint PhotoNumber;
QTimer m_TimeFlush;
private slots:
void GoToShowPhoto(); //代码没有优化,这个函数其实可以去掉
// void Takephoto();两个抓取图片的函数,这个是我借鉴别人的
void SaveImage(); //这个是老师的
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
#include <QMessageBox>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
m_Capture=NULL; //初始化对象
m_Frame=NULL;
PhotoNumber=100; //定义定义路径下的图片名字的初始值
//实时的显示
m_TimeFlush.setInterval(20);
m_TimeFlush.start();
//显示图片,定义大小
ui->LB_IMAGE->move( 0,0 );
ui->LB_IMAGE->resize(VIDEO_WIDTH -50,VIDEO_HEIGHT -50 );
this->resize(VIDEO_WIDTH,VIDEO_HEIGHT + 50);
if( ! InitCamera() )
{
QMessageBox::information(this,"camera","InitCamera failed");
exit(1);
}
if( ! ShowImage ())
{
QMessageBox::information(this,"camera","Show Image failed");
exit(2);
}
connect(&m_TimeFlush,SIGNAL(timeout()),this,SLOT(GoToShowPhoto())); //实时显示图片
// connect(ui->Take,SIGNAL(clicked()),this,SLOT(Takephoto()));
connect(ui->Take,SIGNAL(clicked()),this,SLOT(SaveImage()));
}
Dialog::~Dialog()
{
delete ui;
if(m_Capture)
cvReleaseCapture(&m_Capture);
}
//初始化摄像头
bool Dialog::InitCamera()
{
m_Capture=cvCreateCameraCapture(-1);
if(m_Capture==NULL)
return false;
cvSetCaptureProperty(m_Capture,CV_CAP_PROP_FRAME_WIDTH,VIDEO_WIDTH);
cvSetCaptureProperty(m_Capture,CV_CAP_PROP_FRAME_HEIGHT,VIDEO_HEIGHT);
return true;
}
bool Dialog::ShowImage()
{
QImage Image;
m_Frame = cvQueryFrame(m_Capture);
if(m_Frame == NULL){
return false;
}
//我理解的是定义抓取的图片的大小和格式,为RGB888格式的 rgbSwapped是把图片显示成正常模式
Image = QImage( (uchar*)m_Frame->imageData ,m_Frame->width,m_Frame->height,QImage::Format_RGB888).rgbSwapped() ;
ui->LB_IMAGE->setPixmap( QPixmap::fromImage(Image));
return true;
}
void Dialog::GoToShowPhoto()
{
Dialog::ShowImage();
}
/*void Dialog::Takephoto()
{
QImage NewImage;
QString PhotoPath = "/home/pi/hah/";
PhotoPath += QString ("%1.jpg").arg(++PhotoNumber);
NewImage = QImage((uchar *)m_Frame->imageData ,m_Frame->width,m_Frame->height,QImage::Format_RGB888).rgbSwapped() ;
NewImage.save(PhotoPath);
QMessageBox::information(this,"Tips","take ok!");
}*/
void Dialog::SaveImage()
{
QImage Image;
Image= QImage((uchar *)m_Frame->imageData ,m_Frame->width,m_Frame->height,QImage::Format_RGB888).rgbSwapped() ;
if(Image.isNull())
return;
Image.save(QString("%1.png").arg(rand ()%100),"png",100);
}
//在其中有一个BUG,就是没有把Image没有设置成全局变量,设置成局部变量了,这是老师诚心考我们的,其实把QImage Image放在dialog.h的private中就可以了,其他的函数就不用再设置一下了。
第九天:
通过之前第七天的代码开始修改,增加判断语句,通过m_IsSave的true or false 判断
只不过是在其中加了一句判断的指针,改变了几个函数的返回值,改变了一个存储文件的路径的返回值,和初始化摄像头的返回值,同时设置指针为BOOL类型。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include "imgproc/imgproc.hpp"
#include "highgui/highgui.hpp"
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#include <QTimer>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
bool InitCamera();
bool m_IsSave;
bool SaveImage( QImage * Image);
private:
Ui::Dialog *ui;
CvCapture* m_Capture;
IplImage* m_Frame;
QTimer* m_TimeFlush;
private slots:
void OnBtCaptureClicked();
void ShowImage();
};
#endif // DIALOG_H
我一开始不知道为什么有时候connect()中加&有时候不加,一开始在前面代码中,m_TimeFlush设置的是类型变量不是指针,在这里设置的是一个类型指针,所以想取地址,就加取地址符
#include "dialog.h"
#include "ui_dialog.h"
#include <QMessageBox>
#include <QString>
#include <QImage>
#include <QFileDialog>
#include <QTimer>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
m_Capture=NULL;
m_IsSave=false;
m_TimeFlush=NULL;
m_Frame = NULL;
ui->LB_IMAGE->move( 0,0 );
ui->LB_IMAGE->resize(VIDEO_WIDTH -50,VIDEO_HEIGHT -50 );
this->resize(VIDEO_WIDTH,VIDEO_HEIGHT + 50);
m_TimeFlush=new QTimer(this);
if(m_TimeFlush==NULL)
exit(0);
m_TimeFlush->setInterval(20);
m_TimeFlush->start();
ShowImage();
connect(ui->Take,SIGNAL(clicked()),this,SLOT(OnBtCaptureClicked()));
connect(m_TimeFlush,SIGNAL(timeout()),this,SLOT(ShowImage()));
if( ! InitCamera() )
{
QMessageBox::information(this,"camera","InitCamera failed");
exit(1);
}
}
Dialog::~Dialog()
{
delete ui;
if(m_Capture)
cvReleaseCapture(&m_Capture);
if(m_TimeFlush)
{
m_TimeFlush->stop();
delete m_TimeFlush;
}
}
bool Dialog::InitCamera()
{
m_Capture=cvCreateCameraCapture(-1);
if(m_Capture==NULL)
return false;
cvSetCaptureProperty(m_Capture,CV_CAP_PROP_FRAME_WIDTH,VIDEO_WIDTH);
cvSetCaptureProperty(m_Capture,CV_CAP_PROP_FRAME_HEIGHT,VIDEO_HEIGHT);
return true;
}
void Dialog::ShowImage()
{
QImage Image;
m_Frame = cvQueryFrame(m_Capture);
if(m_Frame == NULL){
return;
}
Image = QImage( (uchar*)m_Frame->imageData ,m_Frame->width,m_Frame->height,QImage::Format_RGB888).rgbSwapped() ;
if( m_IsSave )
{
m_IsSave = false;
SaveImage( &Image );
}
ui->LB_IMAGE->setPixmap( QPixmap::fromImage(Image));
}
bool Dialog::SaveImage( QImage * Image)
{
if(Image->isNull())
return false;
return Image->save(QString("%1.png").arg(rand ()%100),"png",100);
}
void Dialog::OnBtCaptureClicked()
{
m_IsSave = true;
}
先设置m_IsSave是false,初始化为false,在初始化摄像头的函数中,如果m_IsSave为真的话,就把对象清零,同时执行存储语句