Python基于OpenCV实现动态图像时钟

慢慢来
慢慢来
发布时间:2026-10-15 | 2人浏览过
原创

本文详细介绍如何使用Python和OpenCV库实现一个动态图像时钟。内容涵盖表盘绘制、72根刻线的坐标计算、角度转换逻辑以及实时时间同步更新。通过解析平面坐标系与图像坐标系的转换关系,提供完整的代码实现方案,帮助开发者掌握OpenCV在图形绘制和时间处理方面的应用技巧。

解决方案详解

绘制表盘

表盘设计包含60条分/秒刻线和12条小时刻线,以及外部轮廓圆。核心难点在于如何准确绘制这72根线条。首先,我们需要绘制出基础的圆形轮廓:


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组坐标点的问题。在平面坐标系中,已知半径r和角度α,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两点坐标即可绘制出直线:


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°;若计算角度>360°,则计算角度 = 计算角度-360°。

同步时间

在Python中获取当前时间和添加日期文字较为简单,具体实现请参考代码,此处不再赘述。


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实现图像时钟的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表