Contents

Hur man bygger en kameraapplikation med Python

Oavsett om du vill arbeta med ett engagerande Python-projekt eller utforska olika aspekter av Python-programmering kan du bygga en kameraapplikation för detta ändamål. Det handlar om att kombinera olika aspekter av Python-programmering, t.ex. utveckling av grafiska användargränssnitt (GUI), bild- och videobearbetning samt multi-threading.

Att ta sig an verkliga problem som det här bidrar dessutom till att förbättra ens kritiska tänkande och problemlösningsförmåga. Sådana förmågor har stor betydelse i ett brett spektrum av programvaruutvecklingsprojekt.

Konfigurera din miljö

Börja med att skapa en ny virtuell miljö som separerar ditt projekt från potentiella avvikelser som uppstår på grund av motstridiga paketversioner. Utför sedan följande kommando i din terminal:

 pip install opencv-python pillow 

Det här kommandot underlättar installationen av både OpenCV-biblioteket, som tillhandahåller en omfattande uppsättning verktyg för att utföra olika datorseendeuppgifter, samt Python Imaging Library (PIL), en viktig modul som gör det möjligt för användare att utföra omfattande bildbehandlingsoperationer. Följaktligen kan du använda OpenCV för dess robusta utbud av datorseendefunktioner medan du använder PIL för den intrikata manipuleringen av bilder i din virtuella miljö.

Den fullständiga källkoden för detta projekt kan nås via ett GitHub-arkiv, som fungerar som ett digitalt lagringsutrymme för utvecklare att dela och samarbeta om sitt arbete.

Importera de nödvändiga biblioteken

Efter installation av dessa bibliotek kan de importeras tillsammans med ytterligare moduler från Pythons grundbibliotek, i enlighet med de specifika kraven för en viss applikation eller uppgift.

 import tkinter as tk
import cv2
from PIL import Image, ImageTk
import os
import threading
import time

Med hjälp av Tkinter-biblioteket ska jag utveckla ett visuellt tilltalande grafiskt användargränssnitt (GUI) som förbättrar den övergripande användarupplevelsen av min applikation. Genom att utnyttja modulerna os, threading och time kommer jag dessutom att tillhandahålla viktiga funktioner för att förbättra systemets prestanda. Genom att implementera concurrency genom att segregera vissa delar av koden i separata trådar, strävar jag efter att optimera exekveringseffektiviteten och effektivisera verksamheten.

Skapa en gallerikatalog och definiera globala variabler och flaggor

Processen innebär att man skapar en särskild mapp för lagring av både fotografier och videofilmer, vilket säkerställer att det nödvändiga lagringsutrymmet finns tillgängligt innan man fångar eller spelar in något visuellt innehåll.

 if not os.path.exists("gallery"):
    os.makedirs("gallery") 

För att skapa variabler för lagring av miniatyrbilder av bilder och videor i ett fotoalbum måste vi först skapa två nya datastrukturer som heter “image\_thumbnails” och “video\_thumbnails”.

 # Initialize image_thumbnails as a global list
image_thumbnails = []
video_thumbnails = [] # New list for video thumbnails
update_camera = True 

Flaggan “update\_camera” används för att reglera uppdateringsfrekvensen för kameraflödet.

Fånga bilder från kameraflödet

pythondef process_frame(camera):# Fånga en bild från kameraflödetframe = cv2.imread(‘input_video.mp4’)# Spara bilden i katalogen ‘gallery’ med ett unikt filnamn baserat på dess indexnummeri = 0while True:filename = f"{i}.jpg"if not os.path.exists(“gallery”):os.makedirs(“gallery”)retval = cv2.imwrite(filename, frame)i \+= 1# Visa den sparade bilden med show_image cv2.imshow(cv2.namedWindow(“Gallery”, cv2.WINDOW

 def capture_image():
    ret, frame = cap.read()

    if ret:
        # Generate a unique filename with a timestamp
        timestamp = time.strftime("%Y%m%d%H%M%S")
        image_path = os.path.join("gallery", f"captured_image_{timestamp}.jpg")
        cv2.imwrite(image_path, frame)
        show_image(image_path) 

Starta och stoppa videoinspelning

