C++ OpenCV 如何在使用单个静态图像时将速度矢量绘制为箭头
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10161351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
OpenCV How to Plot velocity vectors as arrows in using single static image
提问by wolvorinePk
I am trying to plot velocity vectors like in matlab we use "quiver" function http://www.mathworks.com/help/techdoc/ref/quiver.html
我正在尝试像在 matlab 中一样绘制速度向量,我们使用“quiver”函数http://www.mathworks.com/help/techdoc/ref/quiver.html
I need to port same methodology in C++ using OpenCV library.
我需要使用 OpenCV 库在 C++ 中移植相同的方法。
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)
我听说有几种光流方法,即 Lucas and Kanade (cvCalOpticalFlowLK) 或 Horn and Schunck (cvCalOpticalFlowHS) 或 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
}
}
回答by Dan
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.
我在这里完成了当前的答案,但未能给出每个箭头尖端的正确大小。MATLAB 的方式是,当箭头接近一个点时,它没有任何尖端,而对于长箭头,它显示一个大尖端,如下图所示。
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
这是此 OpenCV 代码外观的示例
I hope this help other people Googling for the same issue.
我希望这可以帮助其他人在谷歌上搜索同样的问题。
回答by PhilLab
Based on the code from Dan and the suggestion of mkuse, here is a function with the same syntax as cv::line():
根据 Dan 的代码和 mkuse 的建议,这里有一个与 cv::line() 语法相同的函数:
static void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color,
int thickness=1, int line_type=8, int shift=0, double tipLength=0.1)
{
const double tipSize = norm(pt1-pt2)*tipLength; // Factor to normalize the size of the tip depending on the length of the arrow
line(img, pt1, pt2, color, thickness, line_type, shift);
const double angle = atan2( (double) pt1.y - pt2.y, (double) pt1.x - pt2.x );
Point p(cvRound(pt2.x + tipSize * cos(angle + CV_PI / 4)),
cvRound(pt2.y + tipSize * sin(angle + CV_PI / 4)));
line(img, p, pt2, color, thickness, line_type, shift);
p.x = cvRound(pt2.x + tipSize * cos(angle - CV_PI / 4));
p.y = cvRound(pt2.y + tipSize * sin(angle - CV_PI / 4));
line(img, p, pt2, color, thickness, line_type, shift);
}
We will see if those maintaining the OpenCV repository will like it :-)
我们将看看那些维护 OpenCV 存储库的人是否会喜欢它 :-)
回答by Samuel Gosselin
The cvCalOpticalFlowLKdoes not plot velocity vectors, it computesthese velocity vectors. If you do not have these vectors, you must call this function with two images. I guess you already have these vectors, and you just want to plot them.
该cvCalOpticalFlowLK不绘制速度矢量,它计算出这些速度矢量。如果您没有这些向量,则必须使用两个图像调用此函数。我猜你已经有了这些向量,你只想绘制它们。
In this case, you can use the cv::line function, for example:
在这种情况下,您可以使用cv::line 函数,例如:
cv::line(yourImage, cv::Point(baseX, baseY), cv::Point(endX, endY));
I hope this will help you!
我希望这能帮到您!