OpenCV中如何绘制速度矢量为箭头使用单个静态图像
我试图绘制速度矢量像MATLAB中我们使用“颤动”功能http://www.mathworks.com/help/techdoc/ref/quiver.htmlOpenCV中如何绘制速度矢量为箭头使用单个静态图像
我需要移植相同的方法在C++中使用OpenCV库。
我听说过有几个光流法,即卢卡斯和金出武雄(cvCalOpticalFlowLK)或非洲之角和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=(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
}
}
我在这里完成当前的答案,这不能给出每个箭头的提示的正确大小。 MATLAB以一种方式实现它,当一个箭头几乎是一个点时,它没有任何提示,而对于长箭头,它显示了一个很大的提示,如下图所示。
为了得到这种效果,我们需要在箭头长度的范围内归一化每个箭头的“针尖大小”。下面的代码做的伎俩
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);
}
}
}
这是本OpenCV的代码会是什么样子
我希望这种帮助别人谷歌搜索同一个问题的例子。
的cvCalOpticalFlowLK不积速度矢量,它计算这些速度矢量。如果你没有这些矢量,你必须用两个图像调用这个函数。我想你已经有了这些载体,而你只是想绘制它们。
在这种情况下,你可以使用cv::line function,例如:
cv::line(yourImage, cv::Point(baseX, baseY), cv::Point(endX, endY));
我希望这会帮助你!
谢谢我试图用一堆不同的方式来创建一个使用一个单一的图像箭头,现在它的工作。 – wolvorinePk 2012-04-17 05:44:53
为了我的其他帮助而添加了上面的代码 – wolvorinePk 2012-04-17 05:47:51
没有符号(方向/箭头提示)的矢量绘图是不好的做法。我建议下面的答案。 – TimZaman 2014-02-24 09:38:00
基于从丹的代码和mkuse的建议,这里是相同的语法CV ::线()函数:
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);
}
我们将看到如果这些保持OpenCV的库会喜欢它:-)
下一个OpenCV版本将有[cv :: arrowedLine](https://github.com/Itseez/opencv/blob/a7006ac21c2e41b98be5d6635d75b3962000986b/modules/core/doc/drawing_functions.rst#arrowedline)可用 – PhilLab 2014-07-24 07:58:39
感谢dan有帮助 – wolvorinePk 2012-06-27 07:40:27
@wolvorinePk我很高兴它帮助了某人! – Dan 2012-06-27 08:30:06
@Dan:我可以建议你编辑代码,并将其放在像“arrowedLine()”这样的函数中。它有一个类似cv :: line()的语法? – mkuse 2014-03-27 15:26:21