OpenCV-Python實戰(番外篇)——OpenCV中繪制模擬時鐘顯示當前時間
- 前言
- 模擬時鐘外觀
- 計算時針刻度 hours_orig 和 hours_dest 陣列
- 使用模擬時鐘顯示當前時間
- clock_appearance.py 完整代碼
- 相關鏈接
前言
我們已經在《OpenCV-Python實戰(3)——OpenCV中繪制圖形與文本》學習了如何使用 OpenCV 繪制圖形和文本,在本番外篇中,將進一步利用所學的繪圖函式,學習如何在實戰專案中使用繪圖,繪制模擬時鐘顯示當前時間,
模擬時鐘外觀
結合《OpenCV-Python實戰(3)——OpenCV中繪制圖形與文本》中講解的 OpenCV 中的繪圖函式(例如,cv2.line()、cv2.circle()和 cv2.putText() 等),以渲染更高級的繪圖,同時更好的理解和實際運用所了解的繪圖函式,為了將所有繪圖函式進行綜合運用,構建一個模擬時鐘來顯示當前時間——包括時針、分針和秒針,
為了實作上述需求,撰寫 clock_appearance.py 腳本,clock_appearance.py 腳本使用 cv.line() 、 cv.circle() 和 cv2.putText() 繪制模擬時鐘,首先繪制靜態時鐘外觀,我們需要兩個包含固定坐標的陣列(至于這些陣列是如何計算得到的,將在下一小節中介紹):
hours_orig = np.array([(620,320), (580, 470), (470, 580), (320, 620), (170, 580), (60, 470), (20, 320), (60, 170), (169, 61), (319, 20), (469, 60), (579, 169)])
hours_dest = np.array([(600,320), (563, 460), (460, 562), (320, 600), (180, 563), (78, 460), (40, 320), (77, 180), (179, 78), (319, 40), (459, 77), (562, 179)])
這些陣列是渲染小時刻度所必需的,因為它們定義了時鐘每小時的刻度線條,陣列定義完成后,將這些刻度進行繪制:
for i in range(0, 12):
cv2.line(image, array_to_tuple(hours_orig[i]), array_to_tuple(hours_dest[i]), colors['black'], 3)
此外,還應該繪制了一個大圓圈,對應于模擬時鐘表盤的形狀:
cv2.circle(image, (320, 320), 310, colors['black'], 8)
最后,在時鐘內繪制文本,進行個性化定制:
cv2.rectangle(image, (150, 175), (490, 270), colors['dark_gray'], -1)
cv2.putText(image, "Mastering OpenCV 4", (150, 200), 1, 2, colors['light_gray'], 1, cv2.LINE_AA)
cv2.putText(image, "with Python", (210, 250), 1, 2, colors['light_gray'], 1, cv2.LINE_AA)
一旦在影像中繪制了這些靜態資訊,我們將其復制到 image_original 影像中:
image_original = image.copy()
在下圖中,可以看到模擬時鐘的外觀:

