Рисование аналоговых часов в OpenCV для отображения текущего времени

компьютерное зрение OpenCV
Рисование аналоговых часов в OpenCV для отображения текущего времени

«Это 27-й день моего участия в ноябрьском испытании обновлений. Подробную информацию об этом событии см.:Вызов последнего обновления 2021 г."

предисловие

В этой статье я буду использовать функцию рисования, чтобы узнать, как использовать рисование в реальных проектах для рисования аналоговых часов для отображения текущего времени.

Внешний вид аналоговых часов

комбинировать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=x0+r*cos(t),0t2число Пиy=y0+r*sin(t),0t2число Пи\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}

Рассчитано по приведенной выше формуле, каждые 30 градусов от 0 градусов - это шкала часовой стрелки, всего 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)))

Отображение текущего времени с помощью аналоговых часов

Когда у вас появится внешний вид циферблата, следующим шагом будет использование аналоговых часов для отображения текущего времени:

  1. Получить часы, минуты и секунды из текущего времени:
    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
    
  2. Преобразование часов, минут и секунд в градусы для следующего сегмента указателя:
    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)
    
  3. Нарисуйте отрезки, соответствующие часовой, минутной и секундной стрелкам:
    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)
    
  4. Наконец, нарисуйте маленький круг в качестве точки соединения трех указателей:
    cv2.circle(image, (320, 320), 10, colors['dark_gray'], -1)
    

Запустив код, вы увидите, что нарисованные аналоговые часы могут корректно отображать текущее время:

模拟时钟显示当前时间