OpenCV does not provide functions to draw an arrow. We will introduce a simple way to do it!
First, we draw a simple line (easy). Then, we plot the two segments that represent the arrow. These segments present an angle of 45 degrees (pi / 4) with the main line.
Here is the code for that:
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
void drawArrow(IplImage *image, CvPoint p, CvPoint q, CvScalar color, int arrowMagnitude = 9, int thickness=1, int line_type=8, int shift=0)
{
//Draw the principle line
cvLine(image, p, q, color, thickness, line_type, shift);
const double PI = 3.141592653;
//compute the angle alpha
double angle = atan2((double)p.y-q.y, (double)p.x-q.x);
//compute the coordinates of the first segment
p.x = (int) ( q.x + arrowMagnitude * cos(angle + PI/4));
p.y = (int) ( q.y + arrowMagnitude * sin(angle + PI/4));
//Draw the first segment
cvLine(image, p, q, color, thickness, line_type, shift);
//compute the coordinates of the second segment
p.x = (int) ( q.x + arrowMagnitude * cos(angle – PI/4));
p.y = (int) ( q.y + arrowMagnitude * sin(angle – PI/4));
//Draw the second segment
cvLine(image, p, q, color, thickness, line_type, shift);
}
//How to call this function
int main()
{
IplImage *canvas = cvCreateImage(cvSize(320, 240), IPL_DEPTH_8U, 3);
cvNamedWindow(“win”);
drawArrow(canvas, cvPoint(10, 20), cvPoint(100, 150), CV_RGB(100, 0, 255), 20);
cvShowImage(“win”, canvas);
cvWaitKey();
cvReleaseImage(&canvas);
cvDestroyAllWindows();
return 1;
}
First, we draw a simple line (easy). Then, we plot the two segments that represent the arrow. These segments present an angle of 45 degrees (pi / 4) with the main line.
Here is the code for that:
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
void drawArrow(IplImage *image, CvPoint p, CvPoint q, CvScalar color, int arrowMagnitude = 9, int thickness=1, int line_type=8, int shift=0)
{
//Draw the principle line
cvLine(image, p, q, color, thickness, line_type, shift);
const double PI = 3.141592653;
//compute the angle alpha
double angle = atan2((double)p.y-q.y, (double)p.x-q.x);
//compute the coordinates of the first segment
p.x = (int) ( q.x + arrowMagnitude * cos(angle + PI/4));
p.y = (int) ( q.y + arrowMagnitude * sin(angle + PI/4));
//Draw the first segment
cvLine(image, p, q, color, thickness, line_type, shift);
//compute the coordinates of the second segment
p.x = (int) ( q.x + arrowMagnitude * cos(angle – PI/4));
p.y = (int) ( q.y + arrowMagnitude * sin(angle – PI/4));
//Draw the second segment
cvLine(image, p, q, color, thickness, line_type, shift);
}
//How to call this function
int main()
{
IplImage *canvas = cvCreateImage(cvSize(320, 240), IPL_DEPTH_8U, 3);
cvNamedWindow(“win”);
drawArrow(canvas, cvPoint(10, 20), cvPoint(100, 150), CV_RGB(100, 0, 255), 20);
cvShowImage(“win”, canvas);
cvWaitKey();
cvReleaseImage(&canvas);
cvDestroyAllWindows();
return 1;
}
Thank you for posting your function it saved me a lot of time when I needed to do the same thing in python. Here is my python version in case anybody reading your page can make use of it.
RépondreSupprimerdef draw_arrow(image, p, q, color, arrow_magnitude=9, thickness=1, line_type=8, shift=0):
# adapted from http://mlikihazar.blogspot.com.au/2013/02/draw-arrow-opencv.html
# draw arrow tail
cv2.line(image, p, q, color, thickness, line_type, shift)
# calc angle of the arrow
angle = np.arctan2(p[1]-q[1], p[0]-q[0])
# starting point of first line of arrow head
p = (int(q[0] + arrow_magnitude * np.cos(angle + np.pi/4)),
int(q[1] + arrow_magnitude * np.sin(angle + np.pi/4)))
# draw first half of arrow head
cv2.line(image, p, q, color, thickness, line_type, shift)
# starting point of second line of arrow head
p = (int(q[0] + arrow_magnitude * np.cos(angle - np.pi/4)),
int(q[1] + arrow_magnitude * np.sin(angle - np.pi/4)))
# draw second half of arrow head
cv2.line(image, p, q, color, thickness, line_type, shift)
Thanks a lot !
SupprimerThank you both, you have saved me time.
RépondreSupprimerPlease give me your bitcoin address, I would like you to have a beer on me.
Thank you so much for this code :)
RépondreSupprimer