Skip to content

Instantly share code, notes, and snippets.

@addam
Created September 14, 2019 09:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save addam/191f137806df6a7c3778c952bde7fb4e to your computer and use it in GitHub Desktop.
Save addam/191f137806df6a7c3778c952bde7fb4e to your computer and use it in GitHub Desktop.
Interactive board using a laser pointer
#!/usr/bin/python3
import cv2
import numpy
import pyautogui
# usage:
# after launch, a shot from the camera appears.
# mark four corners of the projector by clicking in order: top left, bottom left, bottom right, top right
# the program moves mouse when it sees the laser pointer on-screen
# the program never exits (you have to kill it)
# dimensions of the image while being processed
# (set this lower for faster processing. Do not set higher than camera resolution)
in_shape = 640, 480
# dimensions and of the projector screen and its offset in multi-screen layout
out_shape = 1024, 768
out_offset = 1920, 0
tsf = None
def camera(source):
cam = cv2.VideoCapture(source)
while 1:
status, img = cam.read()
if not status:
return
yield img
def move(pos):
pos = [out_offset[i] + int(out_shape[i] * pos[i] / in_shape[i]) for i in range(2)]
pyautogui.moveTo(*pos)
def init(img):
src_points = []
def onmouse(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
src_points.append((x, y))
if len(src_points) == 4:
cv2.destroyAllWindows()
winname = "init"
cv2.imshow(winname, img)
cv2.setMouseCallback(winname, onmouse)
cv2.waitKey()
dst_points = numpy.array(((0, 0), (0, in_shape[1]), in_shape, (in_shape[0], 0)))
src_points = numpy.array(src_points)
tsf, _ = cv2.findHomography(src_points, dst_points)
return tsf
for img in camera(0):
if tsf is None:
tsf = init(img)
b, g, r = cv2.split(img)
img = cv2.warpPerspective(r, tsf, in_shape)
_, img = cv2.threshold(img, 245, 255, cv2.THRESH_BINARY)
_, contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
positions = list()
for pts in contours:
if pts.shape[0] > 4:
rect = cv2.fitEllipse(pts)
cv2.ellipse(img, rect, 255)
pos, (w, h), angle = rect
if 2 <= w <= 10 and 2 <= h <= 10 and 0.5 <= w / h <= 2:
positions.append(pos)
if len(positions) == 1:
move(positions[0])
# cv2.imshow("warped", img)
# if cv2.waitKey(1) == 27:
# break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment