


一、获取图像帧
1.qt自带的视频相关控件,可用于提取图像帧的有QMediaPlayer,但是该控件不支持跳转帧,理论上获取所有图像帧需要将视频完整播放一遍。因此这个方案不可行。
2.使用opencv获取图像帧,opencv中有很好的获取图像帧的方案,且可以获取视频信息:长、宽、帧率、总帧数等。可以直接跳转到指定帧,很适合此项目。
void VideoProcessor::runProcessing(const QString &videoPath) {
cv::VideoCapture cap(videoPath.toStdString());
if (!cap.isOpened()) {
emit errorOccurred("Failed to open video file");
return;
}
int frameCount = 0;
int totalFrames = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_COUNT));
cv::Mat frame;
QFileInfo fileInfo(videoPath);
QString outputDir = fileInfo.absolutePath() + "/frames/";
QDir().mkpath(outputDir);
while (true) {
cap >> frame;
if (frame.empty()) break;
QString fileName = outputDir + QString::number(frameCount)+".jpg";
cv::imwrite(fileName.toStdString(), frame);
frameCount++;
}
cap.release();
emit processingComplete(outputDir);
}
以上代码为逐帧保存,若要以一定间隔取帧可以使用
cap.set(cv::CAP_PROP_POS_FRAMES,frameCount);
跳转到指定帧。
3.使用halcon获取图像帧,因为后续的暗区分析也会用到halcon,因此推荐直接用halcon来获取图像帧。
HFramegrabber AcqHandle; open_framegrabber('DirectFile', 1, 1, 0, 0, 0, 0, 'default', 8, 'rgb', -1, 'false', 'path/to/video.mp4', 'default', -1, -1, &AcqHandle); // 获取视频总帧数
Hlong firstFrame, lastFrame;
get_framegrabber_param(AcqHandle, 'first_frame', &firstFrame);
get_framegrabber_param(AcqHandle, 'last_frame', &lastFrame); // 遍历每一帧并保存
for (Hlong i = firstFrame; i <= lastFrame - 1; i++) {
HImage Image;
grab_image(&Image, AcqHandle); // 读取当前帧
write_image(Image, 'jpeg', 0, ('path/to/save/frame_' + std::to_string(i) + '.jpg').c_str()); // 保存帧
}
// 关闭视频文件
close_framegrabber(AcqHandle);
二、定位暗区,并计算暗区面积
HTuple fpath = HTuple(fileName.toLatin1().data());//加载图片
HImage img;
img.ReadImage(fpath);
HTuple hv_Width;
HTuple hv_Height;
img.GetImageSize(&hv_Width,&hv_Height);//获取图片尺寸
HImage GrayImage = img.Rgb1ToGray();//转为灰度图
HRegion region = GrayImage.Threshold(gray_l,gray_h);//按灰度阈值提取区域
HRegion regionfill = region.FillUp();//填充
HRegion regioncon = regionfill.Connection();//连通
int nums = regioncon.CountObj();//获取区域数量
qDebug()<<"obj nums:"<<nums;
for(int i=1;i<=nums;i++){//遍历所有区域,筛选
HRegion selectedregion = regioncon.SelectObj(i);
Hlong row1,col1,row2,col2;
selectedregion.SmallestRectangle1(&row1,&col1,&row2,&col2);//获取区域最小外接矩形
HTuple areavalue = selectedregion.Area();//获取区域面积
int i_area = areavalue[0].I();
if(needarea_h){//判断面积条件
if(i_area<area_l || i_area>area_h)
continue;
}
else{
if(i_area<area_l)
continue;
}
//判断区域位置条件,剔除在图像边缘的噪声暗区
if((col1>=margin) && (col2<=hv_Width-margin) && (row1>=margin) && (row2<=hv_Height-margin)){
GrayImage.OverpaintRegion(selectedregion,255,"fill");//在灰度图上绘制区域
QString proceName = outputhalcon+time.toString("hh_mm_ss")+".jpg";
GrayImage.WriteImage("jpg",0,proceName.toLatin1().data());//导出图片
qDebug()<<fileName<<"area:"<<i_area;
emit progressUpdated(frameCount*100/totalFrames,i_area,proceName);
break;
}
qDebug()<<i;
}
有图像处理、图像分析、机器视觉相关需求的,可以私信我
