C++ 围绕光流路径场创建边界框

C++ 围绕光流路径场创建边界框,c++,opencv,openframeworks,opticalflow,C++,Opencv,Openframeworks,Opticalflow,我使用了cv::calcOpticalFlowFarneback在openFrameworks中使用ofxOpenCv计算当前和以前视频帧中的光流 然后我画了视频,上面有光流场,然后画了向量,显示了在某个阈值以上区域的运动流 我现在要做的是创建这些运动区域的边界框,获取质心并将其x,y位置存储在变量中以进行跟踪 如果有帮助的话,这就是我绘制流场的方式 if (calculatedFlow){ ofSetColor( 255, 255, 255 ); video.draw( 0,

我使用了
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 );
                }
              }
            }
          } 
if(计算流量){
设置颜色(255、255、255);
视频绘制(0,0);
int w=灰色1.5倍宽度;
int h=灰色1.1高度;
//1.输入图像+光流
矩阵();
量表(4,4);
//光流
float*flowXPixels=flowX.getPixelsAsFloats();
float*flowYPixels=flowY.getPixelsAsFloats();
设置颜色(0,0,255);

对于(int y=0;y对于你所问的问题,没有简单的答案。这里是一个建议的解决方案。它涉及多个步骤,但如果你的领域足够简单,你可以简化它

对于每个帧

  • 使用farneback方法将流计算为两幅图像,将当前帧与前一帧进行比较

  • 将流图像转换为hsv图像,其中每个像素的色调分量表示流的角度
    atan2(流y/流x)
    ,每个像素的值分量表示流的大小
    sqrt(流x\*\*2+流y\*\\*2)

  • 在上面的步骤中,使用阈值机制抑制大小低于某个阈值的流像素(使其变为黑色)
  • 根据颜色范围分割HSV图像。您可以使用有关域的先验信息,也可以使用色调分量的直方图并识别突出的色调范围来对像素进行分类。通过此步骤,您可以为每个像素指定一个类别

  • 将属于每个类别的像素分离为多个图像。属于分割类别1的所有像素将转到图像1,属于分割类别2的所有像素将转到图像2等。现在,每个分割图像包含HSV图像中特定颜色范围内的像素

  • 将每个分割图像转换为黑白图像,并使用opencv的形态学操作使用连接性将其分割为多个区域。(连接的组件)

  • 找到每个连接组件的质心


  • 我发现在这方面很有帮助。

    我通过从我的flowX和flowY创建新图像来解决问题。这是通过将flowX和flowY添加到新图像中来完成的

    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
    }
    
    contourFinder.findContours(掩码,10,10000,20,false);
    //使用轮廓查找器存储对象中心。
    向量&blobs=contourFinder.blobs;
    int n=blob.size();//获取blob的数量
    调整对象大小(n);//调整对象数组大小
    
    对于(int i=0;这有助于理解更多的概念。我想cv::Mat可以处理不同运动矢量中的三角,因为我只需要在从这两个矢量获得像素后对图像进行阈值设置。谢谢。
    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;