diff --git a/frame_opencv.py b/frame_opencv.py index bb739fd..16ef639 100644 --- a/frame_opencv.py +++ b/frame_opencv.py @@ -10,11 +10,13 @@ import sys import subprocess import time import tomllib -# TODO : remove tkinter dep -# ~ import tkinter as tk -# ~ from tkinter import messagebox 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 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'] @@ -265,6 +267,16 @@ def previous_frame(img_index): return img_index, update_image(img_list, img_index) +def last_frame(img_index): + img_index = len(img_list)-1 + return img_index, update_image(img_list, img_index) + + +def first_frame(img_index): + img_index = 0 + return img_index, update_image(img_list, img_index) + + def clean_img_list(folder_path): # Check file in dict exists, else remove it file_list = os.listdir(folder_path) @@ -322,7 +334,7 @@ def remove_frame(img_list, img_index): # ~ frame_path = os.path.realpath(frame_name) frame_path = os.path.join(folder_path, frame_name) if not os.path.exists(frame_path): - return img_index, blank_image + return img_list, img_index, blank_image print(_("Removing {}").format(frame_path)) # trash file send2trash(frame_path) @@ -336,24 +348,16 @@ def remove_frame(img_list, img_index): # update index if possible img_index = check_range(img_index, False) # update display - return img_index, update_image(img_list, img_index) + return img_list, img_index, update_image(img_list, img_index) else: - return 0, blank_image + return img_list, 0, blank_image def playback_animation(img_list, img_index): # save onionskin state if onionskin: onionskin = False onionskin_was_on = True - - # ~ index = 0 - # Play all frames - # ~ while index < len(img_list): - # ~ print(img_list[index]) - # ~ img = update_image(img_list, index) - # ~ cv2.imshow("StopiCV", img) - # ~ time.sleep(.5) - # ~ index += 1 + for file in img_list: img = update_image(img_list, img_list.index(file)) print(str(img_list.index(file)) + " : " + file ) @@ -410,19 +414,14 @@ def export_animation(input_filename, export_filename): def main(args): - global onionskin, playback, loop_playback, playhead, index + global onionskin, playback, loop_playback, playhead, index, img_list if not testDevice(0): print(_("No camera device found. Exiting...")) return 1 cam = cv2.VideoCapture(0) - cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) - cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) - - # ~ cv2.namedWindow("StopiCV", cv2.WINDOW_GUI_NORMAL) - # ~ cv2.setWindowProperty("StopiCV", cv2.WND_PROP_OPENGL, cv2.WINDOW_OPENGL) - # ~ cv2.setWindowProperty("StopiCV", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) - # ~ cv2.setWindowProperty("StopiCV", cv2.WND_PROP_ASPECT_RATIO, cv2.WINDOW_KEEPRATIO) + cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1600) + cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 900) frame = get_onionskin_frame(savepath, index) while True: @@ -450,7 +449,11 @@ def main(args): # Resize preview overlay = cv2.resize(overlay, (project_settings['screen_w'], project_settings['screen_h'])) # Apply onionskin - overlay = cv2.addWeighted(frame, 1.0, overlay, project_settings['onionskin_alpha_default'], 0) + 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']: @@ -473,6 +476,19 @@ def main(args): if (k%256 == 111) or (k%256 == 47): # Toggle onionskin onionskin = not onionskin + # Key up + elif (k%256 == 82) or (k%256 == 56): + if len(img_list): + if playback: + playback = False + index, frame = last_frame(index) + # Key down + elif (k%256 == 84) or (k%256 == 50): + if len(img_list): + if playback: + playback = False + index, frame = first_frame(index) + print(index) # Key left elif (k%256 == 81) or (k%256 == 52): # Displau previous frame @@ -488,19 +504,20 @@ def main(args): index, frame = next_frame(index) # Key e / keypad * elif (k%256 == 101) or (k%256 == 42): - print("Export") + print(_("Export")) ffmpeg_process = export_animation(input_filename, export_filename) # Key Return elif (k%256 == 13): - print("Playback") + print(_("Playback")) + print(img_list) playhead = index loop_playback = True playback = not playback # Key remove frame - backspace, del, numpad_minus elif (k%256 == 8) or (k%256 == 45) or (k == 255): # Remove frame - print("Remove frame") - index, frame = remove_frame(img_list, index) + print(_("Remove frame")) + img_list, index, frame = remove_frame(img_list, index) # Quit app elif k%256 == 27: # ESC pressed @@ -519,7 +536,7 @@ def main(args): img_path = os.path.join(savepath, img_name) cv2.imwrite(img_path, og_frame) print(_("File {} written.").format(img_path)) - if len(img_list) and (img_list[index] == 'A.-001.png'): + if len(img_list) and (img_list[index] == '{letter}.-001.{ext}'.format(letter=project_letter, ext=project_settings['file_extension'])): img_list[index] = img_name else: index += 1 diff --git a/requirements.txt b/requirements.txt index 71e4ffe..0631529 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ Send2Trash opencv-python numpy -tkinter +pyserial +pillow