【问题标题】:Plotting Velocity Vectors in a Binary Image Using OpenCV使用 OpenCV 在二值图像中绘制速度向量
【发布时间】:2017-12-02 10:13:01
【问题描述】:

我有一个二进制(黑白)图像,我想在其上绘制某个速度的速度向量。在 MATLAB 中,我们可以使用quiver 来绘制这些向量。我正在使用 C++ 在 OpenCV 中寻找解决此问题的方法。如果有人可以分享解决方案,我将不胜感激。尽管在 SO (OpenCV How to Plot velocity vectors as arrows in using single static image) 上使用静态图像时提供了一种解决方案,但不清楚如何在二进制图像上实现它。如果有人可以指导我,我将不胜感激。 期待一些关于实施的建议。

【问题讨论】:

  • 您只需将color 参数更改为单个灰度值而不是RGB 三元组。另请注意,接受的答案使用已弃用的 C-API 调用 cvLine 而不是 C++ cv::line
  • @beaker 我对解决方案的呈现方式更加困惑。我认为他们没有共享完整的代码。他们只是放了一部分代码。

标签: c++ opencv vector


【解决方案1】:

这是我对您的问题的解决方案:在此示例中,我从来自网络摄像头的 rgb 图像开始,然后将其转换为灰度,然后在应用阈值后转换为二进制。

下一步,当您有一个二进制图像时,将其再次转换为 RGB(或 BGR 作为 OpenCV 约定)并在其上绘制您想要的任何内容。箭头的代码是您所链接内容的复制。

希望对你有帮助

cv::VideoCapture cam(n_source);
cam >> frame;

cv::Mat grey_image;
cv::Mat binary_image;  // Your binary image
cv::cvtColor(frame, grey_image, CV_RGB2GRAY);
cv::threshold(grey_image, binary_image, 100, 255, 0);

// Convert the binary to RGB
cv::Mat dst_rgb;
cv::cvtColor(binary_image, dst_rgb, CV_GRAY2BGR);

// Draw the arrow on the RGB image
int x = 200;
int y = 200;
int u = 100;
int v = 100;

cv::Point pt1,pt2;
double Theta;
double PI = 3.1416;

cv::Scalar Color(255,0,0);
int size = 5;
int Thickness = 5;

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(dst_rgb,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(dst_rgb,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(dst_rgb,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(dst_rgb,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(dst_rgb,pt1,pt2,Color,Thickness,8);  //Draw Line
}

// Plot
cv::namedWindow("test rgb");
cv::imshow("test rgb", dst_rgb);
cv::waitKey(0);

一个例子:

【讨论】:

  • 抱歉回复晚了。我生病了,所以无法回复。请告诉我如何在图中定义一定量级的速度矢量。
  • 在我编写的代码中,速度向量(或一般的向量)表示为两点之间的一条线,p1p2 类型为cv::Point。这个向量的大小就是p1p2 之间的欧几里得距离。 xy 代表直线的起点,uvp2 相对于 p1 的 x 和 y 坐标。为了修改向量的方向和大小,您只需要旋转 p2 并从 p1“拉伸”它。换句话说,只需更改 sizeTheta 的值
  • 非常感谢您的解释。此代码仅适用于一个箭头,但如果我们想用多个箭头将箭头扩展成圆形图案,您能对此提出一些建议吗!
  • 在这种情况下,您只需要定义一个 std::vector<cv::Point> p1_vecstd::vector<cv::Point> p2_vec 来存储绘制一条线所需的每个 p1p2。现在在for(int i=0; i<pt1_vec.size(); i++) 循环中,您只需调用cv::line(dst_rgb,pt1_vec.at(i),pt2_vec.at(i),Color,Thickness,8); 记住cv::line 只需像opencv 的所有其他绘图函数一样修改dst_rgb 的像素值。我的意思是没有“对象”或“内存位置”链接到 opencv 线,因此您可以绘制任何您想要的线,而不会增加内存使用量
  • 接受您的回答。非常感谢您的回答。它确实帮助了我很多。节省了我很多时间!!
【解决方案2】:

经过一番讨论,我在 OpenCV 中遇到了 cv::arrowedLine,其用法之一如下:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>

 #include <opencv2/opencv.hpp>
 #include <opencv2/highgui.hpp>

  using namespace std;
  using namespace cv;

 int main(int argc, char* argv[])
 {
auto width = 320;
auto height = 320;
auto img = cv::Mat(cv::Size(width, height), CV_8UC3); // create background image

auto center = cv::Point(width / 2, height / 2); // center point

int lineType = 8;
int thickness = 1;
double tipLength = 0.1;

img.setTo(255);                          // clear image - set to black (0) or white (255)

for (int angle = 0; angle < 360; angle += 15)
{
    auto angleRad = angle*CV_PI / 180.0;   // convert angle to radians

    auto length = 150;
    auto direction = cv::Point(length * cos(angleRad), length * sin(angleRad)); // calculate direction
    tipLength = .01 + 0.4 * (angle % 180) / 360;

    cv::arrowedLine(img, center + direction*0.5, center + direction, CV_RGB(255, angle, 0), thickness, lineType, 0, tipLength); // draw arrow!

    ++thickness;
    if (0 == angle % 45)
        thickness = 0;

    if (180 <= angle)
        lineType = CV_AA;
}
imshow("Arrowed Image", img);          // show image
waitKey();

return EXIT_SUCCESS;
}

【讨论】:

    猜你喜欢
    • 2015-12-30
    • 2017-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-22
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    相关资源
    最近更新 更多