绘图函数(python中文显示)
本章节内容是博主网上收集的,主要内容包括OpenCv的一些基本绘图函数的操作。
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
demo1:利用随机数画不同尺寸和颜色的圆形

demo2:利用freetype-py库显示中文字体

demo3:绘制OpenCv Logo

demo4:绘制任意图形

C#版本运行代码如下:
C#本身就支持中文字体,所以没有demo2
using OpenCvSharp;
using System;
namespace demo
{
internal class Program
{
public static RNG rng = new RNG(12345);
static void Main(string[] args)
{
demo1();
//demo2();
//demo3();
//demo4();
}
public static void click_event(MouseEventTypes @event, int x, int y, MouseEventFlags flags, IntPtr userData)
{
if (@event == MouseEventTypes.LButtonDown)
System.Diagnostics.Debug.WriteLine($"{x},{y}");
}
private static void demo1()
{
Cv2.NamedWindow("Canvas", WindowFlags.GuiExpanded);
Cv2.SetMouseCallback("Canvas", new MouseCallback(click_event));
Mat canvas = new Mat(new Size(300, 300), MatType.CV_8UC3);
while (true)
{
for (int i = 0; i < 25; i++)
{
byte b = (byte)rng.Uniform(100, 255);
byte g = (byte)rng.Uniform(100, 255);
byte r = (byte)rng.Uniform(100, 255);
int radius = (byte)rng.Uniform(5, 200);
Scalar color = new Scalar(b, g, r);
Point pt = new Point((byte)rng.Uniform(0, 300), (byte)rng.Uniform(0, 300));
Cv2.Circle(canvas, pt, radius, color, -1);
}
Cv2.ImShow("Canvas", canvas);
if (Cv2.WaitKey(1000) == 'q')
break;
}
}
private static void demo2()
{
Console.WriteLine("freetype 操作,暂无");
}
private static void demo3()
{
int r1 = 70;
int r2 = 30;
int ang = 60;
int d = 170;
int h = (int)(d / 2 * Math.Sqrt(3));
Point dot_red = new Point(256, 128);
Point dot_green = new Point((int)(dot_red.X - d / 2), dot_red.Y + h);
Point dot_blue = new Point((int)(dot_red.X + d / 2), dot_red.Y + h);
Scalar red = new Scalar(0, 0, 255);
Scalar green = new Scalar(0, 255, 0);
Scalar blue = new Scalar(255, 0, 0);
Scalar black = new Scalar(0, 0, 0);
int full = -1;
Mat img = new Mat(new Size(512, 512), MatType.CV_8UC3, new Scalar(0, 0, 0));
Cv2.Circle(img, dot_red, r1, red, full);
Cv2.Circle(img, dot_green, r1, green, full);
Cv2.Circle(img, dot_blue, r1, blue, full);
Cv2.Circle(img, dot_red, r2, black, full);
Cv2.Circle(img, dot_green, r2, black, full);
Cv2.Circle(img, dot_blue, r2, black, full);
Cv2.Ellipse(img, dot_red, new Size(r1, r1), ang, 0, ang, black, full);
Cv2.Ellipse(img, dot_green, new Size(r1, r1), 360 - ang, 0, ang, black, full);
Cv2.Ellipse(img, dot_blue, new Size(r1, r1), 360 - 2 * ang, ang, 0, black, full);
HersheyFonts font = HersheyFonts.HersheySimplex;
Cv2.PutText(img, "OpenCV", new Point(15, 450), font, 4, new Scalar(255, 255, 255), 10);
Cv2.ImShow("opencv_logo.jpg", img);
Cv2.WaitKey(0);
}
private static void demo4()
{
Mat img = new Mat(new Size(512, 512), MatType.CV_8UC3, new Scalar(0, 0, 0));
Cv2.Line(img, new Point(0, 0), new Point(511, 511), new Scalar(255, 0, 0), 5);
// polylines() 可以 用来画很多条线。只需要把想 画的线放在一 个列表中, 将 列表传给函数就可以了。
// 每条线 会被独立绘制。 这会比用 cv2.line() 一条一条的绘制 要快一些。
Cv2.ArrowedLine(img, new Point(21, 13), new Point(151, 401), new Scalar(255, 0, 0), 5);
Cv2.Rectangle(img, new Point(384, 0), new Point(510, 128), new Scalar(0, 255, 0), 3);
Cv2.Circle(img, new Point(447, 63), 63, new Scalar(0, 0, 255), -1);
// 一个参数是中心点的位置坐标。 下一个参数是长轴和短轴的长度。椭圆沿逆时针方向旋转的角度。
// 椭圆弧演顺时针方向起始的角度和结束角度 如果是 0 很 360 就是整个椭圆
Cv2.Ellipse(img, new Point(256, 256), new Size(100, 50), 0, 0, 180, 255, -1);
// 这里 reshape 的第一个参数为 - 1, 表明这一维的长度是根据后面的维度的计算出来的。
// 注意 如果第三个参数是 False 我们得到的多边形是不闭合的 ,首 尾不相 连 。
HersheyFonts font = HersheyFonts.HersheySimplex;
// 或使用 bottomLeftOrigin=True,文字会上下颠倒
Cv2.PutText(img, "bottomLeftOrigin", new Point(10, 400), font, 1, new Scalar(255, 255, 255), 1, LineTypes.Link8, true);
Cv2.PutText(img, "OpenCV", new Point(10, 500), font, 4, new Scalar(255, 255, 255), 2);
Cv2.NamedWindow("example", 0);
Cv2.ImShow("example", img);
Cv2.WaitKey(0);
Cv2.DestroyAllWindows();
}
}
}
C++版本运行代码如下:
C++本身就支持中文字体,所以没有demo2
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
// 用左键点击屏幕,打印坐标
void click_event(int event, int x, int y, int flags, void*)
{
if (event == EVENT_LBUTTONDOWN)
printf("%d,%d\r\n", x, y);
}
void demo1()
{
namedWindow("Canvas", WINDOW_GUI_EXPANDED);
setMouseCallback("Canvas", click_event);
Mat canvas(300, 300, CV_8UC3);
while (true)
{
for (size_t i = 0; i < 25; i++)
{
int radius = theRNG().uniform(5, 200);
Scalar color = Scalar(theRNG().uniform(0, 256), theRNG().uniform(0, 256), theRNG().uniform(0, 256));
Point pt = Point(theRNG().uniform(0, 300), theRNG().uniform(0, 300));
circle(canvas, pt, radius, color, -1);
}
imshow("Canvas", canvas);
if (waitKey(1000) == 'q')
break;
}
}
void demo2()
{
/* freetype 操作,暂无 */
}
void demo3()
{
int r1 = 70;
int r2 = 30;
int ang = 60;
int d = 170;
int h = int(d / 2 * sqrt(3));
Point dot_red = Point(256, 128);
Point dot_green = Point(int(dot_red.x - d / 2), dot_red.y + h);
Point dot_blue = Point(int(dot_red.x + d / 2), dot_red.y + h);
Scalar red = Scalar(0, 0, 255);
Scalar green = Scalar(0, 255, 0);
Scalar blue = Scalar(255, 0, 0);
Scalar black = Scalar(0, 0, 0);
int full = -1;
Mat img(512, 512, CV_8UC3);
img = Scalar::all(0);
circle(img, dot_red, r1, red, full);
circle(img, dot_green, r1, green, full);
circle(img, dot_blue, r1, blue, full);
circle(img, dot_red, r2, black, full);
circle(img, dot_green, r2, black, full);
circle(img, dot_blue, r2, black, full);
ellipse(img, dot_red, Point(r1, r1), ang, 0, ang, black, full);
ellipse(img, dot_green, Point(r1, r1), 360 - ang, 0, ang, black, full);
ellipse(img, dot_blue, Point(r1, r1), 360 - 2 * ang, ang, 0, black, full);
int font = FONT_HERSHEY_SIMPLEX;
putText(img, "OpenCV", Point(15, 450), font, 4, Scalar(255, 255, 255), 10);
imshow("opencv_logo.jpg", img);
waitKey(0);
}
void demo4()
{
Mat img(512, 512, CV_8UC3);
img = Scalar::all(0);
line(img, Point(0, 0), Point(511, 511), Scalar(255, 0, 0), 5);
// polylines() 可以 用来画很多条线。只需要把想 画的线放在一 个列表中, 将 列表传给函数就可以了。
// 每条线 会被独立绘制。 这会比用 cv2.line() 一条一条的绘制 要快一些。
arrowedLine(img, Point(21, 13), Point(151, 401), Scalar(255, 0, 0), 5);
rectangle(img, Point(384, 0), Point(510, 128), Scalar(0, 255, 0), 3);
circle(img, Point(447, 63), 63, Scalar(0, 0, 255), -1);
// 一个参数是中心点的位置坐标。 下一个参数是长轴和短轴的长度。椭圆沿逆时针方向旋转的角度。
// 椭圆弧演顺时针方向起始的角度和结束角度 如果是 0 很 360 就是整个椭圆
ellipse(img, Point(256, 256), Point(100, 50), 0, 0, 180, 255, -1);
// 这里 reshape 的第一个参数为 - 1, 表明这一维的长度是根据后面的维度的计算出来的。
// 注意 如果第三个参数是 False 我们得到的多边形是不闭合的 ,首 尾不相 连 。
int font = FONT_HERSHEY_SIMPLEX;
// 或使用 bottomLeftOrigin=True,文字会上下颠倒
putText(img, "bottomLeftOrigin", Point(10, 400), font, 1, Scalar(255, 255, 255), 1, true);
putText(img, "OpenCV", Point(10, 500), font, 4, Scalar(255, 255, 255), 2);
namedWindow("example", 0);
imshow("example", img);
waitKey(0);
destroyAllWindows();
}
void main()
{
//demo1();
//demo2();
//demo3();
demo4();
}
Python版本运行代码如下:
import cv2
import numpy as np
import math
import ft2
"""
利用随机数画不同尺寸和颜色的圆形
"""
def demo1():
def click_event(event, x, y, flags, param):
'''
用左键点击屏幕,打印坐标
:param event:
:param x:
:param y:
:param flags:
:param param:
:return:
'''
if event == cv2.EVENT_LBUTTONDOWN:
print(x, y, flags, param)
cv2.namedWindow('Canvas', cv2.WINDOW_GUI_EXPANDED)
cv2.setMouseCallback("Canvas", click_event)
canvas = np.zeros((300, 300, 3), dtype="uint8")
while True:
try:
for i in range(0, 25):
radius = np.random.randint(5, high=200)
color = np.random.randint(0, high=256, size=(3,)).tolist()
pt = np.random.randint(0, high=300, size=(2,))
cv2.circle(canvas, tuple(pt), radius, color, -1)
cv2.imshow("Canvas", canvas)
key = cv2.waitKey(1000) # 等待1秒
if key == ord('q'):
break
else:
# sleep(1)
continue
except KeyboardInterrupt as e:
print('KeyboardInterrupt', e)
finally:
cv2.imwrite('random-circles2.jpg', canvas)
"""
利用freetype-py库显示中文字体
pip install freetype-py ft2 -i https://mirror.baidu.com/pypi/simple
https://fireant.github.io/misc/2017/01/28/ttf-opencv.html
"""
def demo2():
img = np.zeros((100, 300, 3), dtype=np.uint8)
line = '你好中文'
color = (0, 255, 0) # Green
pos = (3, 3)
text_size = 24
# ft = put_chinese_text('wqy-zenhei.ttc')
ft = ft2.put_chinese_text('msyh.ttf')
image = ft.draw_text(img, pos, line, text_size, color)
name = u'图片展示'
cv2.imshow(name, image)
cv2.imwrite("out.jpg", image)
cv2.waitKey(0)
"""
绘制OpenCv Logo
"""
def demo3():
r1 = 70
r2 = 30
ang = 60
d = 170
h = int(d / 2 * math.sqrt(3))
dot_red = (256, 128)
dot_green = (int(dot_red[0] - d / 2), dot_red[1] + h)
dot_blue = (int(dot_red[0] + d / 2), dot_red[1] + h)
# tan = float(dot_red[0]-dot_green[0])/(dot_green[1]-dot_red[0])
# ang = math.atan(tan)/math.pi*180
red = (0, 0, 255)
green = (0, 255, 0)
blue = (255, 0, 0)
black = (0, 0, 0)
full = -1
img = np.zeros((512, 512, 3), np.uint8)
# img = np.ones((512, 512, 3), np.uint8)
cv2.circle(img, dot_red, r1, red, full)
cv2.circle(img, dot_green, r1, green, full)
cv2.circle(img, dot_blue, r1, blue, full)
cv2.circle(img, dot_red, r2, black, full)
cv2.circle(img, dot_green, r2, black, full)
cv2.circle(img, dot_blue, r2, black, full)
cv2.ellipse(img, dot_red, (r1, r1), ang, 0, ang, black, full)
cv2.ellipse(img, dot_green, (r1, r1), 360 - ang, 0, ang, black, full)
cv2.ellipse(img, dot_blue, (r1, r1), 360 - 2 * ang, ang, 0, black, full)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, text='OpenCV', org=(15, 450), fontFace=font, fontScale=4, color=(255, 255, 255),
thickness=10) # text,
cv2.imshow("opencv_logo.jpg", img)
cv2.waitKey(0)
"""
绘制任意图形
"""
def demo4():
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
# Draw a diagonal blue line with thickness of 5 px
cv2.line(img, pt1=(0, 0), pt2=(511, 511), color=(255, 0, 0), thickness=5) # pt1, pt2, color, thickness=
# cv2.polylines() 可以 用来画很多条线。只需要把想 画的线放在一 个列表中, 将 列表传给函数就可以了。每条线 会被独立绘制。 这会比用 cv2.line() 一条一条的绘制 要快一些。
# cv2.polylines(img, pts, isClosed, color, thickness=None, lineType=None, shift=None)
cv2.arrowedLine(img, pt1=(21, 13), pt2=(151, 401), color=(255, 0, 0), thickness=5)
cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
cv2.circle(img, center=(447, 63), radius=63, color=(0, 0, 255),
thickness=-1) # center, radius, color, thickness=None
# 一个参数是中心点的位置坐标。 下一个参数是长轴和短轴的长度。椭圆沿逆时针方向旋转的角度。
# 椭圆弧演顺时针方向起始的角度和结束角度 如果是 0 很 360 就是整个椭圆
cv2.ellipse(img, center=(256, 256), axes=(100, 50), angle=0, startAngle=0, endAngle=180, color=255,
thickness=-1) # center, axes, angle, startAngle, endAngle, color, thickness=
pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
pts = pts.reshape((-1, 1, 2))
# 这里 reshape 的第一个参数为-1, 表明这一维的长度是根据后面的维度的计算出来的。
# 注意 如果第三个参数是 False 我们得到的多边形是不闭合的 ,首 尾不相 连 。
font = cv2.FONT_HERSHEY_SIMPLEX
# org :Bottom-left corner of the text string in the image.左下角
# 或使用 bottomLeftOrigin=True,文字会上下颠倒
cv2.putText(img, text='bottomLeftOrigin', org=(10, 400), fontFace=font, fontScale=1, color=(255, 255, 255),
thickness=1, bottomLeftOrigin=True) # text, org, fontFace, fontScale, color, thickness=
cv2.putText(img, text='OpenCV', org=(10, 500), fontFace=font, fontScale=4, color=(255, 255, 255),
thickness=2) # text, org, fontFace, fontScale, color, thickness=
# 所有的绘图函数的返回值都是 None ,所以不能使用 img = cv2.line(img,(0,0),(5
winname = 'example'
cv2.namedWindow(winname, 0)
cv2.imshow(winname, img)
cv2.imwrite("example.jpg", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
# demo1()
# demo2()
# demo3()
demo4()