Always-on computer music
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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()