【发布时间】:2021-06-08 15:39:46
【问题描述】:
这听起来很容易,但我已经花了好几个小时了。有几篇标题相似的帖子,所以让我先描述一下我的问题。
我有H264 编码的视频文件,这些文件显示结肠镜检查/胃镜检查的记录。
在检查过程中,灭虫者可以制作某种截图。您可以在视频中看到这一点,因为大约一秒钟左右图像没有移动,因此有几帧显示“相同”。我想知道这些屏幕截图是什么时候制作的。
所以我首先提取了视频的图像:
ffmpeg -hwaccel cuvid -c:v h264_cuvid -i '/myVideo.mkv' -vf "hwdownload,format=nv12" -start_number 0 -vsync vfr -q:v 1 '/myFrames/%05d.jpg'
这很好用,结果是一个包含所有高质量图像的文件夹。现在的想法是比较图像x 和图像x+1(或+y),看看它们是否“相同”,如果是,则截取屏幕截图。
如果我看一下那些图像,图像看起来真的是一样的,我看不出有什么区别,但是电脑可以。
由于这些图像已被压缩/编码,因此它们有损失。我猜根据视频编码过程中的关键帧,那些“相同”图像之间的差异有时是 0,有时是“巨大”。到目前为止的问题,是时候写一点代码了:
// init mPrev with last element
cv::Mat mPrev = cv::imread(imagePaths[imagePaths.size() - 1])(*rect).clone();
cvtColor(mPrev, mPrev, cv::COLOR_BGR2GRAY);
// remove smaller noise
cv::medianBlur(mPrev, mPrev, 5);
// create binary image, shows only light reflection (landmarks) everything else is to dark
mPrev = mPrev.setTo(0, mPrev < max);
mPrev = mPrev.setTo(255, mPrev >= max);
cv::Mat diff;
std::vector<int> screenShotVec;
for (int k = start; k < end; k++) {
cv::Mat mat = cv::imread(imagePaths[k])(*rect).clone();
cvtColor(mat, mat, cv::COLOR_BGR2GRAY);
// remove smaller noise
cv::medianBlur(mat, mat, medSize);
// create binary image, shows only light reflection (landmarks) everything else is to dark
mat = mat.setTo(0, mat < max);
mat = mat.setTo(255, mat >= max);
double d = cv::sum(mat)[0];
// if image is totally black, it is not a screenshot, since parts of interest always have light reflection
if (d > 0) {
// get difference of binary images
absdiff(mPrev, mat, diff);
// differences should be very small and easy to remove with median blur
cv::medianBlur(diff, diff, 9);
d = cv::sum(diff)[0];
// no difference, it is a screenshot
if (d == 0) {
screenShotVec.push_back(k);
}
}
//clone the mat for the next round
mPrev = mat.clone();
}
}
这是迄今为止效果最好的代码。但它不是很稳定,我有来自许多不同内窥镜处理器、相机和抓取器的视频。 所以我每次都要调整。例如,如果我“cv::substract”两个伪相同的帧,这就是结果:
虽然这是我“cv::substract”两帧相机移动非常小的结果:
大多数时候相机移动得非常快,因为我将帧 x 与帧 x+y (y >= 5) 进行比较,差异更加明显,问题是当相机移动不快时。 除了 cv::substract 我尝试了几种内核大小作为中值,我尝试只用 canny 检测边缘,然后比较它们或使用 cv::norm 函数。
有没有人有建议,我如何将那些伪相同的帧转换或测量为相同的东西,而显示真实变化的帧仍然可以区分?
附言很抱歉我不能发布真实的图像,因为这是医疗数据
【问题讨论】:
-
您对比较直方图有何看法?它可能很有用,但我不确定当相机不快速移动时的直方图结果。
-
嗨@badcode,直方图是一种快速的方法,但遗憾的是,当图像不移动时它看起来非常相似。
标签: c++ opencv image-processing