我想实现一个背景平均方法。我在一秒钟内拍摄了 50 帧图像,其中一些帧包含我想提取为前景的闪电。这些帧是用固定的相机拍摄的,并且这些帧是作为灰度拍摄的。我想做的是:
- 获取背景模型
- 之后,将每一帧与背景模型进行比较,以确定该帧中是否有光照。
我阅读了一些关于如何使用 cvAcc() 来完成此操作的文档,但我很难理解如何做到这一点。我希望有一段代码可以指导我并链接到可以帮助我理解如何实现这一点的文档。
提前谢谢你。
我想实现一个背景平均方法。我在一秒钟内拍摄了 50 帧图像,其中一些帧包含我想提取为前景的闪电。这些帧是用固定的相机拍摄的,并且这些帧是作为灰度拍摄的。我想做的是:
我阅读了一些关于如何使用 cvAcc() 来完成此操作的文档,但我很难理解如何做到这一点。我希望有一段代码可以指导我并链接到可以帮助我理解如何实现这一点的文档。
提前谢谢你。
在我们的一个项目中,我们有同样的任务。
要获得背景模型,我们只需创建一个类 BackgroundModel,捕获前 50 帧(假设是)并计算平均帧以避免背景模型中的像素错误。
例如,如果您从相机获得 8 位灰度图像 (CV_8UC1),则使用 CV_16UC1 初始化模型以避免剪切。
cv::Mat model = cv::Mat(HEIGHT, WIDTH, CV_16UC1, cv::Scalar(0));
现在,等待第一帧计算您的模型,只需将每一帧添加到模型中并计算接收到的帧数。
void addFrame(cv::Mat frame) {
cv::Mat convertedFrame;
frame.convertTo(convertedFrame, CV_16UC1);
cv::add(convertedFrame, model, model);
if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50
createMask();
}
}
createMask() 函数计算我们用于模型的平均帧。
void createMask() {
cv::convertScaleAbs(model, mask, 1.0 / learnedFrames);
mask.convertTo(mask, CV_8UC1);
}
现在,您只需通过BackgroundModel 类将所有帧发送到函数subtract()。如果结果是一个空的 cv::Mat,掩码仍然被计算。否则,你会得到一个减去的帧。
cv::Mat subtract(cv::Mat frame) {
cv::Mat result;
if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50
cv::subtract(frame, mask, result);
}
else {
addFrame(frame);
}
return result;
}
最后但并非最不重要的一点是,您可以使用 Scalar sum(const Mat& mtx) 来计算像素总和并确定它是否是带有灯光的帧。
MyPolygon 函数屏蔽 ROI,然后计算绝对像素差并计算白色像素的数量。
srcImage :参考图像。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <random>
using namespace std;
using namespace cv;
cv::Mat MyPolygon( Mat img )
{
int lineType = 8;
// [(892, 145), (965, 150), (933, 199), (935, 238), (970, 248), (1219, 715), (836, 709), (864, 204)]
/** Create some points */
Point rook_points[1][8];
rook_points[0][0] = Point(892, 145);
rook_points[0][1] = Point(965, 150);
rook_points[0][2] = Point(933, 199);
rook_points[0][3] = Point(935, 238);
rook_points[0][4] = Point(970, 248);
rook_points[0][5] = Point(1219, 715);
rook_points[0][6] = Point(836, 709);
rook_points[0][7] = Point(864, 204);
const Point* ppt[1] = { rook_points[0] };
int npt[] = { 8 };
cv::Mat mask = cv::Mat::zeros(img.size(), img.type());
fillPoly( mask,
ppt,
npt,
1,
Scalar( 255, 0, 0 ),
lineType
);
cv::bitwise_and(mask,img, img);
return img;
}
int main() {
/* code */
cv::Mat srcImage = cv::imread("/home/gourav/Pictures/L1 Image.png", cv::IMREAD_GRAYSCALE);
resize(srcImage, srcImage, Size(1280, 720));
// cout << " Width : " << srcImage.cols << endl;
// cout << " Height: " << srcImage.rows << endl;
if (srcImage.empty()){
std::cerr<<"Ref Image not found\n";
return 1;
}
cv::Mat img = MyPolygon(srcImage);
Mat grayBlur;
GaussianBlur(srcImage, grayBlur, Size(5, 5), 0);
VideoCapture cap("/home/gourav/GenralCode/LD3LF1_stream1.mp4");
Mat frames;
if(!cap.isOpened()){
std::cout << "Error opening video stream or file" << endl;
return -1;
}
while (1)
{
cap >> frames;
if (frames.empty())
break;
// Convert current frame to grayscale
cvtColor(frames, frames, COLOR_BGR2GRAY);
// cout << "Frame Width : " << frames.cols << endl;
// cout << "Frame Height: " << frames.rows << endl;
Mat imageBlure;
GaussianBlur(frames, imageBlure, Size(5, 5), 0);
cv::Mat frame = MyPolygon(imageBlure);
Mat dframe;
absdiff(frame, grayBlur, dframe);
// imshow("grayBlur", grayBlur);
// Threshold to binarize
threshold(dframe, dframe, 30, 255, THRESH_BINARY);
//White Pixels
int number = cv::countNonZero(dframe);
cout<<"Count: "<< number <<"\n";
if (number > 3000)
{
cout<<"generate Alert ";
}
// Display Image
imshow("dframe", dframe);
char c=(char)waitKey(25);
if (c==27)
break;
}
cap.release();
return 0;
}