För att kunna visa en video är det nödvändigt att fastställa en metod för att generera den. Därför skall vi utveckla en funktion som startar videoinspelningen när användaren ger instruktioner om att spela in en video. Dessutom kommer denna funktion att avaktivera knappen “Record” (för att förhindra samtidiga inspelningar), samtidigt som knappen “Stop Recording” aktiveras. Denna åtgärd innebär att inspelningen har påbörjats.

 def start_recording():
    global video_writer, recording_start_time, recording_stopped, update_camera

    if not video_writer:
        timestamp = time.strftime("%Y%m%d%H%M%S")
        video_path = os.path.join("gallery", f"recorded_video_{timestamp}.mp4")

        # Use mp4v codec (or try other codecs)
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')

        # Adjust frame rate and resolution if needed
        video_writer = cv2.VideoWriter(video_path, fourcc, 20.0,
                                       (640, 480))

        recording_start_time = time.time()
        recording_stopped = False
        record_button.config(state=tk.DISABLED)
        stop_button.config(state=tk.NORMAL)

        # Start a separate thread for recording and time-lapse display
        recording_thread = threading.Thread(target=record_and_display)
        recording_thread.start() 

Utveckla därefter en funktion som avslutar videoinspelningsprocessen och frigör videokodaren.

 def stop_recording():
    global video_writer, recording_stopped

    if video_writer:
        video_writer.release()
        recording_stopped = True
         record_button.config(state=tk.NORMAL)
        stop_button.config(state=tk.DISABLED)

Den ovan nämnda funktionen utför en ytterligare operation för att uppdatera användargränssnittet, vilket innebär att aktivera knappen “Spela in” samtidigt som knappen “Stoppa inspelning” inaktiveras. Sådana åtgärder innebär att inspelningsprocessen har upphört.

Inspelning och visning av video

Utveckla en funktion som sömlöst hämtar bildrutor från videokällan, utför nödvändiga bearbetningsuppgifter och presenterar dem i det grafiska användargränssnittet tills kommandot “Stoppa inspelning” aktiveras. Utförandet av denna process skall avbrytas när ovannämnda åtgärd vidtas.

 def record_and_display():
    global recording_stopped, update_camera

    while video_writer and not recording_stopped:
        ret, frame = cap.read()

        if ret:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

            # Calculate elapsed time and add it to the frame
            elapsed_time = time.time() - recording_start_time
            timestamp = f"Time Elapsed: {int(elapsed_time)}s"

            cv2.putText(frame, timestamp, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
                         0.5, (255, 255, 255), 2)

            img = Image.fromarray(frame)
            photo = ImageTk.PhotoImage(image=img)
            camera_feed.config(image=photo)
            camera_feed.image = photo

            video_writer.write(frame)
            time.sleep(0.05)

    camera_feed.after(10, update_camera_feed)

Funktionen omfattar även beräkning och visning av den tid, i minuter och sekunder, som har förflutit sedan inspelningen påbörjades, inom varje enskild videobild.

Visning av tagna bilder och videor

För att visa det visuella innehåll som har tagits fram genom bild- och videoinspelningsprocesser krävs en lämplig presentationsmetod.

För att kunna visa visuellt innehåll i användargränssnittet är det nödvändigt att utveckla en funktion som hämtar en bildfil från dess lagringsplats, konverterar den till ett format som är kompatibelt med det grafiska användargränssnittet i Python Tkinter-biblioteket och uppdaterar den visade vybilden med de nyligen förvärvade visuella data. Denna process innebär att Python Imaging Library (PIL) används för åtkomst och bearbetning av den lagrade bilden, följt av användning av lämpliga metoder i Tkinter GUI-ramverket för att införliva den transformerade bilden inom det angivna området på kamerans förhandsgranskningsskärm.

 def show_image(image_path):
    image = Image.open(image_path)
    photo = ImageTk.PhotoImage(image=image)
    camera_feed.config(image=photo)
    camera_feed.image = photo

För att visa de inspelade videorna bör man implementera en funktion som aktiverar ett videouppspelningsgränssnitt så att tittaren kan observera inspelade bilder. Dessutom avbryter denna process alla ytterligare uppdateringar av kameraströmmen under videouppspelningen.

 def play_video(video_path):
    def close_video_player():
        video_player.destroy()
        global update_camera
        update_camera = True

     global update_camera
    update_camera = False

     video_player = tk.Toplevel(root)
    video_player.title("Video Player")

    video_cap = cv2.VideoCapture(video_path)

    def update_video_frame():
        ret, frame = video_cap.read()

        if ret:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = Image.fromarray(frame)
            photo = ImageTk.PhotoImage(image=img)
            video_label.config(image=photo)
            video_label.image = photo

            # Get the actual frame rate of the video
            frame_rate = video_cap.get(cv2.CAP_PROP_FPS)
            delay = int(1000 / frame_rate)

            video_player.after(delay, update_video_frame)
         else:
            video_player.destroy()

    video_label = tk.Label(video_player)
    video_label.pack()

    update_video_frame()

    video_player.protocol("WM_DELETE_WINDOW", close_video_player)

Att stoppa spridningen av uppdateringar av videoströmmen bidrar till en sömlös visuell uppfattning.

Skapa miniatyrbilder av video och öppna galleriet

Införliva följande uttalande på ett vältaligt sätt:Implementeringen av en funktion för att skapa miniatyrbilder anses vara nödvändig, eftersom den gör det möjligt för användare att snabbt urskilja och välja önskat videoinnehåll genom en visuellt kortfattad representation av detsamma.

 def create_video_thumbnail(video_path):
    video_cap = cv2.VideoCapture(video_path)
    ret, frame = video_cap.read()

    if ret:
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        thumbnail = Image.fromarray(frame).resize((100, 100))
        thumbnail_photo = ImageTk.PhotoImage(image=thumbnail)
        return thumbnail_photo, os.path.basename(video_path)

     return None, None 

Skapa en ny JavaScript-funktion som heter “playVideo” som aktiveras när man klickar på en videominiatyr i gallerifönstret. Denna funktion ska initiera uppspelning av den valda videon och visa den i videospelarens container.

 def play_video_from_thumbnail(video_path):
    play_video(video_path) 

Visst, här är ett exempel på hur du kan implementera den här funktionen i Python med OpenCV-biblioteket:pythonimport cv2import numpy as npfrom tkinter import Tk, Frame, Button, Label, Text, Scrollbar, VERTICAL)def save_captured_frames(window):# Definiera inspelningsparametrar (kan ändras för att justera upplösning, bildhastighet, etc. )cap = cv2.VideoCapture(0)fourcc = cv2.VideoWriter_fourcc(*“mp4v”)fps = int(cap.get(cv2.CAP_PROP_FPS))width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))

 def open_gallery():
    global update_camera
    update_camera = False

     gallery_window = tk.Toplevel(root)
    gallery_window.title("Gallery")

    def back_to_camera():
        gallery_window.destroy()
        global update_camera

        # Resume updating the camera feed
        update_camera = True

    back_button = tk.Button(gallery_window, text="Back to Camera",
                             command=back_to_camera)

    back_button.pack()

    gallery_dir = "gallery"
    image_files = [f for f in os.listdir(gallery_dir) if f.endswith(".jpg")]
    video_files = [f for f in os.listdir(gallery_dir) if f.endswith(".mp4")]

    # Clear the existing image_thumbnails and video_thumbnails lists
    del image_thumbnails[:]
    del video_thumbnails[:]

    for image_file in image_files:
        image_path = os.path.join(gallery_dir, image_file)
        thumbnail = Image.open(image_path).resize((100, 100))
        thumbnail_photo = ImageTk.PhotoImage(image=thumbnail)
        image_name = os.path.basename(image_file)

        def show_image_in_gallery(img_path, img_name):
            image_window = tk.Toplevel(gallery_window)
            image_window.title("Image")
            img = Image.open(img_path)
            img_photo = ImageTk.PhotoImage(img)
            img_label = tk.Label(image_window, image=img_photo)
            img_label.image = img_photo
            img_label.pack()
            img_label_name = tk.Label(image_window, text=img_name)
            img_label_name.pack()

        thumbnail_label = tk.Label(gallery_window, image=thumbnail_photo)
        thumbnail_label.image = thumbnail_photo

        thumbnail_label.bind("<Button-1>", lambda event,
                                                  img_path=image_path,
                                                  img_name=image_name:
         show_image_in_gallery(img_path, img_name))

        thumbnail_label.pack()
        image_thumbnails.append(thumbnail_photo)

         # Display the image filename below the thumbnail
        image_name_label = tk.Label(gallery_window, text=image_name)
        image_name_label.pack()

    for video_file in video_files:
        video_path = os.path.join(gallery_dir, video_file)

        # Create a video thumbnail and get the filename
        thumbnail_photo, video_name = create_video_thumbnail(video_path)

        if thumbnail_photo:
            video_thumbnail_button = tk.Button(
                gallery_window,
                image=thumbnail_photo,
                command=lambda path=video_path: play_video_from_thumbnail(path)
            )

            video_thumbnail_button.pack()

            # Store the video thumbnail PhotoImage objects
            video_thumbnails.append(thumbnail_photo)

             # Display the video filename below the thumbnail
            video_name_label = tk.Label(gallery_window, text=video_name)
            video_name_label.pack()

