OpenCV如何在使用单个静态图像时将速度矢量绘制为箭头 [英] OpenCV How to Plot velocity vectors as arrows in using single static image

查看:1094
本文介绍了OpenCV如何在使用单个静态图像时将速度矢量绘制为箭头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在绘制速度矢量,就像在matlab中一样,我们使用颤抖函数 http:// www .mathworks.com / help / techdoc / ref / quiver.html



我需要在C ++中使用OpenCV库移植相同的方法。



我听说有几个光流法,即Lucas和Kanade(cvCalOpticalFlowLK)或Horn和Schunck(cvCalOpticalFlowHS)或者块匹配方法(cvCalOpticalFlowBM) >

但是所有这些功能都需要两个图像,而我需要使用一个图像,因为我在处理指纹。



请帮我...




找到的解决方案

  void cvQuiver(IplImage * Image,int x,int y,int u,int v,CvScalar Color,
int Size,int Thickness){
cv :: Point pt1,pt2;
double Theta;
double PI = 3.1416;

if(u == 0)
Theta = PI / 2;
else
Theta = atan2(double(v),(double)(u));

pt1.x = x;
pt1.y = y;

pt2.x = x + u;
pt2.y = y + v;

cv :: line(Image,pt1,pt2,Color,Thickness,8); // Draw Line


Size =(int)(Size * 0.707);


if(Theta == PI / 2& pt1.y> pt2.y)
{
pt1.x = Size * cos(Theta)-Size * sin(Theta)+ pt2.x);
pt1.y =(int)(Size * sin(Theta)+ Size * cos(Theta)+ pt2.y);
cv :: line(Image,pt1,pt2,Color,Thickness,8); // Draw Line

pt1.x =(int)(Size * cos(Theta)+ Size * sin(Theta)+ pt2.x);
pt1.y =(int)(Size * sin(Theta)-Size * cos(Theta)+ pt2.y);
cv :: line(Image,pt1,pt2,Color,Thickness,8); // Draw Line
}
else {
pt1.x =(int)( - Size * cos(Theta)-Size * sin(Theta)+ pt2.x);
pt1.y =(int)( - Size * sin(Theta)+ Size * cos(Theta)+ pt2.y);
cv :: line(Image,pt1,pt2,Color,Thickness,8); // Draw Line

pt1.x =(int)( - Size * cos(Theta)+ Size * sin(Theta)+ pt2.x);
pt1.y =(int)( - Size * sin(Theta)-Size * cos(Theta)+ pt2.y);
cv :: line(Image,pt1,pt2,Color,Thickness,8); // Draw Line
}

}


解决方案

我在这里完成当前的答案,无法给出每个箭头的正确大小的提示。 MATLAB以这样的方式,当一个箭头几乎是一个点,它没有任何提示,而对于长箭头它显示一个大提示,如下图所示。



>



得到这个效果,我们需要在箭头的长度范围内规范化每个箭头的尖端大小。

  double l_max = -10; 