計算時針刻度 hours_orig 和 hours_dest 陣列
為了計算計算時針刻度 hours_orig 和 hours_dest 陣列,我們撰寫 clock_hours.py 計算 hours_orig 和 hours_dest 陣列的固定坐標,為了計算小時刻度的 (x, y) 坐標,我們使用圓的引數方程:
{
x
=
x
0
+
r
?
c
o
s
(
t
)
,
0
≤
t
≤
2
π
y
=
y
0
+
r
?
s
i
n
(
t
)
,
0
≤
t
≤
2
π
\begin{cases} x=x_0+r*cos(t), & \text{$0 \le t \le 2\pi$} \\ y=y_0+r*sin(t), & \text{$0 \le t \le 2\pi$} \end{cases}
{x=x0?+r?cos(t),y=y0?+r?sin(t),?0≤t≤2π0≤t≤2π?
按照上述公式計算從 0 度開始每隔 30 度為一個時針刻度,共 12 個點 P(x, y) 的坐標( 0、30、60、90、120、150、180、210、240、270、300 和 330 ),為了獲取兩個端點的坐標,我們具有兩個不同的半徑,這樣,我們就可以得到時針刻度線的坐標:
radius = 300
center = (320, 320)
for x in (0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330):
x_coordinate = center[0] + radius * math.cos(x * 3.14 / 180)
y_coordinate = center[1] + radius * math.sin(x * 3.14 / 180)
print("x: {} y: {}".format(round(x_coordinate), round(y_coordinate)))
print("----------------------")
for x in (0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330):
x_coordinate = center[0] + (radius - 20) * math.cos(x * 3.14 / 180)
y_coordinate = center[1] + (radius - 20) * math.sin(x * 3.14 / 180)
print("x: {} y: {}".format(round(x_coordinate), round(y_coordinate)))
使用模擬時鐘顯示當前時間
得到表盤外觀后,接下來就要使用模擬時鐘顯示當前時間:
- 從當前時間獲取小時、分鐘和秒:
date_time_now = datetime.datetime.now() time_now = date_time_now.time() hour = math.fmod(time_now.hour, 12) minute = time_now.minute second = time_now.second - 將時、分和秒都轉換為角度,用于接下來指標線段的繪制:
second_angle = math.fmod(second * 6 + 270, 360) minute_angle = math.fmod(minute * 6 + 270, 360) hour_angle = math.fmod((hour*30) + (minute/2) + 270, 360) - 繪制與時針、分針和秒針對應的線段:
second_x = round(320 + 310 * math.cos(second_angle * 3.14 / 180)) second_y = round(320 + 310 * math.sin(second_angle * 3.14 / 180)) cv2.line(image, (320, 320), (second_x, second_y), colors['cyan'], 2) minute_x = round(320 + 260 * math.cos(minute_angle * 3.14 / 180)) minute_y = round(320 + 260 * math.sin(minute_angle * 3.14 / 180)) cv2.line(image, (320, 320), (minute_x, minute_y), colors['cyan'], 8) hour_x = round(320 + 220 * math.cos(hour_angle * 3.14 / 180)) hour_y = round(320 + 220 * math.sin(hour_angle * 3.14 / 180)) cv2.line(image, (320, 320), (hour_x, hour_y), colors['cyan'], 10) - 最后繪制一個小圓圈作為三根指標的連接點:
cv2.circle(image, (320, 320), 10, colors['dark_gray'], -1)
clock_appearance.py 完整代碼
clock_appearance.py 腳本完整代碼如下:
import cv2
import numpy as np
import datetime
import math
def array_to_tuple(arr):
return tuple(arr.reshape(1, -1)[0])
colors = {'blue': (255, 0, 0), 'green': (0, 255, 0), 'red': (0, 0, 255), 'yellow': (0, 255, 255),
'magenta': (255, 0, 255), 'cyan': (255, 255, 0), 'white': (255, 255, 255), 'black': (0, 0, 0),
'gray': (125, 125, 125), 'rand': np.random.randint(0, high=256, size=(3,)).tolist(),
'dark_gray': (50, 50, 50), 'light_gray': (220, 220, 220)}
# 創建畫布
image = np.zeros((640, 640, 3), dtype="uint8")
# 背景色
image[:] = colors['light_gray']
# 定義時針刻度陣列
hours_orig = np.array(
[(620, 320), (580, 470), (470, 580), (320, 620), (170, 580), (60, 470), (20, 320), (60, 170), (169, 61), (319, 20),
(469, 60), (579, 169)])
hours_dest = np.array(
[(600, 320), (563, 460), (460, 562), (320, 600), (180, 563), (78, 460), (40, 320), (77, 180), (179, 78), (319, 40),
(459, 77), (562, 179)])
# 繪制時針刻度
for i in range(0, 12):
cv2.line(image, array_to_tuple(hours_orig[i]), array_to_tuple(hours_dest[i]), colors['black'], 3)
# 繪制表盤
cv2.circle(image, (320, 320), 310, colors['black'], 8)
cv2.putText(image, "OpenCV-Python", (200, 200), 1, 1.8, colors['magenta'], 1, cv2.LINE_AA)
cv2.putText(image, "DIY clocks and watches", (150, 440), 1, 1.8, colors['magenta'], 1, cv2.LINE_AA)
image_original = image.copy()
# 模擬時鐘顯示當前時間
while True:
date_time_now = datetime.datetime.now()
# 獲取當前時間
time_now = date_time_now.time()
# 計算當前時分秒
hour = math.fmod(time_now.hour, 12)
minute = time_now.minute
second = time_now.second
print("hour:'{}' minute:'{}' second: '{}'".format(hour, minute, second))
# 獲取時、分、秒角度
second_angle = math.fmod(second * 6 + 270, 360)
minute_angle = math.fmod(minute * 6 + 270, 360)
hour_angle = math.fmod((hour * 30) + (minute / 2) + 270, 360)
print("hour_angle:'{}' minute_angle:'{}' second_angle: '{}'".format(hour_angle, minute_angle, second_angle))
# 繪制時針
second_x = round(320 + 310 * math.cos(second_angle * 3.14 / 180))
second_y = round(320 + 310 * math.sin(second_angle * 3.14 / 180))
cv2.line(image, (320, 320), (second_x, second_y), colors['cyan'], 2)
# 繪制分針
minute_x = round(320 + 260 * math.cos(minute_angle * 3.14 / 180))
minute_y = round(320 + 260 * math.sin(minute_angle * 3.14 / 180))
cv2.line(image, (320, 320), (minute_x, minute_y), colors['cyan'], 8)
# 繪制秒針
hour_x = round(320 + 220 * math.cos(hour_angle * 3.14 / 180))
hour_y = round(320 + 220 * math.sin(hour_angle * 3.14 / 180))
cv2.line(image, (320, 320), (hour_x, hour_y), colors['cyan'], 10)
cv2.circle(image, (320, 320), 10, colors['black'], -1)
cv2.imshow("clock", image)
# 獲取帶有靜態資訊的影像 :
image = image_original.copy()
if cv2.waitKey(500) & 0xFF == ord('q'):
break
# Release everything:
cv2.destroyAllWindows()
運行代碼可以看到繪制的模擬時鐘可以正確顯示當前時間:

相關鏈接
《OpenCV-Python實戰(3)——OpenCV中繪制圖形與文本》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296693.html
標籤:其他
