如何从ocl :: PyrLKOpticalFlow :: dense()绘制光流图像

joe*_*joe 2 opencv opticalflow

如何绘制光流图像ocl::PyrLKOpticalFlow::dense()实际上计算光流的水平和垂直分量?所以我不知道如何绘制它们.我是opencv的新手.谁能帮我?

句法 :

ocl::PyrLKOpticalFlow::dense(oclMat &prevImg, oclMat& nextImg, oclMat& u, oclMat &v,oclMat &err)
Run Code Online (Sandbox Code Playgroud)

Tob*_*nst 8

在光流社区中使用的良好建立方法是将运动矢量场显示为彩色编码图像,如您在各种数据集之一处所见.例如MPI数据集Middlebury数据集.

因此,您可以估计运动矢量的长度和角度.并使用HSV到RGB颜色空间转换(请参阅OpenCV cvtColor函数)来创建颜色编码图像.使用运动矢量的角度作为H(色调) - 通道,将标准化长度用作S(饱和度) - 通道,并将V(值)设置为1.图像的颜色将显示运动的方向和饱和度的长度(速度).

代码应该是这样的(注意如果use_value == true,则饱和度将设置为1并且Value通道与运动矢量长度相关):

    void FlowToRGB(const cv::Mat & inpFlow,
                cv::Mat & rgbFlow,
                const float & max_size ,
                bool use_value)
{
    if(inpFlow.empty()) return;
    if( inpFlow.depth() != CV_32F)
        throw(std::exception("FlowToRGB: error inpFlow wrong data type ( has be CV_32FC2"));
    const float grad2deg = (float)(90/3.141);
    cv::Mat pol(inpFlow.size(), CV_32FC2);

    float mean_val = 0, min_val = 1000, max_val = 0;
    float _dx, _dy;

    for(int r = 0; r < inpFlow.rows; r++)
    {
        for(int c = 0; c < inpFlow.cols; c++)
        {
            cv::Point2f polar = cvmath::toPolar(inpFlow.at<cv::Point2f>(r,c));
            polar.y *= grad2deg;
            mean_val +=polar.x;
            max_val = MAX(max_val, polar.x);
            min_val = MIN(min_val, polar.x);
            pol.at<cv::Point2f>(r,c) = cv::Point2f(polar.y,polar.x);
        }
    }
    mean_val /= inpFlow.size().area();
    float scale = max_val - min_val;
    float shift = -min_val;//-mean_val + scale;
    scale = 255.f/scale;
    if( max_size > 0)
    {
        scale = 255.f/max_size;
        shift = 0;
    }

    //calculate the angle, motion value 
    cv::Mat hsv(inpFlow.size(), CV_8UC3);
    uchar * ptrHSV = hsv.ptr<uchar>();
    int idx_val  = (use_value) ? 2:1;
    int idx_sat  = (use_value) ? 1:2;


    for(int r = 0; r < inpFlow.rows; r++, ptrHSV += hsv.step1())
    {
        uchar * _ptrHSV = ptrHSV;
        for(int c = 0; c < inpFlow.cols; c++, _ptrHSV+=3)
        {
            cv::Point2f vpol = pol.at<cv::Point2f>(r,c);

            _ptrHSV[0] = cv::saturate_cast<uchar>(vpol.x);
            _ptrHSV[idx_val] = cv::saturate_cast<uchar>( (vpol.y + shift) * scale);  
            _ptrHSV[idx_sat] = 255;
        }
    }   
    cv::Mat rgbFlow32F;
    cv::cvtColor(hsv, rgbFlow32F, CV_HSV2BGR);
    rgbFlow32F.convertTo(rgbFlow, CV_8UC3);}
 }
Run Code Online (Sandbox Code Playgroud)


Yeo*_*Yeo 5

Python

请参阅 opt_flow.py#draw_flow

def draw_flow(img, flow, step=16):
    h, w = img.shape[:2]
    y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
    fx, fy = flow[y,x].T
    lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
    lines = np.int32(lines + 0.5)
    vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    cv2.polylines(vis, lines, 0, (0, 255, 0))
    for (x1, y1), (x2, y2) in lines:
        cv2.circle(vis, (x1, y1), 1, (0, 255, 0), -1)
    return vis
Run Code Online (Sandbox Code Playgroud)

C++

请参考tvl1_optical_flow.cpp#drawOpticalFlow

static void drawOpticalFlow(const Mat_<Point2f>& flow, Mat& dst, float maxmotion = -1)
{
    dst.create(flow.size(), CV_8UC3);
    dst.setTo(Scalar::all(0));

    // determine motion range:
    float maxrad = maxmotion;

    if (maxmotion <= 0)
    {
        maxrad = 1;
        for (int y = 0; y < flow.rows; ++y)
        {
            for (int x = 0; x < flow.cols; ++x)
            {
                Point2f u = flow(y, x);

                if (!isFlowCorrect(u))
                    continue;

                maxrad = max(maxrad, sqrt(u.x * u.x + u.y * u.y));
            }
        }
    }

    for (int y = 0; y < flow.rows; ++y)
    {
        for (int x = 0; x < flow.cols; ++x)
        {
            Point2f u = flow(y, x);

            if (isFlowCorrect(u))
                dst.at<Vec3b>(y, x) = computeColor(u.x / maxrad, u.y / maxrad);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)