Always-on computer music
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

88 líneas
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()