Seite 1 von 1

Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Samstag 10. Februar 2018, 10:08
von kaytec
Hallo,

die Buttons erklären sich selbst und es wird sofort ein Video zusammengefügt. Es langt eine USB-Cam oder auch die eingebaute Kamera im Rechner. Mit der "DEFAULT_CAM_ID" muss rumprobiert werden und mit "-1" wird die erste Cam (eingebaute Kamera) gefunden.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8
try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial

WIDTH = 600
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    
    def __init__(self, cam_id, file_name):
        self.cam = cv2.VideoCapture(cam_id)
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = self.cam.get(self.PROPID_WIDTH)
        self.cam_height = self.cam.get(self.PROPID_HEIGHT)
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return (int(self.cam_width), int(self.cam_height))
                
    def get_image(self, size = None):
        if size:
            size = size
        else:
            size = self.size
        state, self.frame = self.cam.read()
        if state:
            image = Image.frombytes("RGB", self.size ,self.frame,
                "raw", "BGR").resize(size)
            return image
        else:
            return state
       
    def write_frame(self,width, height, fps):
        for x in xrange(fps):
            self.video_writer.write(self.frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.write_buttons = list()
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        write_button_frame = tk.Frame(self,  bg="gray")
        write_button_frame.pack(padx=5, pady=5)
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(write_button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.write_buttons.append(button)
            button.config(command=partial(command, var))
            
    def start_stop(self, fps = None, write = False):
        if fps != None:
            self.fps = fps
        if self.after_id is None:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.write_buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.width, self.height, self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.write_buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        self.tk_image = self.cam.get_image((self.width, self.height))
        if self.tk_image:
            self.canvas.delete("img")
            self.tk_image = ImageTk.PhotoImage(self.tk_image)
            self.canvas.create_image((10,10), anchor=tk.NW, 
                image=self.tk_image, tag="img")
            self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
        else:
            self.canvas.create_text((self.width / 2, self.height / 2),
                text='NO CAM', font='Arial 40')
            self.config(text="NO CAM")
            for button in self.write_buttons:
                button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam(DEFAULT_CAM_ID, DEFAULT_FILE_NAME) as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
Gruß Frank

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Samstag 7. April 2018, 07:11
von kaytec
Hallo,

nach der vielen Hilfe bei dem "Mikroskop mit Tkinter-GUI" habe ich die "Stop-Motion-Cam mit Tkinter-GUI" verbessert. Dir Profis finden bestimmt noch Fehler.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 600
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS= {"NEAREST" : cv2.INTER_NEAREST,
                            "LINEAR" : cv2.INTER_LINEAR,
                            "AREA" : cv2.INTER_AREA,
                            "CUBIC" : cv2.INTER_CUBIC,
                            "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = self.cam.get(self.PROPID_WIDTH)
        self.cam_height = self.cam.get(self.PROPID_HEIGHT)
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return (int(self.cam_width), int(self.cam_height))
                
    def get_image(self, size = None):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, size if size else self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self,width, height, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.write_buttons = list()
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        write_button_frame = tk.Frame(self,  bg="gray")
        write_button_frame.pack(padx=5, pady=5)
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(write_button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.write_buttons.append(button)
            button.config(command=partial(command, var))
            

    def start_stop(self, fps = None, write = False):

        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.write_buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.width, self.height, 
                    fps if fps else self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.write_buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
Gruß Frank

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Dienstag 10. April 2018, 05:20
von kaytec
Hallo,

hat keine Bilder mehr in die Datei geschrieben, da "self.fps" immer mit None überschrieben wurde. Die Bildgröße ändern im laufenden Betrieb ist auch keine gute Idee - sollte beim Starten gleich gemacht werden.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 640
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS = {"NEAREST" : cv2.INTER_NEAREST,
                             "LINEAR" : cv2.INTER_LINEAR,
                             "AREA" : cv2.INTER_AREA,
                             "CUBIC" : cv2.INTER_CUBIC,
                             "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = int(self.cam.get(self.PROPID_WIDTH))
        self.cam_height = int(self.cam.get(self.PROPID_HEIGHT))
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return self.cam_width, self.cam_height
                
    def get_image(self):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.write_buttons = list()
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        write_button_frame = tk.Frame(self,  bg="gray")
        write_button_frame.pack(padx=5, pady=5)
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(write_button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.write_buttons.append(button)
            button.config(command=partial(command, var))
            

    def start_stop(self, fps = None, write = False):
        if fps:
            self.fps = fps
        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.write_buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.write_buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
    
Gruß

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Dienstag 10. April 2018, 07:42
von MagBen
Hast du Beispiele von Stopmotion Animationen, die du damit gemacht hast (z.B. auf YouTube)?

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Dienstag 10. April 2018, 08:07
von kaytec
Hallo MagBen,

ich habe mit Hortkindern schon sehr viele Filme erstellt, doch mache ich solche Angebote nicht mit dem Anspruch ein "Meisterwerk" der Filmgeschichte zu produzieren. Die Kinder sollen eher einen Einblick in die Tricks/Manipulation von Filmen bekommen. Falls ich Zeit habe, dann mache ich mal eins für Youtube.

Gruß Frank

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Dienstag 10. April 2018, 08:14
von Kebap
Hallo Frank,

ich wollte das mal ausprobieren, leider erfolglos:

Code: Alles auswählen

ImportError: No module named cv2

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Dienstag 10. April 2018, 08:22
von kaytec
Hallo Kebap,

braucht du OpenCV --> https://opencv.org/

Gruß

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Samstag 28. April 2018, 06:30
von kaytec
Hallo,
war noch ein kleiner Fehler drin.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 640
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS = {"NEAREST" : cv2.INTER_NEAREST,
                             "LINEAR" : cv2.INTER_LINEAR,
                             "AREA" : cv2.INTER_AREA,
                             "CUBIC" : cv2.INTER_CUBIC,
                             "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = int(self.cam.get(self.PROPID_WIDTH))
        self.cam_height = int(self.cam.get(self.PROPID_HEIGHT))
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return self.cam_width, self.cam_height
                
    def get_image(self):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        button_frame = tk.Frame(self,  bg="gray")
        button_frame.pack(padx=5, pady=5)
        self.buttons = list()
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.buttons.append(button)
            button.config(command=partial(command, var))

    def start_stop(self, fps = None, write = False):
        if fps:
            self.fps = fps
        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
Gruß

Re: Stop-Motion-Cam mit Tkinter-Gui

Verfasst: Sonntag 9. Dezember 2018, 09:10
von kaytec
Hallo,

hat sich bei OpenCV was geändert.

Code: Alles auswählen

/usr/bin/env python
# -*- coding: utf-8

import Tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 640
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS = {"NEAREST" : cv2.INTER_NEAREST,
                             "LINEAR" : cv2.INTER_LINEAR,
                             "AREA" : cv2.INTER_AREA,
                             "CUBIC" : cv2.INTER_CUBIC,
                             "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = int(self.cam.get(self.PROPID_WIDTH))
        self.cam_height = int(self.cam.get(self.PROPID_HEIGHT))
        self.video_writer = cv2.VideoWriter(file_name, cv2.VideoWriter_fourcc(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return self.cam_width, self.cam_height
                
    def get_image(self):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        button_frame = tk.Frame(self,  bg="gray")
        button_frame.pack(padx=5, pady=5)
        self.buttons = list()
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.buttons.append(button)
            button.config(command=partial(command, var))

    def start_stop(self, fps = None, write = False):
        if fps:
            self.fps = fps
        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()


Gruß Frank