OpenCV绘制箭头线段---函数arrowedLine()使用(C++ Python)

时间:2022-07-23
本文章向大家介绍OpenCV绘制箭头线段---函数arrowedLine()使用(C++ Python),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

OpenCV不仅提供了绘制线段、矩形、圆等方法,还提供了一个绘制箭头线段的函数arrowedLine(),OpenCV官方文档介绍:

https://docs.opencv.org/4.4.0/d6/d6e/group__imgproc__draw.html#ga0a165a3ca093fd488ac709fdf10c05b2

以OpenCV4.4.0为例,使用此函数需要包含头文件imgproc.hpp --> #include <opencv2/imgproc.hpp>

参数也比较容易理解:

img: 需要绘制箭头的图像

pt1, pt2:绘制箭头线段的起点和终点坐标

color: 绘制箭头线段的颜色

thickness: 箭头线段的线宽(线的粗细)

line_type: 绘制线的类型参考定义LineTypes

shitf: 坐标系中的小数位数?没明白有什么用,一般设置默认为0,改了可能会乱

tipLength: 箭头笔尖的长度(相对于线段长度的比例),默认0.1,比例越大箭头越长

下面是C++ OpenCV代码演示:

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main()
{
  Mat img = Mat::zeros(300, 300, CV_8UC3);
  arrowedLine(img, Point(10, 30), Point(200, 30), Scalar(0, 255, 0), 2, 8, 0, 0.1);
  arrowedLine(img, Point(10, 100), Point(200, 100), Scalar(255, 0, 0), 2, 8, 0, 0.2);
  arrowedLine(img, Point(10, 170), Point(200, 170), Scalar(255, 0, 255), 2, 8, 0, 0.3);
  imshow("绘制箭头", img);
  waitKey(0);
  return 0;
}

效果:

下面是Python OpenCV代码演示:

import numpy as np
import cv2

img = np.zeros((300,300,3),np.uint8)
cv2.arrowedLine(img, (10, 30), (200, 30), (0, 255, 0), 
                thickness=3, line_type=cv2.LINE_4, shift=0, tipLength=0.1)
cv2.arrowedLine(img, (10, 100), (200, 100), (255, 0, 0), 
                thickness=3, line_type=cv2.LINE_4, shift=0, tipLength=0.2)
cv2.arrowedLine(img, (10, 170), (200, 170), (255, 0, 255), 

                thickness=3, line_type=cv2.LINE_4, shift=0, tipLength=0.3)
cv2.imshow('LineArrows', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

这里有一个优化版的C++ OpenCV绘制带箭头线段的函数:

http://tmjfzy.blog.163.com/blog/static/664470252012225101017794/


void drawArrow(cv::Mat& img, cv::Point pStart, cv::Point pEnd, int len, int alpha, cv::Scalar color, int thickness, int lineType)
{
    const double PI = 3.1415926;
    Point arrow;
    //计算 θ 角(最简单的一种情况在下面图示中已经展示,关键在于 atan2 函数,详情见下面)   
    double angle = atan2((double)(pStart.y - pEnd.y), (double)(pStart.x - pEnd.x));
    line(img, pStart, pEnd, color, thickness, lineType);
    //计算箭角边的另一端的端点位置(上面的还是下面的要看箭头的指向,也就是pStart和pEnd的位置) 
    arrow.x = pEnd.x + len * cos(angle + PI * alpha / 180);
    arrow.y = pEnd.y + len * sin(angle + PI * alpha / 180);
    line(img, pEnd, arrow, color, thickness, lineType);
    arrow.x = pEnd.x + len * cos(angle - PI * alpha / 180);
    arrow.y = pEnd.y + len * sin(angle - PI * alpha / 180);
    line(img, pEnd, arrow, color, thickness, lineType);
}

相对于OpenCV这个绘制方法更佳,可以设置箭头的角度,OpenCV绘制的箭头角度看起来都是45°有些呆板,调用实例:

//自定义函数绘制
drawArrow(img, Point(10, 30), Point(200, 30), 30, 30, Scalar(0, 255, 0), 2, 8);
drawArrow(img, Point(10, 100), Point(200, 100), 30, 50, Scalar(255, 0, 0), 2, 8);
drawArrow(img, Point(10, 170), Point(200, 170), 30, 60, Scalar(255, 0, 255), 2, 8);

绘制效果(个人比较喜欢角度为30°的箭头,看起来更美观):