解决方案详解
绘制表盘
表盘上只有60条分/秒刻线和12条小时刻线,当然还有表盘的外部轮廓圆,也就是重点在如何画72根线。先把简单的圆画出来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import cv2 as cv
import math
import datetime
import numpy as np
margin = 5 # 上下左右边距
radius = 220 # 圆的半径
center = (center_x, center_y) = ( 225 , 225 ) # 圆心
# 1. 新建一个画板并填充成白色
img = np.zeros(( 450 , 450 , 3 ), np.uint8)
img[:] = ( 255 , 255 , 255 )
# 2. 画出圆盘
cv.circle(img, center, radius, ( 0 , 0 , 0 ), thickness = 5 )
|
我们使用opencv画直线的时候,需知道直线的起点和终点坐标,那么画72根线就变成了获取72组坐标。
平面坐标系下,已知半径和角度的话,a点的坐标可以表示为:
x=r×cosα
y=r×sinα
先只考虑将坐标系原点移动到左上角,角度依然是平面坐标系中的逆时针计算,那么新坐标是:
x=r+r×cosα
y=r+r×sinα
对于60条分/秒刻线,刻线间的夹角是360°/60=6°,对于小时刻线,角度是360°/12=30°,这样就得到了72组起点坐标,那怎么得到终点坐标呢?其实同样的原理,用一个同心的小圆来计算得到b点:
通过a/b两点就可以画出直线:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
pt1 = []
# 3. 画出60条秒和分钟的刻线
for i in range ( 60 ):
# 最外部圆,计算a点
x1 = center_x + (radius - margin) * math.cos(i * 6 * np.pi / 180.0 )
y1 = center_y + (radius - margin) * math.sin(i * 6 * np.pi / 180.0 )
pt1.append(( int (x1), int (y1)))
# 同心小圆,计算b点
x2 = center_x + (radius - 15 ) * math.cos(i * 6 * np.pi / 180.0 )
y2 = center_y + (radius - 15 ) * math.sin(i * 6 * np.pi / 180.0 )
cv.line(img, pt1[i], ( int (x2), int (y2)), ( 0 , 0 , 0 ), thickness = 2 )
# 4. 画出12条小时的刻线
for i in range ( 12 ):
# 12条小时刻线应该更长一点
x = center_x + (radius - 25 ) * math.cos(i * 30 * np.pi / 180.0 )
y = center_y + (radius - 25 ) * math.sin(i * 30 * np.pi / 180.0 )
# 这里用到了前面的pt1
cv.line(img, pt1[i * 5 ], ( int (x), int (y)), ( 0 , 0 , 0 ), thickness = 5 )
# 到这里基本的表盘图就已经画出来了
|
角度换算
接下来算是一个小难点,首先时钟的起始坐标在正常二维坐标系的90°方向,其次时钟跟图像一样,都是顺时针计算角度的,所以三者需要统一下:
因为角度是完全对称的,顺逆时针没有影响,所以平面坐标系完全不用理会,放在这里只是便于大家理解。对于时钟坐标和图像坐标,时钟0的0°对应图像的270°,时钟15的90°对应图像的360°,时钟30的180°对应图像的450°(360°+90°)…
所以两者之间的关系便是:
计算角度 = 时钟角度+270°
计算角度 = 计算角度 if 计算角度<=360° else 计算角度-360°
同步时间
python中如何获取当前时间和添加日期文字都比较简单,看代码就行,我就不解释了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
while ( 1 ):
# 不断拷贝表盘图,才能更新绘制,不然会重叠在一起
temp = np.copy(img)
# 5. 获取系统时间,画出动态的时-分-秒三条刻线
now_time = datetime.datetime.now()
hour, minute, second = now_time.hour, now_time.minute, now_time.second
# 画秒刻线
# 参见博客,opencv中的角度是顺时针计算的,所以需要转换下
sec_angle = second * 6 + 270 if second < = 15 else (second - 15 ) * 6
sec_x = center_x + (radius - margin) * math.cos(sec_angle * np.pi / 180.0 )
sec_y = center_y + (radius - margin) * math.sin(sec_angle * np.pi / 180.0 )
cv.line(temp, center, ( int (sec_x), int (sec_y)), ( 255 , 0 , 0 ), 2 )
# 画分刻线
min_angle = minute * 6 + 270 if minute < = 15 else (minute - 15 ) * 6
min_x = center_x + (radius - 35 ) * math.cos(min_angle * np.pi / 180.0 )
min_y = center_y + (radius - 35 ) * math.sin(min_angle * np.pi / 180.0 )
cv.line(temp, center, ( int (min_x), int (min_y)), ( 0 , 255 , 0 ), 8 )
# 画时刻线
hour_angle = hour * 30 + 270 if hour < = 3 else (hour - 3 ) * 30
hour_x = center_x + (radius - 75 ) * math.cos(hour_angle * np.pi / 180.0 )
hour_y = center_y + (radius - 75 ) * math.sin(hour_angle * np.pi / 180.0 )
cv.line(temp, center, ( int (hour_x), int (hour_y)), ( 0 , 0 , 255 ), 20 )
# 6. 添加当前日期文字
font = cv.font_hershey_simplex
time_str = now_time.strftime( "%d/%m/%y" )
cv.puttext(img, time_str, ( 135 , 275 ), font, 1 , ( 0 , 0 , 0 ), 2 )
cv.imshow( 'clocking' , temp)
if cv.waitkey( 1 ) = = 27 : # 按下esc键退出
break
|
以上就是python基于opencv 实现图像时钟的详细内容,更多关于python opencv 实现图像时钟的资料请关注服务器之家其它相关文章!
原文链接:https://www.cnblogs.com/wojianxin/p/12626164.html