for(int y = 0; y {
for (int x = 0; x {
double dx = cvGetReal2D(velx,y,x); //获取流程的X组件
double dy = cvGetReal2D(vely,y,x); //获取流程的Y分量

CvPoint p = cvPoint(x,y);

double l = sqrt(dx * dx + dy * dy); //该函数设置用于绘制图像的基本阈值

if(l> l_max)l_max = 1;
}
}


for(int y = 0; y {
for (int x = 0; x {
double dx = cvGetReal2D(velx,y,x); //获取流程的X组件
double dy = cvGetReal2D(vely,y,x); //获取流程的Y分量

CvPoint p = cvPoint(x,y);

double l = sqrt(dx * dx + dy * dy); //此函数设置绘制图像的基本阈值
if(l> 0)
{
double spinSize = 5.0 * l / l_max; //因子将箭头的长度归一化自旋的大小

CvPoint p2 = cvPoint(p.x +(int)(dx),p.y +(int)(dy)
cvLine(resultDenseOpticalFlow,p,p2,CV_RGB(0,255,0),1,CV_AA);

双角度//绘制箭头的旋转
angle = atan2((double)p.y - p2.y,(double)p.x - p2.x);

p.x =(int)(p2.x + spinSize * cos(angle + 3.1416 / 4));
p.y =(int)(p2.y + spinSize * sin(angle + 3.1416 / 4));
cvLine(resultDenseOpticalFlow,p,p2,CV_RGB(0,255,0),1,CV_AA,0);

p.x =(int)(p2.x + spinSize * cos(angle - 3.1416 / 4));
p.y =(int)(p2.y + spinSize * sin(angle - 3.1416 / 4));
cvLine(resultDenseOpticalFlow,p,p2,CV_RGB(0,255,0),1,CV_AA,0)

}
}
}

是这个OpenCV代码如何的示例





我希望这篇文章能帮助其他人为同一个问题Googling。


I am trying to plot velocity vectors like in matlab we use "quiver" function http://www.mathworks.com/help/techdoc/ref/quiver.html

I need to port same methodology in C++ using OpenCV library.

I have heard There are a few optical flow methods, i.e. Lucas and Kanade (cvCalOpticalFlowLK) or Horn and Schunck (cvCalOpticalFlowHS) or Block Matching method (cvCalOpticalFlowBM)

but all of these functions take two images , while i need to use one image because i am working on fingerprints.

Kindly help me ...

[Edit] Solution found

void cvQuiver(IplImage*Image,int x,int y,int u,int v,CvScalar Color,
                                            int Size,int Thickness){
cv::Point pt1,pt2;
double Theta;
double PI = 3.1416;

if(u==0)
    Theta=PI/2;
else
    Theta=atan2(double(v),(double)(u));

pt1.x=x;
pt1.y=y;

pt2.x=x+u;
pt2.y=y+v;

cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line


Size=(int)(Size*0.707);


if(Theta==PI/2 && pt1.y > pt2.y)
    {
    pt1.x=(int)(Size*cos(Theta)-Size*sin(Theta)+pt2.x);
    pt1.y=(int)(Size*sin(Theta)+Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line

    pt1.x=(int)(Size*cos(Theta)+Size*sin(Theta)+pt2.x);
    pt1.y=(int)(Size*sin(Theta)-Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line
  }
else{
    pt1.x=(int)(-Size*cos(Theta)-Size*sin(Theta)+pt2.x);
    pt1.y=(int)(-Size*sin(Theta)+Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line

    pt1.x=(int)(-Size*cos(Theta)+Size*sin(Theta)+pt2.x);
    pt1.y=(int)(-Size*sin(Theta)-Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line
    }

}

解决方案

I am kind of completing the current answer here, which fails in giving the right size of each of the arrows' tip. MATLAB does it in a way that when an arrow is nearly a dot, it doesn't have any tip, while for long arrows it shows a big tip, as the following image shows.

To get this effect, we need to normalise the "tip size" of each of the arrow over the range of arrows' length. The following code does the trick

    double l_max = -10;

    for (int y = 0; y < img_sz.height; y+=10)                                                           // First iteration, to compute the maximum l (longest flow)
    {
        for (int x = 0; x < img_sz.width; x+=10)
        {
            double dx = cvGetReal2D(velx, y, x);                                                        // Gets X component of the flow
            double dy = cvGetReal2D(vely, y, x);                                                        // Gets Y component of the flow

            CvPoint p = cvPoint(x, y);

            double l = sqrt(dx*dx + dy*dy);                                                             // This function sets a basic threshold for drawing on the image

            if(l>l_max) l_max = l;
        }
    }


    for (int y = 0; y < img_sz.height; y+=10)
{
    for (int x = 0; x < img_sz.width; x+=10)
    {
        double dx = cvGetReal2D(velx, y, x);                                                        // Gets X component of the flow
        double dy = cvGetReal2D(vely, y, x);                                                        // Gets Y component of the flow

        CvPoint p = cvPoint(x, y);

        double l = sqrt(dx*dx + dy*dy);                                                             // This function sets a basic threshold for drawing on the image
        if (l > 0)
        {
            double spinSize = 5.0 * l/l_max;                                                        // Factor to normalise the size of the spin depeding on the length of the arrow

            CvPoint p2 = cvPoint(p.x + (int)(dx), p.y + (int)(dy));
            cvLine(resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA);

            double angle;                                                                           // Draws the spin of the arrow
            angle = atan2( (double) p.y - p2.y, (double) p.x - p2.x );

            p.x = (int) (p2.x + spinSize * cos(angle + 3.1416 / 4));
            p.y = (int) (p2.y + spinSize * sin(angle + 3.1416 / 4));
            cvLine( resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA, 0 );

            p.x = (int) (p2.x + spinSize * cos(angle - 3.1416 / 4));
            p.y = (int) (p2.y + spinSize * sin(angle - 3.1416 / 4));
            cvLine( resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA, 0 );

        }
   }
}

And this is an example of how this OpenCV code would look like

I hope this help other people Googling for the same issue.

这篇关于OpenCV如何在使用单个静态图像时将速度矢量绘制为箭头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