The following is the code form that post (though this uses VideoIO
)
using JpegTurbo, VideoIO
using GenieFramework
@genietools
# a convinience function to convert pixel matrices to jpegs
to_frame = String â jpeg_encode
# open the camera
cam = opencamera()
# use `img` as a container for the frames
const img = Ref(read(cam))
# use `frame` as a container for the jpeg
const frame = Ref(to_frame(img[]))
# fetch fresh frames from the camera as quickly as possible
Threads.@spawn while isopen(cam)
read!(cam, img[])
frame[] = to_frame(img[]) # this typically takes less than the camera's 1/fps
yield()
end
# avoid writing to disk, when the user asks for a frame they get the latest one
route("/frame") do
frame[]
end
@app Webcam begin
@out imageurl = "/frame"
end myhandlers
global model = init(Webcam, debounce = 0) |> myhandlers
# add an (invalid) anchor to the imagepath in order to trigger a reload in the Quasar/Vue backend
Stipple.js_methods(model::Webcam) = """updateimage: async function () { this.imageurl = "frame#" + new Date().getTime() }"""
# have the client update the image every 33 milliseconds (should be changed to the camera's actual 1000/fps or less)
Stipple.js_created(model::Webcam) = "setInterval(this.updateimage, 33)"
# set the image style to basic to avoid the loading wheel etc
ui() = [imageview(src=:imageurl, basic=true)]
route("/") do
page(model, ui) |> html
end
Server.up()
and here is how I use libcamera
:
function get_buffer_img(w, h)
w2 = 64ceil(Int, w/64) # dimension adjustments to hardware restrictions
nb = Int(w2*h*3/2) # total number of bytes per img
buff = Vector{UInt8}(undef, nb)
i1 = (w - h) á 2
i2 = i1 + h - 1
img = view(reshape(view(buff, 1:w2*h), w2, h), i1:i2, h:-1:1)
return buff, img
end
struct Camera
mode::CamMode
buff::Vector{UInt8}
img::SubArray{UInt8, 2, Base.ReshapedArray{UInt8, 2, SubArray{UInt8, 1, Vector{UInt8}, Tuple{UnitRange{Int64}}, true}, Tuple{}}, Tuple{UnitRange{Int64}, StepRange{Int64, Int64}}, false}
proc::Base.Process
function Camera(cm::CamMode)
w, h, fps = camera_settings(cm)
buff, img = get_buffer_img(w, h)
proc = open(`rpicam-vid --denoise cdn_off -n --framerate $fps --width $w --height $h --timeout 0 --codec yuv420 -o -`)
eof(proc)
if cm == cmoff
kill(proc)
end
new(cm, buff, img, proc)
end
end
function Base.close(cam::Camera)
kill(cam.proc)
close(cam.detector)
end
function detect(cam::Camera)
read!(cam.proc, cam.buff)
return cam.img
end