参考:精选课:C++完备的实现双目摄像头图像采集、双目摄像头畸变改正、前景物体提取、生成视差图、深度图、PCL点云图
前景物体提取是盘算机视觉中的一个重要技术,可以用于视频监控、虚拟现实和盘算机视觉等范畴。
1.前景物体提取的原理
前景物体提取是将摄像机拍摄到的图像中的前景物体(如移动的人、车辆等)从配景中分离出来的过程。其原理是利用帧间差分和配景建模两个步骤。帧间差分是通过相邻帧之间像素点灰度值的差别来检测出活动目标,配景建模是通过不断更新配景图像来适应场景的变化。
2.实现步骤
步骤1:读取摄像机视频并初始化,使用OpenCV库来读取摄像机视频:
- cv::VideoCapture cap(0);
- if (!cap.isOpened()) {
- std::cout << "Cannot open camera" << std::endl;
- return -1;
- }
- cv::Mat frame;
- cap.read(frame);
复制代码 步骤2:配景建模,界说一个配景图像和一个学习率,初始值为0.01。在每一帧中,将当前帧与配景图像相减,得到一个差分图像。
- cv::Mat background;
- double learning_rate = 0.01;
- // 第一帧作为背景图像
- background = frame.clone();
- // 对于后面的帧,逐像素地计算背景图像
- while (true) {
- cap.read(frame);
- // 将当前帧与背景图像相减,得到一个差分图像
- cv::Mat diff;
- cv::absdiff(frame, background, diff);
- // 根据差分图像更新背景图像
- for (int i = 0; i < diff.rows; i++) {
- for (int j = 0; j < diff.cols; j++) {
- cv::Vec3b pixel = diff.at<cv::Vec3b>(i, j);
- if (pixel[0] > 50 || pixel[1] > 50 || pixel[2] > 50) {
- // 更新背景像素
- cv::Vec3b background_pixel = background.at<cv::Vec3b>(i, j);
- cv::Vec3b frame_pixel = frame.at<cv::Vec3b>(i, j);
- background_pixel[0] = (1 - learning_rate) * background_pixel[0] + learning_rate * frame_pixel[0];
- background_pixel[1] = (1 - learning_rate) * background_pixel[1] + learning_rate * frame_pixel[1];
- background_pixel[2] = (1 - learning_rate) * background_pixel[2] + learning_rate * frame_pixel[2];
- background.at<cv::Vec3b>(i, j) = background_pixel;
- }
- }
- }
- }
复制代码 步骤3:帧间差分,将当前帧与配景图像相减,得到差分图像。然后将差分图像进行二值化处理,得到前景物体掩模。
- // 帧间差分
- cv::Mat diff;
- cv::absdiff(frame, background, diff);
- // 二值化处理,得到前景掩模
- cv::Mat foreground_mask;
- cv::threshold(diff, foreground_mask, 50, 255, cv::THRESH_BINARY);
复制代码 步骤4:过滤掉小的前景物体,使用形态学操作对前景掩模进行处理,去除噪声和小物体。
- // 使用开运算去除噪声和小物体
- cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5));
- cv::Mat foreground_mask_filtered;
- cv::morphologyEx(foreground_mask, foreground_mask_filtered, cv::MORPH_OPEN, kernel);
复制代码 步骤5:表现结果,将原始图像和前景掩模相乘,得到只有前景物体的图像。
- // 显示结果
- cv::Mat result = frame.clone();
- cv::Mat foreground_image = cv::Mat::zeros(frame.size(), frame.type());
- frame.copyTo(foreground_image, foreground_mask_filtered);
- cv::imshow("Original Image", frame);
- cv::imshow("Foreground Mask", foreground_mask_filtered);
- cv::imshow("Foreground Image", foreground_image);
- cv::waitKey(30);
复制代码 3.完备代码
演示了对单个摄像头的前景物体提取,双目摄像机须要对两个摄像头的同一幅图片场景分别做前景物体提取,然后作为左右视图对其进行进一步畸变改正。
- #include <iostream>
- #include <opencv2/opencv.hpp>
- int main() {
- // 打开摄像机
- cv::VideoCapture cap(0);
- if (!cap.isOpened()) {
- std::cout << "Cannot open camera" << std::endl;
- return -1;
- }
- // 初始化
- cv::Mat frame;
- cap.read(frame);
- // 背景建模
- cv::Mat background;
- double learning_rate = 0.01;
- background = frame.clone();
- while (true) {
- // 读取帧
- cap.read(frame);
- // 背景建模
- cv::Mat diff;
- cv::absdiff(frame, background, diff);
- for (int i = 0; i < diff.rows; i++) {
- for (int j = 0; j < diff.cols; j++) {
- cv::Vec3b pixel = diff.at<cv::Vec3b>(i, j);
- if (pixel[0] > 50 || pixel[1] > 50 || pixel[2] > 50) {
- cv::Vec3b background_pixel = background.at<cv::Vec3b>(i, j);
- cv::Vec3b frame_pixel = frame.at<cv::Vec3b>(i, j);
- background_pixel[0] = (1 - learning_rate) * background_pixel[0] + learning_rate * frame_pixel[0];
- background_pixel[1] = (1 - learning_rate) * background_pixel[1] + learning_rate * frame_pixel[1];
- background_pixel[2] = (1 - learning_rate) * background_pixel[2] + learning_rate * frame_pixel[2];
- background.at<cv::Vec3b>(i, j) = background_pixel;
- }
- }
- }
- // 帧间差分
- cv::Mat diff2;
- cv::absdiff(frame, background, diff2);
- cv::Mat foreground_mask;
- cv::threshold(diff2, foreground_mask, 50, 255, cv::THRESH_BINARY);
- // 去除噪声和小物体
- cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5));
- cv::Mat foreground_mask_filtered;
- cv::morphologyEx(foreground_mask, foreground_mask_filtered, cv::MORPH_OPEN, kernel);
- // 显示结果
- cv::Mat result = frame.clone();
- cv::Mat foreground_image = cv::Mat::zeros(frame.size(), frame.type());
- frame.copyTo(foreground_image, foreground_mask_filtered);
- cv::imshow("Original Image", frame);
- cv::imshow("Foreground Mask", foreground_mask_filtered);
- cv::imshow("Foreground Image", foreground_image);
- cv::waitKey(30);
- }
- // 释放资源
- cap.release();
- cv::destroyAllWindows();
- return 0;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |