Skip to content

Instantly share code, notes, and snippets.

@eliocamp
Created March 10, 2024 03:48
Show Gist options
  • Save eliocamp/0e14c7f9bb8155edf59e748897d5deaf to your computer and use it in GitHub Desktop.
Save eliocamp/0e14c7f9bb8155edf59e748897d5deaf to your computer and use it in GitHub Desktop.
Move mouse with a laser pointer
library(Rvision)
X <- 1920
Y <- 1080
corners_screen <- matrix(c(0, Y,
X, Y,
X, 0,
0, 0),
ncol = 2, byrow = TRUE)
# Works on linux w/ xdotool
mouse_move <- function(x, y) {
system(paste0("xdotool mousemove ", x, " ", y))
}
countdown <- function(time = 3) {
for (t in seq_len(time)) {
cat("\r")
cat(t)
beepr::beep(1)
Sys.sleep(1)
}
beepr::beep(2)
}
grab_max_red <- function(image) {
image |>
extractChannel(3) |>
minMaxLoc() |>
_[2, ]
}
# Not used for now.
callibrate_threshold <- function(frames = 30, time = 3) {
maximum_no_laser <- 0
for (f in seq_len(frames)) {
maximum_no_laser <- max(maximum_no_laser, grab_max_red(readNext(my_stream))[[1]])
Sys.sleep(time/frames)
}
message("Point laser at screen")
Sys.sleep(3)
minimum_laser <- 255
for (f in seq_len(frames)) {
minimum_laser <- min(minimum_laser, grab_max_red(readNext(my_stream))[[1]])
Sys.sleep(time/frames)
}
(minimum_laser + maximum_no_laser)/2
}
get_corner <- function(which, stream_index = 0) {
# We need to open and close the stream because otherwise nextFrame doesn't
# return the lastest frame.
stream <- stream(index = stream_index)
on.exit(release(stream))
message(paste0("Point the laser to the ", which, " corner of the screen..."))
countdown(3)
image <- readNext(stream)
# plot(image)
max <- grab_max_red(image)
c(max[[2]], max[[3]])
}
grab_corners <- function(stream_index = 0, threshold = 200) {
corners <- c("bottom left",
"bottom right",
"top right",
"top left")
corners_canvas <- t(vapply(corners, get_corner, FUN.VALUE = numeric(2), stream_index = stream_index))
return(corners_canvas)
}
capture <- function(stream_index = 0,
time = Inf,
threshold = 200,
corners_canvas = grab_corners(stream_index = stream_index)) {
force(corners_canvas) # We need to grab the corners before starting the stream
stream <- stream(index = stream_index)
on.exit(release(stream))
M <- getPerspectiveTransform(from = corners_canvas,
to = corners_screen,
from_dim = dim(stream),
to_dim = c(Y, X))
# newDisplay("My display", nrow(stream) / 2, ncol(stream) / 2)
# on.exit(destroyDisplay("My display"), add = TRUE)
end <- as.numeric(Sys.time()) + time
while (as.numeric(Sys.time()) < end) {
image <- readNext(stream) |>
warpPerspective(M, inverse_map = FALSE, output_size = c(Y, X))
# display(image, "My display", 25, nrow(stream) / 2, ncol(stream) / 2)
max <- grab_max_red(image)
if (max[[1]] >= threshold) {
print(max) # For debugging
mouse_move(max[[2]], max[[3]])
}
}
}
capture()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment