在光流路的场周围创建边界框
creating a bounding box around a field of optical flow paths
我已经使用cv::calcOpticalFlowFarneback
在openFrameworks中使用ofxOpenCv来计算视频的当前帧和前一帧中的光流。
然后,我在顶部绘制光学流场的视频,然后绘制矢量,显示高于特定阈值的区域中的运动流。
我现在想做的是创建这些运动区域的边界框,获得质心,并将x
、y
的位置存储在一个变量中以进行跟踪。
如果有帮助的话,这就是我绘制流场的方式。
if (calculatedFlow){
ofSetColor( 255, 255, 255 );
video.draw( 0, 0);
int w = gray1.width;
int h = gray1.height;
//1. Input images + optical flow
ofPushMatrix();
ofScale( 4, 4 );
//Optical flow
float *flowXPixels = flowX.getPixelsAsFloats();
float *flowYPixels = flowY.getPixelsAsFloats();
ofSetColor( 0, 0, 255 );
for (int y=0; y<h; y+=5) {
for (int x=0; x<w; x+=5) {
float fx = flowXPixels[ x + w * y ];
float fy = flowYPixels[ x + w * y ];
//Draw only long vectors
if ( fabs( fx ) + fabs( fy ) > .5 ) {
ofDrawRectangle( x-0.5, y-0.5, 1, 1 );
ofDrawLine( x, y, x + fx, y + fy );
}
}
}
}
我通过从flowX和flowY创建新图像来解决问题。这是通过将流X和流Y添加到新的CV FloatImage来完成的。
flowX +=flowY;
flowXY = flowX;
然后我可以从新创建的图像的像素中找到轮廓,然后我可以存储所有运动斑点的质心。
像这样:
contourFinder.findContours( mask, 10, 10000, 20, false );
//Storing the objects centers with contour finder.
vector<ofxCvBlob> &blobs = contourFinder.blobs;
int n = blobs.size(); //Get number of blobs
obj.resize( n ); //Resize obj array
for (int i=0; i<n; i++) {
obj[i] = blobs[i].centroid; //Fill obj array
}
我最初注意到,由于负值,运动只在x轴和y轴的一个方向上被跟踪。我通过调用cv::Mat中的abs()函数来更改光流的计算,从而解决了这个问题。
Mat img1( gray1.getCvImage() ); //Create OpenCV images
Mat img2( gray2.getCvImage() );
Mat flow;
calcOpticalFlowFarneback( img1, img2, flow, 0.7, 3, 11, 5, 5, 1.1, 0 );
//Split flow into separate images
vector<Mat> flowPlanes;
Mat newFlow;
newFlow = abs(flow); //abs flow so values are absolute. Allows tracking in both directions.
split( newFlow, flowPlanes );
//Copy float planes to ofxCv images flowX and flowY
IplImage iplX( flowPlanes[0] );
flowX = &iplX;
IplImage iplY( flowPlanes[1] );
flowY = &iplY;
对于您所问的问题,没有简单的答案。这是一个建议的解决方案。它涉及多个步骤,但如果你的域足够简单,你可以简化它。
对于每一帧,
-
使用farneback方法将流计算为比较当前帧和前一帧的两个图像
flow_x
、flow_y
。(你似乎在代码中这样做) -
将流图像转换为hsv图像,其中每个像素的色调分量表示流的角度
atan2(flow_y/flow_x)
,每个像素的值分量表示流sqrt(flow_x**2 + flow_y**2)
的大小 - 在上面的步骤中,使用阈值机制来抑制幅度低于某个阈值的流像素(使其变黑)
-
根据颜色范围分割HSV图像。你可以使用关于你的领域的先验信息,或者你可以使用色调分量的直方图来识别显著的色调范围来对像素进行分类。此步骤的结果是,可以为每个像素指定一个类。
-
将属于每个类别的像素分离为多个图像。属于分段类-1的所有像素将转到图像-1,属于分段类-2的所有像素都将转到图像-2等。现在,每个分段图像都包含HSV图像中特定颜色范围内的像素。
-
将每个分割的图像转换为黑白图像,并使用opencv的形态学操作,使用连接将其拆分为多个区域。(连接的组件)。
-
找到每个连接零部件的质心。
我发现这个参考在这种情况下很有帮助。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 试图在visual studio上用C++创建一个桌面应用程序
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- CGAL:如何创建填充边界曲线的曲面网格?
- 在 c++ 中是否允许创建具有运行时边界的数组?
- 在光流路的场周围创建边界框
- 在 C/C++ 中创建对象时编译器优化的边界是什么
- 如何创建精灵无法通过的边界框
- 创建无边界的DirectShow窗口
- 如何在网格周围创建边界
- Linux护士覆盖由box()创建的边界
- 如何创建 3D 边界框?(直接 3d 11,HLSL)
- 如何在Maya中创建带有边界框的MPxTransform节点