fix playback timing, apply cam settings, rest wb/exp key binding
This commit is contained in:
parent
5aec1e0dac
commit
c4e9c00b67
157
frame_opencv.py
157
frame_opencv.py
|
@ -9,14 +9,10 @@ import signal
|
|||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
from timeit import default_timer as timer
|
||||
import tomllib
|
||||
import numpy as np
|
||||
|
||||
# TODO : find camera module version from image size
|
||||
# https://www.raspberrypi.com/documentation/accessories/camera.html#hardware-specification
|
||||
# v4l2-ctl --list-framesizes=YU12
|
||||
# 2592 x 1944 == v1
|
||||
# 3280 × 2464 == v2
|
||||
import serialutils
|
||||
|
||||
running_from_folder = os.path.realpath(__file__)
|
||||
alphabet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
|
||||
|
@ -65,6 +61,15 @@ for location in config_locations:
|
|||
config_found_msg = _("Found configuration file in {}").format(os.path.expanduser(location))
|
||||
print(config_found_msg)
|
||||
|
||||
def reset_wb_exp():
|
||||
# Flip auto-exposure, white-balance on to adapt to light environment
|
||||
serialutils.send_serial_cmd(serialutils.find_cam_port(), 'v4l2-ctl -d /dev/video0 -c auto_exposure=0 -c white_balance_auto_preset=1')
|
||||
# Give some time to the captor to adapt
|
||||
time.sleep(1)
|
||||
# Flip back, wb 3 = fluorescent
|
||||
serialutils.send_serial_cmd(serialutils.find_cam_port(), 'v4l2-ctl -d /dev/video0 -c auto_exposure=1 -c white_balance_auto_preset=2')
|
||||
|
||||
|
||||
def generate_text_image(text:str, screen_w, screen_h, bullets=False):
|
||||
text_image = Image.new('RGB',
|
||||
(screen_w, screen_h),
|
||||
|
@ -352,26 +357,26 @@ def remove_frame(img_list, img_index):
|
|||
else:
|
||||
return img_list, 0, blank_image
|
||||
|
||||
def playback_animation(img_list, img_index):
|
||||
# save onionskin state
|
||||
if onionskin:
|
||||
onionskin = False
|
||||
onionskin_was_on = True
|
||||
# ~ def playback_animation(img_list, img_index):
|
||||
# ~ # save onionskin state
|
||||
# ~ if onionskin:
|
||||
# ~ onionskin = False
|
||||
# ~ onionskin_was_on = True
|
||||
|
||||
for file in img_list:
|
||||
img = update_image(img_list, img_list.index(file))
|
||||
print(str(img_list.index(file)) + " : " + file )
|
||||
cv2.imshow("StopiCV", img)
|
||||
time.sleep(.5)
|
||||
# Restore previous frame
|
||||
print(img_index)
|
||||
frame_before_playback = update_image(img_list, img_index)
|
||||
# ~ for file in img_list:
|
||||
# ~ img = update_image(img_list, img_list.index(file))
|
||||
# ~ print(str(img_list.index(file)) + " : " + file )
|
||||
# ~ cv2.imshow("StopiCV", img)
|
||||
# Restore onionskin
|
||||
if 'onionskin_was_on' in locals():
|
||||
onionskin = True
|
||||
# Restore index
|
||||
return img_index, frame_before_playback
|
||||
# ~ time.sleep(.5)
|
||||
# ~ # Restore previous frame
|
||||
# ~ print(img_index)
|
||||
# ~ frame_before_playback = update_image(img_list, img_index)
|
||||
# ~ cv2.imshow("StopiCV", img)
|
||||
# ~ # Restore onionskin
|
||||
# ~ if 'onionskin_was_on' in locals():
|
||||
# ~ onionskin = True
|
||||
# ~ # Restore index
|
||||
# ~ return img_index, frame_before_playback
|
||||
|
||||
def testDevice(source):
|
||||
cap = cv2.VideoCapture(source)
|
||||
|
@ -424,7 +429,83 @@ def main(args):
|
|||
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 900)
|
||||
|
||||
frame = get_onionskin_frame(savepath, index)
|
||||
|
||||
# TODO : (re)set camera settings on startup
|
||||
# Using serial to send v4l2-ctl cmd to the camera
|
||||
# Use v4l-ctl to flip frame
|
||||
# v4l2-ctl -d /dev/video0 -c vertical_flip=1 -c control=value
|
||||
# DEPRECATED : Using config file and loading with camera-ctl
|
||||
# Write config file to /tmp/blah
|
||||
# ~ write_config_file = '''rm /tmp/blah && echo "power_line_frequency=2
|
||||
# ~ sharpness=50
|
||||
# ~ video_bitrate=25000000
|
||||
# ~ auto_exposure=1
|
||||
# ~ auto_exposure_bias=2
|
||||
# ~ white_balance_auto_preset=3
|
||||
# ~ exposure_metering_mode=1
|
||||
# ~ " > /tmp/blah'''
|
||||
# Apply config
|
||||
# ~ apply_config = '/opt/camera-control/camera-ctl -c /tmp/blah -v /dev/video0 -i repeat_sequence_header -i h264_i_frame_period -i h264_level -i h264_profile -i compression_quality\rl\rq\r'
|
||||
# ~ serialutils.send_serial_cmd(serialutils.find_cam_port(), write_config_file)
|
||||
# ~ serialutils.send_serial_cmd(serialutils.find_cam_port(), apply_config)
|
||||
|
||||
# ~ User Controls
|
||||
|
||||
# ~ brightness 0x00980900 (int) : min=0 max=100 step=1 default=50 value=50 flags=slider
|
||||
# ~ contrast 0x00980901 (int) : min=-100 max=100 step=1 default=0 value=-2 flags=slider
|
||||
# ~ saturation 0x00980902 (int) : min=-100 max=100 step=1 default=0 value=5 flags=slider
|
||||
# ~ red_balance 0x0098090e (int) : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
|
||||
# ~ blue_balance 0x0098090f (int) : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
|
||||
# ~ horizontal_flip 0x00980914 (bool) : default=0 value=0
|
||||
# ~ vertical_flip 0x00980915 (bool) : default=0 value=0
|
||||
# ~ power_line_frequency 0x00980918 (menu) : min=0 max=3 default=1 value=1
|
||||
# ~ sharpness 0x0098091b (int) : min=-100 max=100 step=1 default=0 value=10 flags=slider
|
||||
# ~ color_effects 0x0098091f (menu) : min=0 max=15 default=0 value=0
|
||||
# ~ rotate 0x00980922 (int) : min=0 max=360 step=90 default=0 value=0 flags=modify-layout
|
||||
# ~ color_effects_cbcr 0x0098092a (int) : min=0 max=65535 step=1 default=32896 value=32896
|
||||
|
||||
# ~ Codec Controls
|
||||
|
||||
# ~ video_bitrate_mode 0x009909ce (menu) : min=0 max=1 default=0 value=0 flags=update
|
||||
# ~ video_bitrate 0x009909cf (int) : min=25000 max=25000000 step=25000 default=10000000 value=25000000
|
||||
# ~ repeat_sequence_header 0x009909e2 (bool) : default=0 value=0
|
||||
# ~ h264_i_frame_period 0x00990a66 (int) : min=0 max=2147483647 step=1 default=60 value=60
|
||||
# ~ h264_level 0x00990a67 (menu) : min=0 max=11 default=11 value=11
|
||||
# ~ h264_profile 0x00990a6b (menu) : min=0 max=4 default=4 value=4
|
||||
|
||||
# ~ Camera Controls
|
||||
|
||||
# ~ auto_exposure 0x009a0901 (menu) : min=0 max=3 default=0 value=0
|
||||
# ~ exposure_time_absolute 0x009a0902 (int) : min=1 max=10000 step=1 default=1000 value=1000
|
||||
# ~ exposure_dynamic_framerate 0x009a0903 (bool) : default=0 value=0
|
||||
# ~ auto_exposure_bias 0x009a0913 (intmenu): min=0 max=24 default=12 value=2
|
||||
# ~ white_balance_auto_preset 0x009a0914 (menu) : min=0 max=9 default=1 value=1
|
||||
# ~ image_stabilization 0x009a0916 (bool) : default=0 value=0
|
||||
# ~ iso_sensitivity 0x009a0917 (intmenu): min=0 max=4 default=0 value=0
|
||||
# ~ iso_sensitivity_auto 0x009a0918 (menu) : min=0 max=1 default=1 value=1
|
||||
# ~ exposure_metering_mode 0x009a0919 (menu) : min=0 max=3 default=0 value=0
|
||||
# ~ scene_mode 0x009a091a (menu) : min=0 max=13 default=0 value=0
|
||||
|
||||
# ~ JPEG Compression Controls
|
||||
# ~ compression_quality 0x009d0903 (int) : min=1 max=100 step=1 default=30 value=30
|
||||
|
||||
# Make sure we're using max bitrate
|
||||
serialutils.send_serial_cmd(serialutils.find_cam_port(), 'v4l2-ctl -d /dev/video0 -c video_bitrate=25000000')
|
||||
# Flip auto-exposure, white-balance on and off to adapt to light environment
|
||||
reset_wb_exp()
|
||||
# Flip preview (0 = vert; 1 = hor)
|
||||
if project_settings['vflip']:
|
||||
serialutils.send_serial_cmd(serialutils.find_cam_port(), 'v4l2-ctl -d /dev/video0 -c vertical_flip=1')
|
||||
else:
|
||||
serialutils.send_serial_cmd(serialutils.find_cam_port(), 'v4l2-ctl -d /dev/video0 -c vertical_flip=0')
|
||||
if project_settings['hflip']:
|
||||
serialutils.send_serial_cmd(serialutils.find_cam_port(), 'v4l2-ctl -d /dev/video0 -c horizontal_flip=1')
|
||||
else:
|
||||
serialutils.send_serial_cmd(serialutils.find_cam_port(), 'v4l2-ctl -d /dev/video0 -c horizontal_flip=0')
|
||||
time.sleep(.5)
|
||||
loop_delta = 0
|
||||
while True:
|
||||
start = timer()
|
||||
if playback:
|
||||
if onionskin:
|
||||
onionskin = False
|
||||
|
@ -433,7 +514,11 @@ def main(args):
|
|||
if playhead < len(img_list)-1:
|
||||
playhead, img = next_frame(playhead, loop_playback)
|
||||
cv2.imshow("StopiCV", img)
|
||||
time.sleep(1.0/project_settings['framerate'])
|
||||
# Calculate framerate according to loop execution time
|
||||
frame_interval = 1.0/project_settings['framerate']-loop_delta
|
||||
if frame_interval < 0:
|
||||
frame_interval = 0
|
||||
time.sleep(frame_interval)
|
||||
else:
|
||||
playhead = index
|
||||
img = update_image(img_list, index)
|
||||
|
@ -445,24 +530,14 @@ def main(args):
|
|||
|
||||
if onionskin:
|
||||
ret, overlay = cam.read()
|
||||
og_frame = overlay
|
||||
og_frame = overlay.copy()
|
||||
# Resize preview
|
||||
overlay = cv2.resize(overlay, (project_settings['screen_w'], project_settings['screen_h']))
|
||||
# Apply onionskin
|
||||
alpha = project_settings['onionskin_alpha_default']
|
||||
beta = (1.0 - alpha)
|
||||
overlay = cv2.addWeighted(frame, alpha, overlay, beta, 0)
|
||||
# TODO : use v4l-ctl to flip frame
|
||||
# v4l2-ctl -d /dev/video0 -c vertical_flip=1
|
||||
# Flip preview (0 = vert; 1 = hor)
|
||||
if project_settings['vflip'] or project_settings['hflip']:
|
||||
if project_settings['vflip'] and project_settings['hflip']:
|
||||
flip_dir = -1
|
||||
elif project_settings['vflip']:
|
||||
flip_dir = 0
|
||||
elif project_settings['hflip']:
|
||||
flip_dir = 1
|
||||
overlay = cv2.flip(overlay, flip_dir)
|
||||
|
||||
if not ret:
|
||||
print(_("Failed to grab frame."))
|
||||
break
|
||||
|
@ -502,6 +577,9 @@ def main(args):
|
|||
if playback:
|
||||
playback = False
|
||||
index, frame = next_frame(index)
|
||||
# Key r / keypad 9 - reset wb,exp
|
||||
elif (k%256 == 114) or (k%256 == 57):
|
||||
reset_wb_exp()
|
||||
# Key e / keypad *
|
||||
elif (k%256 == 101) or (k%256 == 42):
|
||||
print(_("Export"))
|
||||
|
@ -509,7 +587,6 @@ def main(args):
|
|||
# Key Return
|
||||
elif (k%256 == 13):
|
||||
print(_("Playback"))
|
||||
print(img_list)
|
||||
playhead = index
|
||||
loop_playback = True
|
||||
playback = not playback
|
||||
|
@ -546,6 +623,10 @@ def main(args):
|
|||
continue
|
||||
else:
|
||||
print(k) # else print its value
|
||||
end = timer()
|
||||
loop_delta = end - start
|
||||
print(loop_playback)
|
||||
|
||||
if 'ffmpeg_process' in locals():
|
||||
if ffmpeg_process.poll() is None:
|
||||
print(_("Ffmpeg is still running.\n Waiting for task to complete."))
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import serial
|
||||
import serial.tools.list_ports
|
||||
|
||||
def find_cam_port():
|
||||
serial_devices = serial.tools.list_ports.comports()
|
||||
for dev in serial_devices:
|
||||
if str(dev).find('Piwebcam') != -1:
|
||||
return str(dev).split(' ')[0]
|
||||
return None
|
||||
|
||||
def send_serial_cmd(cam_port, cmd:str, clear=True):
|
||||
con = serial.Serial(cam_port, baudrate=115200)
|
||||
if clear:
|
||||
append = b'\rclear\r'
|
||||
else:
|
||||
append = b'\r'
|
||||
con.write(str.encode(cmd) + append)
|
||||
con.close()
|
Loading…
Reference in New Issue