解决方案详解
绘制表盘
表盘上只有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