我正在开发一款适用于天花板内置摄像头的应用程序。目的是让它跟踪表面上的物体。
我需要删除背景,以便我可以获得那里的“diff”的轮廓,但是使用BackgroundSubtractorMOG
会让人感到沮丧,因为我发现它的唯一应用是用于视频。
我需要的是提供一个将作为背景的单个图像,然后从流中计算每个帧的变化。
这就是我所拥有的:
#include <libfreenect/libfreenect_sync.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
const char *kBackgroundWindow = "Background";
const char *kForegroundWindow = "Foreground";
const char *kDiffWindow = "Diff";
const cv::Size kCameraSize(cv::Size(640, 480));
int main(int argc, char **argv) {
uint8_t *raw_frame = (uint8_t *)malloc(640 * 480 * 3);
uint32_t timestamp;
// First, we show the background window. A key press will set the background
// and move on to object detection.
cvNamedWindow(kBackgroundWindow);
cv::Mat background(kCameraSize, CV_8UC3, cv::Scalar(0));
for(;;) {
freenect_sync_get_video((void **)&raw_frame, ×tamp, 0, FREENECT_VIDEO_RGB);
background.data = raw_frame;
cv::cvtColor(background, background, CV_BGR2RGB);
cv::imshow(kBackgroundWindow, background);
if(cv::waitKey(10) > 0)
break;
}
// Create two windows, one to show the current feed and one to show the difference between
// background and feed.
cvNamedWindow(kForegroundWindow);
// Canny threshold values for the track bars
int cannyThresh1 = 20;
int cannyThresh2 = 50;
cvNamedWindow(kDiffWindow);
cv::createTrackbar("Canny Thresh 1", kDiffWindow, &cannyThresh1, 5000, NULL);
cv::createTrackbar("Canny THresh 2", kDiffWindow, &cannyThresh2, 5000, NULL);
// Start capturing frames.
cv::Mat foreground(kCameraSize, CV_8UC3, cv::Scalar(0));
cv::Mat diff(kCameraSize, CV_8UC3, cv::Scalar(0));
cv::BackgroundSubtractorMOG2 bg_subtractor(101, 100.0, false);
bg_subtractor(background, diff, 1);
for(;;) {
freenect_sync_get_video((void **)&raw_frame, ×tamp, 0, FREENECT_VIDEO_RGB);
foreground.data = raw_frame;
cv::cvtColor(foreground, foreground, CV_BGR2RGB);
// Calculate the difference between the background
// and the foreground into diff.
bg_subtractor(foreground, diff, 0.01);
// Run the Canny edge detector in the resulting diff
cv::Canny(diff, diff, cannyThresh1, cannyThresh2);
cv::imshow(kForegroundWindow, foreground);
cv::imshow(kDiffWindow, diff);
cv::waitKey(10);
}
}
如何更改此设置以便它不会“了解”新背景,只是使用background
中存储的静态图像?
谢谢!
答案 0 :(得分:1)
如果你真的只想要一个静态图像作为背景,你可以简单地从前景图像中减去背景图像:
cv::Mat diff;
cv::absdiff(foreground, background, diff);
作为旁注,我认为您拨打cv::cvtColor()
是不必要的。 OpenCV的原生图像格式为BGR,因此如果您事先转换为RGB,imshow()
将显示交换的红色和蓝色通道。