עקוב אחר הפרויקט המקיף הזה כדי ללמוד עוד על Python ועיבוד תמונה.

בין אם אתה רוצה לעבוד על פרויקט Python מרתק או לחקור היבטים שונים של תכנות Python, בניית אפליקציית מצלמה משרתת מטרה זו. זה כרוך בשילוב היבטים שונים של תכנות Python, כגון פיתוח ממשק משתמש גרפי (GUI), עיבוד תמונה ווידאו ו-multi-threading.

כמו כן, פתרון אתגרים מעשיים כמו זה עוזר לחדד את כישורי פתרון הבעיות שלך. כישורים אלה הם בעלי ערך בכל מאמץ תכנות.

הגדרת הסביבה שלך

התחל ב יצירת סביבה וירטואלית חדשה. זה יבודד את הפרויקט שלך ויבטיח שלא תהיה התנגשות בין גרסאות שונות של החבילות שאתה מתקין. לאחר מכן, הפעל את פקודת הטרמינל הזו:

pip install opencv-python pillow

פקודה זו תתקין את OpenCV ספריה ו PIL (Python Imaging Library) בסביבה הוירטואלית שלך. תשתמש ב-OpenCV לפונקציונליות של ראייה ממוחשבת וב-PIL למניפולציה של תמונה.

קוד המקור המלא של פרויקט זה זמין ב-a מאגר GitHub.

ייבוא ​​הספריות הנדרשות

לאחר שהתקנת את הספריות הללו, תוכל לייבא אותן יחד עם מודולים נחוצים אחרים מהספרייה הסטנדרטית של Python:

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

אתה תעשה להשתמש tkinter ליצירת ממשק משתמש גרפי עבור היישום שלך ומערכת ההפעלה, השרשור והזמן עבור הפונקציונליות הקשורה אליהם. על ידי הפרדת חלק מהקוד שלך לשרשורים, תוכל לאפשר לו לפעול במקביל.

יצירת ספריית גלריה והגדרת משתנים ודגלים גלובליים

צור ספרייה לאחסון תמונות שצולמו וסרטונים מוקלטים. שלב זה יבטיח שהספרייה קיימת לפני שתמשיך לצלם או להקליט סרטונים.

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

ואז תגדיר image_thumbnails ו video_thumbnails משתנים. אלה יאחסנו תמונות ממוזערות של תמונות וסרטונים בגלריה.

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

ה update_camera הדגל ישלוט בעדכוני עדכון המצלמה.

לכידת תמונות מהזנת המצלמה

הגדר פונקציה שתשתמש ב-OpenCV כדי ללכוד תמונה מהזנת המצלמה. לאחר מכן הוא אמור לאחזר מסגרת מהמצלמה, לשמור אותה ב- גלריה ספרייה, והצג אותה באמצעות show_image.

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)

הפעלה והפסקה של הקלטת וידאו

לפני שאתה מציג סרטון, אתה צריך דרך ליצור אותו. כדי להשיג זאת, צור פונקציה שמתחילה את תהליך הקלטת הווידאו כאשר המשתמש רוצה לצלם סרטון. הפונקציה צריכה גם להשבית את תקליט לחצן (כדי למנוע הקלטות מרובות בו זמנית) ולאפשר את הפסק להקליט לַחְצָן. זה מציין שההקלטה מתבצעת.

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

לאחר מכן, צור פונקציה שעוצרת את הקלטת הווידאו ומשחררת את כותב הווידאו.

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)

פונקציה זו גם מעדכנת את ממשק המשתמש המאפשרת את תקליט כפתור והשבתת הפסק להקליט לַחְצָן. זה מציין שההקלטה הופסקה.

הקלטה והצגת סרטונים

צור פונקציה שתצלם ברציפות פריימים מהמצלמה, תעבד אותם ותציג אותם ב-GUI כהזנת המצלמה. זה צריך לעשות זאת אלא אם כן הפסק להקליט כפתור נלחץ.

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)

הפונקציה גם מחשבת את הזמן שחלף מאז תחילת ההקלטה ומציגה אותו במסגרת הווידאו.

הצגת תמונות וסרטונים שצולמו

כעת לאחר שלכדת את התמונות והקלטת את הסרטונים, אתה צריך דרך להציג אותם.

כדי להציג את התמונות, צור פונקציה שפותחת תמונה ומציגה אותה בהזנת המצלמה. זה מושג על ידי פתיחת התמונה באמצעות PIL, ולאחר מכן המרת אותו לפורמט ש tkinter יכול להציג, ולבסוף עדכון הווידג'ט של הזנת המצלמה עם התמונה החדשה.

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

כדי להציג את הסרטונים שצולמו, צור פונקציה שפותחת חלון נגן וידאו שבו המשתמש יכול לצפות בסרטונים מוקלטים. זה גם משהה את עדכוני הזנת המצלמה בזמן שהסרטון מופעל.

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)

השהיית עדכוני הזנת המצלמה מבטיחה חווית צפייה חלקה.

יצירת תמונה ממוזערת של וידאו ופתיחת הגלריה

צור פונקציה שתיצור תמונה ממוזערת עבור סרטון נתון. זה יקל על המשתמשים לזהות את הסרטון המעניין.

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

לאחר מכן, צור פונקציה שמשמיעה סרטון כאשר משתמש לוחץ על התמונה הממוזערת של הסרטון בחלון הגלריה:

defplay_video_from_thumbnail(video_path):
play_video(video_path)

לאחר מכן צור פונקציה שיוצרת חלון חדש שבו המשתמש יכול להציג את התמונות והסרטונים שצולמו.

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

תמונות ממוזערות נוצרות הן עבור תמונות והן עבור סרטונים. זה אומר שאתה יכול ללחוץ עליהם כדי לראות את התמונה בגודל מלא או להפעיל את הסרטון.

יצירת ממשק המשתמש הראשי עבור האפליקציה שלך

התחל ביצירת הראשי tkinter חלון יישום ולאחר מכן תן לו כותרת.

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

לאחר מכן אתחל את המשתנים הנדרשים.

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

לאחר מכן צור כפתורים לפעולות שונות.

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)

השתמש במנהל פריסת הרשת כדי לארגן את הכפתורים בחלון הראשי.

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)

צור ווידג'ט כדי להציג את עדכון המצלמה ולאתחל אותו.

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

לאחר מכן, צור פונקציה שמעדכנת ברציפות את הזנת המצלמה המוצגת ב- tkinter חַלוֹן.

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

לבסוף, התחל את הראשי tkinter לולאת אירועים.

root.mainloop()

לולאה זו אחראית לטיפול באינטראקציות של משתמשים.

בדיקת תכונות האפליקציה

סרטון זה מדגים תכונות שונות של האפליקציה:

חידוד כישורי הפייתון שלך עם OpenCV

OpenCV שולט בכל הנוגע לראייה ממוחשבת. זה עובד עם הרבה ספריות שונות המאפשרות לך ליצור פרויקטים מגניבים רבים. אתה יכול להשתמש בו עם Python כדי לתרגל ולחדד את כישורי התכנות שלך.