How to draw Optical flow images from ocl::PyrLKOpticalFlow::dense()

纵然是瞬间 提交于 2019-12-22 18:34:52

问题


How to draw Optical flow images from ocl::PyrLKOpticalFlow::dense() Which actually calculates both horizontal and vertical component of the Optical flow? So I don't know how to draw them. I'm new to opencv . Can anyone help me?

Syntax :

ocl::PyrLKOpticalFlow::dense(oclMat &prevImg, oclMat& nextImg, oclMat& u, oclMat &v,oclMat &err)

回答1:


A well establische method used in the optical flow community is to display a motion vector field as a color coded image as you can see at one of the various data sets. E.g MPI dataset or the Middlebury dataset.

Therefor you estimate the length and the angle of your motion vector. And use a HSV to RGB colorspace transformation (see OpenCV cvtColor function) to create your color coded image. Use the angle of your motion vector as H (Hue) - channel and the normalized length as the S (Saturation) - channel and set V (Value) to 1. The the color of your image will show you the direction of your motion and the saturation the length ( speed ).

The code will should like this ( Note if use_value == true, the Saturation will be set to 1 and the Value channel is related to the motion vector length):

    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);}
 }



回答2:


Python

Please refer to 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

C++

Please can refer to 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);
        }
    }
}



回答3:


I did something like this in my code, a while ago:

        calcOpticalFlowPyrLK(frame_prec,frame_cur,v_corners_prec[i],corners_cur,status, err);


        for(int j=0; j<corners_cur.size(); j++){
                if(status[j]){

                    line(frame_cur,v_corners_prec[i][j],corners_cur[j],colors[i]);
                }
        }

Basically I draw a line between the points tracked by the OF in this iteration and the previous ones, this draws the optical flow lines which represent the flow on the image.

Hope this helps..



来源:https://stackoverflow.com/questions/20064818/how-to-draw-optical-flow-images-from-oclpyrlkopticalflowdense

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!