Generationen av miniatyrbilder utökas till att omfatta både stillbilder och rörliga bilder, vilket gör det möjligt för användare att komma åt motsvarande originalinnehåll genom att klicka på dessa visuella sammanfattningar och därefter läsa den fullskaliga avbildningen eller visa den filmiska produktionen.

Skapa det huvudsakliga användargränssnittet för din applikation

Inled processen med att konstruera det primära tkinter-gränssnittet och ge det en utmärkande benämning.

 root = tk.Tk()
root.title("Camera Application")

Initialisera sedan de nödvändiga variablerna.

 video_writer = None
recording_start_time = 0 # Initialize recording start time
recording_stopped = False # Initialize recording_stopped flag

Skapa sedan knappar för olika åtgärder.

 capture_button = tk.Button(root, text="Capture", command=capture_image)
record_button = tk.Button(root, text="Record", command=start_recording)
stop_button = tk.Button(root, text="Stop Recording", command=stop_recording)
gallery_button = tk.Button(root, text="Gallery", command=open_gallery)
quit_button = tk.Button(root, text="Quit", command=root.quit)

Att använda en Grid Layout Manager är en effektiv strategi för att arrangera knappar i det primära fönstret i en applikation, vilket ger en visuellt tilltalande och organiserad presentation samtidigt som det är lätt att komma åt och interagera med varje enskild knapp.

 capture_button.grid(row=0, column=0, padx=10, pady=10)
record_button.grid(row=0, column=1, padx=10, pady=10)
stop_button.grid(row=0, column=2, padx=10, pady=10)
gallery_button.grid(row=0, column=3, padx=10, pady=10)
quit_button.grid(row=0, column=4, padx=10, pady=10)

Införliva funktionen att visa kameraflödet i ett interaktivt grafiskt användargränssnitt genom att upprätta nödvändiga anslutningar med enhetens hårdvarukomponenter, konfigurera lämpliga inställningar för optimal visualisering och initiera motsvarande modul eller bibliotek för att återge videoströmmen från kameran på det angivna området på skärmen vid programstart eller när användaren anger något.

 camera_feed = tk.Label(root)
camera_feed.grid(row=1, column=0, columnspan=5)
cap = cv2.VideoCapture(0)

Visst! Här är ett exempel på hur du kan implementera den här funktionen med OpenCV och Python:pythonimport cv2from tkinter import *import threadingimport timedef update_camera_feed():# Initiera videoinspelningen devicecap = cv2.VideoCapture(0)while True:# Läs bilden från videoströmmenret, frame = cap.read()if not ret:break# Visa bilden på GUIlabel.config(image=frame)# Vänta på en tangenttryckning för att avsluta looproot.update()event = root.wait_event()if event == ‘q’:

 def update_camera_feed():
    if update_camera:
        if not video_writer:
            ret, frame = cap.read()

            if ret:
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                img = Image.fromarray(frame)
                photo = ImageTk.PhotoImage(image=img)
                camera_feed.config(image=photo)
                camera_feed.image = photo

    root.after(10, update_camera_feed)

update_camera_feed()

Slutligen, starta maintkinterevent-loopen.

 root.mainloop()

Den nuvarande loopen spelar en avgörande roll för att hantera användarnas engagemang och underlätta deras interaktion med systemet.

Testa appens funktioner

Presentationsinnehållet visar en rad olika funktioner som finns i applikationen, vilket belyser dess kapacitet och mångsidighet i drift.

Din webbläsare stöder inte videotaggen.

Förbättra dina Python-kunskaper med OpenCV

OpenCV är allmänt erkänt som ett framstående verktyg för datorseendeapplikationer, på grund av dess kompatibilitet med ett omfattande utbud av bibliotek som underlättar utvecklingen av olika innovativa projekt. Dessutom har användarna möjlighet att utnyttja dess kapacitet genom Python, som fungerar som en utmärkt plattform för att finslipa sina programmeringsförmågor.