Seuraa tätä kattavaa projektia saadaksesi lisätietoja Pythonista ja kuvankäsittelystä.

Halusitpa sitten työskennellä kiinnostavan Python-projektin parissa tai tutustua Python-ohjelmoinnin eri puoliin, kamerasovelluksen rakentaminen palvelee tätä tarkoitusta. Se sisältää Python-ohjelmoinnin eri näkökohtien yhdistämisen, kuten graafisen käyttöliittymän (GUI) kehittämisen, kuvan- ja videonkäsittelyn sekä monisäikeisyyden.

Tämän kaltaisten käytännön haasteiden ratkaiseminen auttaa myös terävöittämään ongelmanratkaisutaitojasi. Nämä taidot ovat arvokkaita kaikissa ohjelmointiyrityksissä.

Ympäristösi luominen

Aloita uuden virtuaaliympäristön luominen. Tämä eristää projektisi ja varmistaa, että asentamiesi pakettien eri versioiden välillä ei ole ristiriitoja. Suorita sitten tämä terminaalikomento:

pip install opencv-python pillow

Tämä komento asentaa OpenCV kirjasto ja PIL (Python Imaging Library) virtuaaliympäristössäsi. Käytät OpenCV: tä tietokonenäkötoimintoihin ja PIL: ää kuvankäsittelyyn.

Tämän projektin koko lähdekoodi on saatavilla a GitHub-arkisto.

Vaadittujen kirjastojen tuonti

Kun olet asentanut nämä kirjastot, voit tuoda ne muiden tarvittavien moduulien kanssa Pythonin vakiokirjastosta:

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

Tulet käyttää tkinter graafisen käyttöliittymän luomiseen sovelluksellesi ja käyttöjärjestelmälle, ketjutus- ja aikamoduuleille niihin liittyville toiminnoille. Erottelemalla osan koodistasi säikeiksi, voit antaa sen toimia samanaikaisesti.

Galleriahakemiston luominen ja globaalien muuttujien ja lippujen määrittäminen

Luo hakemisto kaapattujen kuvien ja tallennettujen videoiden tallentamiseen. Tämä vaihe varmistaa, että hakemisto on olemassa ennen kuin jatkat videoiden kaappaamista tai tallentamista.

ifnot os.path.exists("gallery"):
os.makedirs("gallery")

Sitten määrittele image_thumbnails ja video_thumbnails muuttujia. Nämä tallentavat kuvien ja videoiden pikkukuvat galleriaan.

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

The update_camera lippu ohjaa kameran syötteiden päivityksiä.

Kuvien ottaminen kameran syötteestä

Määritä toiminto, joka käyttää OpenCV: tä kuvan ottamiseksi kameran syötteestä. Sen pitäisi sitten hakea kehys kamerasta ja tallentaa se galleria hakemistosta ja näytä se käyttämällä näytä_kuva.

defcapture_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)

Videon tallennuksen aloittaminen ja lopettaminen

Ennen kuin näytät videon, tarvitset tavan luoda se. Tämän saavuttamiseksi luo toiminto, joka käynnistää videotallennusprosessin, kun käyttäjä haluaa kaapata videon. Toiminnon tulee myös poistaa käytöstä Ennätys -painiketta (estääksesi usean tallennuksen samanaikaisesti) ja ota käyttöön Lopeta tallennus -painiketta. Tämä osoittaa, että tallennus on käynnissä.

defstart_recording():
global video_writer, recording_start_time, recording_stopped, update_camera

ifnot 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()

Luo sitten toiminto, joka pysäyttää videon tallennuksen ja vapauttaa videon kirjoittajan.

defstop_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)

Tämä toiminto päivittää myös käyttöliittymän, joka mahdollistaa Ennätys -painiketta ja poistamalla sen käytöstä Lopeta tallennus -painiketta. Tämä osoittaa, että tallennus on pysähtynyt.

Videoiden tallentaminen ja näyttäminen

Luo toiminto, joka kaappaa jatkuvasti kuvia kamerasta, käsittelee niitä ja näyttää ne graafisessa käyttöliittymässä kameran syötteenä. Sen pitäisi tehdä niin, ellei Lopeta tallennus -painiketta painetaan.

defrecord_and_display():
global recording_stopped, update_camera

while video_writer andnot 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)

Toiminto laskee myös tallennuksen alkamisesta kuluneen ajan ja näyttää sen videoruudussa.

Otettujen kuvien ja videoiden näyttäminen

Nyt kun olet ottanut kuvat ja tallentanut videot, tarvitset tavan näyttää ne.

Voit näyttää kuvat luomalla toiminnon, joka avaa kuvan ja näyttää sen kameran syötteessä. Tämä saavutetaan avaamalla kuva käyttämällä PILja muuntaa sen sitten muotoon, joka tkinter voi näyttää ja lopulta päivittää kameran syötteen widgetin uudella kuvalla.

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

Voit näyttää kaapatut videot luomalla toiminnon, joka avaa videosoitinikkunan, jossa käyttäjä voi katsella tallennettuja videoita. Se myös keskeyttää kameran syötteen päivitykset videon toiston aikana.

defplay_video(video_path):
defclose_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)

defupdate_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)

Kameran syötteiden päivitysten keskeyttäminen varmistaa sujuvan katselukokemuksen.

Videon pikkukuvan luominen ja gallerian avaaminen

Luo toiminto, joka luo pikkukuvan tietylle videolle. Tämä helpottaa käyttäjien tunnistaa kiinnostava video.

defcreate_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)

returnNone, None

Luo seuraavaksi toiminto, joka toistaa videon, kun käyttäjä napsauttaa videon pikkukuvaa galleriaikkunassa:

defplay_video_from_thumbnail(video_path):
play_video(video_path)

Luo sitten toiminto, joka luo uuden ikkunan, jossa käyttäjä voi katsella kaapattuja kuvia ja videoita.

defopen_gallery():
global update_camera
update_camera = False

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

defback_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)

defshow_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("", 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()

Pikkukuvat luodaan sekä kuville että videoille. Tämä tarkoittaa, että voit napsauttaa niitä nähdäksesi täysikokoisen kuvan tai toistaaksesi videon.

Pääkäyttöliittymän luominen sovelluksellesi

Aloita luomalla pää tkinter sovellusikkuna ja anna sille otsikko.

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

Alusta sitten vaaditut muuttujat.

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

Luo sitten painikkeita eri toimintoja varten.

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)

Järjestä pääikkunan painikkeet ruudukkoasettelun hallinnan avulla.

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)

Luo widget kameran syötteen näyttämiseksi ja alusta se.

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

Luo sitten toiminto, joka päivittää jatkuvasti näytössä näkyvää kameran syötettä tkinter ikkuna.

defupdate_camera_feed():
if update_camera:
ifnot 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()

Aloita lopuksi pää tkinter tapahtumasilmukka.

root.mainloop()

Tämä silmukka on vastuussa käyttäjien vuorovaikutusten käsittelystä.

Sovelluksen ominaisuuksien testaus

Tämä video esittelee sovelluksen eri ominaisuuksia:

Python-taitojen terävöittäminen OpenCV: llä

OpenCV hallitsee tietokonenäön suhteen. Se toimii useiden eri kirjastojen kanssa, joten voit luoda monia hienoja projekteja. Voit käyttää sitä Pythonin kanssa harjoitellaksesi ja teroittaaksesi ohjelmointitaitojasi.