خبر و ترفند روز

خبر و ترفند های روز را اینجا بخوانید!

نحوه ساخت اپلیکیشن دوربین با استفاده از پایتون

برای آشنایی بیشتر با پایتون و پردازش تصویر، این پروژه جامع را دنبال کنید.

چه بخواهید روی یک پروژه جذاب پایتون کار کنید یا جنبه های مختلف برنامه نویسی پایتون را کشف کنید، ساخت یک اپلیکیشن دوربین این هدف را دنبال می کند. این شامل ترکیب جنبه های مختلف برنامه نویسی پایتون، مانند توسعه رابط کاربری گرافیکی (GUI)، پردازش تصویر و ویدئو، و چند رشته ای است.

همچنین، حل چالش های عملی مانند این به تقویت مهارت های حل مسئله شما کمک می کند. این مهارت ها در هر تلاش برنامه نویسی ارزشمند هستند.

تنظیم محیط

با ایجاد یک محیط مجازی جدید شروع کنید. این کار پروژه شما را ایزوله می کند و اطمینان حاصل می کند که هیچ تضادی بین نسخه های مختلف بسته هایی که نصب می کنید وجود ندارد. سپس این دستور ترمینال را اجرا کنید:

pip install opencv-python pillow

این دستور کتابخانه OpenCV و PIL (Python Imaging Library) را در محیط مجازی شما نصب می کند. شما از OpenCV برای عملکرد بینایی کامپیوتر و PIL برای دستکاری تصویر استفاده خواهید کرد.

کد منبع کامل این پروژه در یک مخزن GitHub موجود است.

واردات کتابخانه های مورد نیاز

هنگامی که این کتابخانه ها را نصب کردید، می توانید آنها را به همراه سایر ماژول های ضروری از کتابخانه استاندارد پایتون وارد کنید:

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

شما از tkinter برای ایجاد یک رابط کاربری گرافیکی برای برنامه خود و ماژول های OS، Threading و زمان برای عملکرد مرتبط با آنها استفاده خواهید کرد. با جدا کردن برخی از کدهای خود به رشته ها، آن را فعال می کنید تا همزمان اجرا شود.

ایجاد دایرکتوری گالری و تعریف متغیرها و پرچم های جهانی

یک دایرکتوری برای ذخیره تصاویر گرفته شده و فیلم های ضبط شده ایجاد کنید. این مرحله از وجود دایرکتوری قبل از اقدام به ضبط یا ضبط ویدیو اطمینان حاصل می کند.

if not 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 نمایش دهد.

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)

شروع و توقف ضبط ویدیو

قبل از نمایش یک ویدیو، به راهی برای ایجاد آن نیاز دارید. برای رسیدن به این هدف، عملکردی ایجاد کنید که زمانی که کاربر می‌خواهد فیلمی را ضبط کند، فرآیند ضبط ویدیو را آغاز می‌کند. این عملکرد همچنین باید دکمه ضبط را غیرفعال کند (برای جلوگیری از ضبط چندگانه به طور همزمان) و دکمه توقف ضبط را فعال کند. این نشان می دهد که ضبط در حال انجام است.

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

سپس، عملکردی ایجاد کنید که ضبط ویدیو را متوقف می کند و ویدیونویس را آزاد می کند.

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)

این عملکرد همچنین رابط کاربری را به روز می کند و دکمه ضبط را فعال می کند و دکمه توقف ضبط را غیرفعال می کند. این نشان می دهد که ضبط متوقف شده است.

مطلب مرتبط:   3 روش برای استقرار یک React Application در Netlify

ضبط و نمایش فیلم ها

عملکردی ایجاد کنید که به‌طور مداوم فریم‌ها را از دوربین بگیرد، آنها را پردازش کند و در رابط کاربری گرافیکی به عنوان خوراک دوربین نمایش دهد. باید این کار را انجام دهد مگر اینکه دکمه توقف ضبط را فشار دهید.

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)

این عملکرد همچنین زمان سپری شده از شروع ضبط را محاسبه می کند و آن را روی قاب ویدیو نمایش می دهد.

نمایش تصاویر و فیلم های گرفته شده

اکنون که تصاویر را گرفته اید و فیلم ها را ضبط کرده اید، به راهی برای نمایش آنها نیاز دارید.

برای نمایش تصاویر، عملکردی ایجاد کنید که تصویری را باز کرده و در فید دوربین نمایش دهد. این با باز کردن تصویر با استفاده از PIL، سپس تبدیل آن به فرمتی که tkinter می تواند نمایش دهد، و در نهایت به روز رسانی ویجت تغذیه دوربین با تصویر جدید به دست می آید.

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

برای نمایش ویدیوهای گرفته شده، عملکردی ایجاد کنید که پنجره پخش کننده ویدیو را باز می کند تا کاربر بتواند فیلم های ضبط شده را مشاهده کند. همچنین به‌روزرسانی‌های فید دوربین را در حین پخش ویدیو متوقف می‌کند.

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)

توقف موقت به‌روزرسانی‌های فید دوربین، تجربه تماشای روان را تضمین می‌کند.

مطلب مرتبط:   چگونه برنامه جنگو خود را در حالت تعمیر و نگهداری قرار دهیم

ایجاد تصویر کوچک ویدیو و باز کردن گالری

یک تابع ایجاد کنید که یک تصویر کوچک برای یک ویدیوی مشخص ایجاد کند. این کار شناسایی ویدیوی مورد علاقه را برای کاربران آسان تر می کند.

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

در مرحله بعد، عملکردی ایجاد کنید که وقتی کاربر روی تصویر کوچک ویدیو در پنجره گالری کلیک می کند، یک ویدیو پخش می کند:

def play_video_from_thumbnail(video_path):
    play_video(video_path)

سپس یک تابع ایجاد کنید که یک پنجره جدید ایجاد می کند که در آن کاربر می تواند تصاویر و فیلم های گرفته شده را مشاهده کند.

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

ریز عکسها هم برای تصاویر و هم برای فیلم ها ایجاد می شوند. این بدان معناست که می توانید برای مشاهده تصویر در اندازه واقعی روی آنها کلیک کنید یا فیلم را پخش کنید.

مطلب مرتبط:   نحوه ساخت میکروسرویس در پایتون

ایجاد رابط کاربری اصلی برای برنامه شما

با ایجاد پنجره اصلی برنامه 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)

از Grid layout manager برای سازماندهی دکمه ها در پنجره اصلی استفاده کنید.

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 را به روز می کند.

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

در نهایت حلقه رویداد اصلی tkinter را شروع کنید.

root.mainloop()

این حلقه مسئول مدیریت تعاملات کاربر است.

تست ویژگی های برنامه

این ویدیو ویژگی های مختلف این برنامه را نشان می دهد:

تقویت مهارت های پایتون با OpenCV

وقتی صحبت از بینایی کامپیوتری به میان می آید OpenCV غالب است. با بسیاری از کتابخانه های مختلف کار می کند و شما را قادر می سازد تا پروژه های جالب بسیاری ایجاد کنید. می توانید از آن با پایتون برای تمرین و تقویت مهارت های برنامه نویسی خود استفاده کنید.