版本:
QT 5.9
OPENCV: 4.5
实现功能:打开摄像头,并截取通过鼠标拖动截取视频的一部分图片,然后保存,通过模板匹配的方式在视频中跟踪图片。
使用到技术:QT显示视频,QT打开文件,QT实现鼠标拖动截图,QT实现图片保存,QT实现图片模板匹配
第一部分:
打开视频,并通过两个label进行显示。通过定时器周期读取数据
//打开摄像头
videoCap = new VideoCapture(ui->comboBox->currentIndex());
this->videoFlag = true; timer->start(33); //33ms
*******************************************************
************************************************
//显示图片
videoCap->read(gInMat);
//qDebug()<<matframe.rows<<endl;
//qDebug()<<matframe.cols<<endl;
gInMat.copyTo(gOutMat);
emit setImageCmd(1,NULL); //发送信号给线程处理数据
QImage image = cvMat2Image(gInMat);
if(displayFlag)
{
displayFlag = false;
disImage = image; //赋值给ima
MatImage = gInMat;//保存一个mat,用于截图使用
DisplayFrom->show();
}
ui->label->setPixmap(QPixmap::fromImage(image));
//图像转换 借鉴
Mat QImage2cvMat(QImage image)
{
Mat mat;
switch(image.format())
{
case QImage::Format_ARGB32:
case QImage::Format_RGB32:
case QImage::Format_ARGB32_Premultiplied:
mat = Mat(image.height(),image.width(),CV_8UC4,(void *)image.constBits(),image.bytesPerLine());
break;
case QImage::Format_RGB888:
mat = Mat(image.height(),image.width(),CV_8UC3,(void *)image.constBits(),image.bytesPerLine());
cv::cvtColor(mat,mat,COLOR_BGR2RGB);
break;
case QImage::Format_Indexed8:
mat = Mat(image.height(),image.width(),CV_8UC1,(void *)image.constBits(),image.bytesPerLine());
break;
default:
break;
}
return mat;
}
QImage cvMat2Image(const Mat &mat)
{
//单通道
if(mat.type() == CV_8UC1) //单通道
{
QImage image(mat.cols,mat.rows,QImage::Format_Indexed8);
image.setColorCount(256); //灰度级数256
for(int i = 0;i < 256 ; i++)
{
image.setColor(i,qRgb(i,i,i));
}
uchar *pSrc = mat.data; //复制mat数据
for(int row = 0; row < mat.rows;row++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest,pSrc,mat.cols);
pSrc +=mat.step;
}
return image;
}
else if(mat.type() == CV_8UC3)
{
uchar *pSrc = mat.data;
QImage image(pSrc,mat.cols,mat.rows,mat.step,QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
const uchar *pSrc = (const uchar *)mat.data;
QImage image(pSrc,mat.cols,mat.rows,mat.step,QImage::Format_ARGB32);
//return image.copy();
return image;
}
else
{
QImage image;
return image;
}
}
/*****************************************/
鼠标截图
void DisplayDialog::on_dispushButton_clicked()
{
if(isrectFlag == false)
{
QMessageBox warn;
qDebug()<<"please2";
warn.warning(this,"wanging!","please 2");
}
else
{
if(saveflag)
{
int x,y,w,h;
x = lastPoint.x();
y = lastPoint.y();
w = endPoint.x() - x;
h = endPoint.y() - y;
Rect rect(x,y,w,h);
Mat ROI = MatImage(rect);
qDebug()<<"write,"<<w<<","<<h<<endl;
imwrite(savefilename.toStdString(),ROI);
}
else
{
QMessageBox warn;
qDebug()<<"please1";
warn.warning(this,"wanging!","please 1");
}
}
// isdRrawing = true;
}
void DisplayDialog::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
isdRrawing = true;
lastPoint = event->pos();
}
}
void DisplayDialog::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() == Qt::LeftButton)
{
endPoint = event->pos();
update();
}
}
void DisplayDialog::mouseReleaseEvent(QMouseEvent *event)
{
// qDebug()<<"release111"<<endl;
if(event->button() == Qt::LeftButton)
{
endPoint = event->pos();
// qDebug()<<"release"<<endl;
isrectFlag = true;
isdRrawing = false;
// update();
}
}
//模板匹配
result_cols = gOutMat.cols - temp1.cols +1;
result_rows = gOutMat.rows - temp1.rows+1;
result.create(result_rows,result_cols,CV_32FC1);
// bool Method_accepts_mask = (CV_)
matchTemplate(gOutMat,temp1,result,Method);//进行匹配
normalize(result,result,0,1,NORM_MINMAX,-1,Mat());//进行标准化
minMaxLoc(result,&minVal,&maxVal,&minLoc,&maxLoc,Mat());
if(Method == TM_SQDIFF ||Method == TM_SQDIFF_NORMED)
{
matchLoc =minLoc;
}
else
{
matchLoc = maxLoc;
}
rectangle(gOutMat,matchLoc,Point(matchLoc.x+temp1.cols,matchLoc.y+temp1.rows),Scalar(0,0,255),2,8,0);
// rectangle(result,matchLoc,POint(matchLoc.x+temp1.cols,matchLoc.y+temp1.rows),Scalar::all(0),2,8,0);