首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++中的慢动作

C++中的慢动作
EN

Stack Overflow用户
提问于 2019-04-26 20:28:41
回答 1查看 408关注 0票数 1

我想做慢动作。我在这里看到了一个实现:https://github.com/vaibhav06891/SlowMotion

我修改了代码,只生成一个帧。

代码语言:javascript
复制
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/tracking.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
#include <string>
using namespace cv;
using namespace std;


#define CLAMP(x,min,max) (  ((x) < (min)) ? (min) : ( ((x) > (max)) ? (max) : (x) )  )

int main(int argc, char** argv)
{
    Mat frame,prevframe;
    prevframe = imread("img1.png");
    frame = imread("img2.png");

    Mat prevgray, gray;
    Mat fflow,bflow;

    Mat flowf(frame.rows,frame.cols ,CV_8UC3);   // the forward co-ordinates for interpolation
    flowf.setTo(Scalar(255,255,255));
    Mat flowb(frame.rows,frame.cols ,CV_8UC3);   // the backward co-ordinates for interpolation
    flowb.setTo(Scalar(255,255,255));
    Mat final(frame.rows,frame.cols ,CV_8UC3);

    int fx,fy,bx,by;

    cvtColor(prevframe,prevgray,COLOR_BGR2GRAY);  // Convert to gray space for optical flow calculation
    cvtColor(frame, gray, COLOR_BGR2GRAY);
    calcOpticalFlowFarneback(prevgray, gray, fflow, 0.5, 3, 15, 3, 3, 1.2, 0);  // forward optical flow
    calcOpticalFlowFarneback(gray, prevgray, bflow, 0.5, 3, 15, 3, 3, 1.2, 0);   //backward optical flow

    for (int y=0; y<frame.rows; y++) 
    {
        for (int x=0; x<frame.cols; x++) 
        {
            const Point2f fxy = fflow.at<Point2f>(y,x);
            fy = CLAMP(y+fxy.y*0.5,0,frame.rows);
            fx = CLAMP(x+fxy.x*0.5,0,frame.cols);

            flowf.at<Vec3b>(fy,fx) = prevframe.at<Vec3b>(y,x);

            const Point2f bxy = bflow.at<Point2f>(y,x);
            by = CLAMP(y+bxy.y*(1-0.5),0,frame.rows);
            bx = CLAMP(x+bxy.x*(1-0.5),0,frame.cols);
            flowb.at<Vec3b>(by,bx) = frame.at<Vec3b>(y,x);                  
        }
    }                   
    final = flowf*(1-0.5) + flowb*0.5;  //combination of frwd and bckward martrix
    cv::medianBlur(final,final,3);
    imwrite( "output.png",final);
    return 0;
}

但结果并不像预期的那样。

对于图像:

结果是:

有人知道问题出在哪里吗?

EN

回答 1

Stack Overflow用户

发布于 2019-04-26 22:29:36

光流算法不适用于您的测试图像。

第一个问题是您的测试图像在相邻像素值上的差异很小。完全黑色的线条和单色正方形没有给光流算法带来任何线索,因为算法不能一次处理整个图像,并使用小的15x15 (如您在calcOpticalFlowFarneback中设置的)像素窗口计算光流。

第二个问题是您的测试图像差别太大。棕色正方形的位置之间的距离太大。同样,Farneback无法检测到它。

尝试使用一些真实的视频帧或编辑您的测试,使其不那么单调(为正方形、背景色和矩形线设置一些纹理),并使图像上的方块彼此更接近(尝试2-10像素距离)。您还可以尝试使用calcOpticalFlowFarneback参数(请参阅here)以适合您的条件。

您可以使用此代码将获得的光流保存到图像中以进行调试:

代码语言:javascript
复制
Mat debugImage = Mat::zeros(fflow.size(), CV_8UC3);
float hsvHue, magnitude;

for (int x = 0; x < fflow.cols; x++)
{
    for (int y = 0; y < fflow.rows; y++)
    {
        auto& item = fflow.at<Vec2f>(y, x);
        magnitude = sqrtf(item[0] * item[0] + item[1] * item[1]);
        hsvHue = atan2f(item[1], item[0]) / static_cast<float>(CV_PI)* 180.f;
        // div 2 to fit 0..255 range
        hsvHue = (hsvHue >= 0. ? hsvHue : (360.f + hsvHue)) / 2.f;
        debugImage.at<Vec3b>(y, x)[0] = static_cast<uchar>(hsvHue);
        debugImage.at<Vec3b>(y, x)[1] = 255;
        debugImage.at<Vec3b>(y, x)[2] = static_cast<uchar>(255.f * magnitude);
    }
}
cvtColor(debugImage, debugImage, CV_HSV2BGR);
imwrite("OpticalFlow.png", debugImage);

这里,像素流动方向将用颜色(色调)表示,像素移动距离将用亮度表示。

尝试使用我创建的这些图像:

还要注意的是

代码语言:javascript
复制
for (int y = 0; y < frame.rows; y++)
{
    for (int x = 0; x < frame.cols; x++)
    {
        const Point2f fxy = fflow.at<Point2f>(y, x);
        fy = CLAMP(y + fxy.y*0.5, 0, frame.rows);
        fx = CLAMP(x + fxy.x*0.5, 0, frame.cols);

        flowf.at<Vec3b>(fy, fx) = prevframe.at<Vec3b>(y, x);
        ...

代码不会对一些没有移动到相应目标位置的flowf像素进行着色,而光流算法可能会产生这种情况。我会将其更改为:

代码语言:javascript
复制
for (int y = 0; y < frame.rows; y++)
{
    for (int x = 0; x < frame.cols; x++)
    {
        const Point2f fxy = fflow.at<Point2f>(y, x);
        fy = CLAMP(y - fxy.y*0.5, 0, frame.rows);
        fx = CLAMP(x - fxy.x*0.5, 0, frame.cols);
        flowf.at<Vec3b>(y, x) = prevframe.at<Vec3b>(fy, fx);

        const Point2f bxy = bflow.at<Point2f>(y, x);
        by = CLAMP(y - bxy.y*(1 - 0.5), 0, frame.rows);
        bx = CLAMP(x - bxy.x*(1 - 0.5), 0, frame.cols);
        flowb.at<Vec3b>(y, x) = frame.at<Vec3b>(by, bx);
    }
}

使用修改后的代码和我的测试,我得到以下输出:

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55867677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档