Always-on computer music
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

88 řádky
2.5KB

  1. import math
  2. import time
  3. import itertools as it
  4. import cv2
  5. import colorsys
  6. from pythonosc import udp_client
  7. import numpy as np
  8. DENSITY = 4
  9. RED = [0, 0, 255]
  10. N_COLORS = 3
  11. LAST_MESSAGE_TIME = 0
  12. def draw_rectangle(frame, sp, ep):
  13. """ Draw a rectangle on the frame """
  14. return cv2.rectangle(frame, sp, ep, RED, 1)
  15. def analyze_block(frame, osc, index, sp, ep, send=False):
  16. """ Analyze a block """
  17. block = frame[sp[1]:ep[1], sp[0]:ep[0], 0:3]
  18. average_color = np.average(block, (0, 1)) / 255
  19. h, s, v = colorsys.rgb_to_hsv(*average_color)
  20. # Configure the oscillator
  21. if send:
  22. print("Sending message", h, s, v)
  23. osc.send_message(
  24. "/radio",
  25. [int(index), float(h),
  26. float(s), float(v), .5])
  27. # Draw a blob of the average color
  28. sp2 = tuple(int(x) for x in (2 * np.array(sp) + np.array(ep)) / 3)
  29. ep2 = tuple(int(x) for x in (np.array(sp) + 2 * np.array(ep)) / 3)
  30. frame = cv2.rectangle(frame, sp2, ep2,
  31. [int(x * 255) for x in average_color], -1)
  32. # Draw the image
  33. for thickness, color in ((3, (0, 0, 0)), (1, (255, 255, 255))):
  34. frame = cv2.putText(frame,
  35. text=f"{h:.2f} {s:.2f} {v:.2f}",
  36. org=(sp[0] + 10, sp[1] + 20),
  37. fontScale=.5,
  38. color=color,
  39. fontFace=2,
  40. thickness=thickness)
  41. return frame
  42. def analyze(frame, osc):
  43. """ Analyze the full frame """
  44. global LAST_MESSAGE_TIME
  45. height, width, d = frame.shape
  46. n = DENSITY
  47. m = math.ceil(n * (height / width))
  48. dx = width / n
  49. dy = height / m
  50. send = False
  51. if time.time() - LAST_MESSAGE_TIME > 0.1:
  52. LAST_MESSAGE_TIME = time.time()
  53. send = True
  54. for index, (y, x) in enumerate(it.product(range(m), range(n))):
  55. sp = (int(x * dx), int(y * dy))
  56. ep = (int(x * dx + dx), int(y * dy + dy))
  57. frame = draw_rectangle(frame, sp, ep)
  58. frame = analyze_block(frame, osc, index, sp, ep, send)
  59. return frame
  60. if __name__ == '__main__':
  61. camera = cv2.VideoCapture("/dev/video2")
  62. # camera = cv2.VideoCapture(0)
  63. osc = udp_client.SimpleUDPClient("0.0.0.0", 5005)
  64. while True:
  65. ret, frame = camera.read()
  66. frame = analyze(frame, osc)
  67. cv2.imshow('Input', frame)
  68. c = cv2.waitKey(1)
  69. if c == 27:
  70. break
  71. camera.release()
  72. cv2.destroyAllWindows()