FA-TOOLS — Header Component
آموزش ادغام چند تصویر با PIL

آموزش جامع ادغام چند تصویر با کتابخانه PIL در پایتون

خلاصه کاربردی مقاله:

  • یادگیری متدهای اصلی ادغام تصاویر (افقی، عمودی و هم‌پوشانی) در پایتون با کدهای کاملاً تست‌شده.
  • آموزش هم‌اندازه کردن تصاویر مختلف قبل از ترکیب آن‌ها برای جلوگیری از به هم ریختگی کادر.
  • ارائه راهکارهای عملی برای ساخت آلبوم تصاویر شبکه‌ای و اعمال واترمارک روی عکس‌ها.

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

کتابخانه PIL (Pillow) چیست و چرا برای ادغام تصاویر مناسب است؟

آموزش ادغام چند تصویر با PIL — تصویر 1

کتابخانه Pillow (نسخه توسعه‌یافته PIL) محبوب‌ترین ابزار پایتون برای کار با تصاویر است که به دلیل سرعت بالا، سادگی دستورات و پشتیبانی از انواع فرمت‌ها، بهترین گزینه برای ترکیب و ادغام تصاویر به شمار می‌رود. این کتابخانه به شما اجازه می‌دهد ماتریس‌های پیکسلی تصاویر را با کمترین مصرف حافظه ترکیب کنید.

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

پیش‌نیازها و نصب کتابخانه Pillow

آموزش ادغام چند تصویر با PIL — تصویر 2

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

pip install Pillow

پس از نصب، کلاس‌های مورد نیاز را به پروژه خود وارد می‌کنیم. در بیشتر سناریوهای ادغام، کلاس Image از کتابخانه PIL تمام نیازهای ما را پوشش می‌دهد.

۱. ادغام افقی و عمودی تصاویر (Stitching)

آموزش ادغام چند تصویر با PIL — تصویر 3

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

اگر ابعاد تصاویر یکسان نباشد، ابتدا باید اندازه آن‌ها را تغییر دهیم تا خروجی نهایی بدون حاشیه خالی یا کشیدگی بیهوده ایجاد شود. در ادامه یک تابع کامل برای ادغام افقی دو تصویر با ارتفاع‌های متفاوت آورده شده است:

from PIL import Image

def merge_images_horizontally(image1_path, image2_path, output_path):
    # باز کردن تصاویر
    img1 = Image.open(image1_path)
    img2 = Image.open(image2_path)
    
    # هم‌اندازه کردن ارتفاع تصویر دوم متناسب با تصویر اول
    if img1.height != img2.height:
        new_width = int(img2.width * (img1.height / img2.height))
        img2 = img2.resize((new_width, img1.height), Image.Resampling.LANCZOS)
    
    # محاسبه ابعاد تصویر نهایی
    total_width = img1.width + img2.width
    combined_image = Image.new('RGB', (total_width, img1.height))
    
    # چسباندن تصاویر در موقعیت مناسب
    combined_image.paste(img1, (0, 0))
    combined_image.paste(img2, (img1.width, 0))
    
    # ذخیره تصویر خروجی
    combined_image.save(output_path)
    print("تصاویر با موفقیت به صورت افقی ادغام شدند!")

# نمونه فراخوانی تابع
# merge_images_horizontally('left.jpg', 'right.jpg', 'merged_horizontal.jpg')

برای ادغام عمودی نیز کافی است عرض تصاویر را هماهنگ کرده و موقعیت چسباندن (Y-axis) تصویر دوم را برابر با ارتفاع تصویر اول قرار دهید.

۲. قرار دادن یک تصویر روی تصویر دیگر (Overlay / Watermark)

آموزش ادغام چند تصویر با PIL — تصویر 4

ادغام لایه‌ای یا قرار دادن یک تصویر (مانند لوگو یا آیکون) روی یک تصویر بزرگتر، با استفاده از حالت شفافیت (Alpha Channel) انجام می‌شود. برای این کار باید هر دو تصویر را در حالت رنگی RGBA پردازش کنیم.

اگر از کانال آلفا استفاده نکنید، بخش‌های شفاف لوگو یا واترمارک شما به صورت یک کادر سفید یا مشکی زشت روی تصویر اصلی ظاهر می‌شوند. کد زیر نحوه اضافه کردن لوگوی شفاف روی گوشه پایین سمت راست یک تصویر را نشان می‌دهد:

from PIL import Image

def apply_watermark(base_image_path, watermark_path, output_path):
    # باز کردن تصویر اصلی و لوگو و تبدیل به حالت RGBA
    base_img = Image.open(base_image_path).convert('RGBA')
    watermark = Image.open(watermark_path).convert('RGBA')
    
    # تغییر اندازه لوگو در صورت نیاز (مثلاً ۱۵ درصد عرض تصویر اصلی)
    scale_factor = 0.15
    new_width = int(base_img.width * scale_factor)
    new_height = int(watermark.height * (new_width / watermark.width))
    watermark = watermark.resize((new_width, new_height), Image.Resampling.LANCZOS)
    
    # محاسبه موقعیت (پایین سمت راست با فاصله ۲۰ پیکسلی از لبه‌ها)
    position = (base_img.width - watermark.width - 20, base_img.height - watermark.height - 20)
    
    # ادغام با استفاده از ماسک آلفا برای حفظ شفافیت
    base_img.paste(watermark, position, watermark)
    
    # ذخیره نهایی به صورت RGB (فرمت JPEG کانال آلفا را پشتیبانی نمی‌کند)
    final_img = base_img.convert('RGB')
    final_img.save(output_path, 'JPEG', quality=95)
    print("واترمارک با موفقیت اعمال شد!")

# نمونه فراخوانی تابع
# apply_watermark('background.jpg', 'logo.png', 'result_watermark.jpg')

۳. ساخت گالری شبکه‌ای (کلاژ تصاویر)

آموزش ادغام چند تصویر با PIL — تصویر 5

کلاژ شبکه‌ای به فرآیندی گفته می‌شود که در آن چند تصویر هم‌اندازه به صورت ردیفی و ستونی (مثلاً ۲در۲ یا ۳در۳) در یک بوم واحد چیده می‌شوند. این متد برای ساخت تصاویر کاتالوگ فروشگاه‌های اینترنتی فوق‌العاده کاربردی است.

در کد زیر، ما صریحاً یک ساختار شبکه‌ای تعریف می‌کنیم که فهرستی از تصاویر را دریافت کرده، آن‌ها را هم‌اندازه می‌کند و در قالب ستون‌ها و ردیف‌های منظم خروجی می‌دهد:

from PIL import Image

def create_image_grid(image_paths, output_path, cols=2, thumb_size=(300, 300)):
    # محاسبه تعداد ردیف‌های مورد نیاز
    num_images = len(image_paths)
    rows = (num_images + cols - 1) // cols
    
    # محاسبه اندازه بوم نهایی
    grid_width = cols * thumb_size[0]
    grid_height = rows * thumb_size[1]
    
    # ایجاد بوم خالی سفید رنگ
    grid_image = Image.new('RGB', (grid_width, grid_height), color='white')
    
    for index, path in enumerate(image_paths):
        # باز کردن و تغییر اندازه تصویر به مربع هم‌اندازه
        img = Image.open(path)
        img = img.thumbnail(thumb_size) # حفظ نسبت تصویر
        
        # برای داشتن مربع دقیق، از متد متناسب‌تر استفاده می‌کنیم:
        img = Image.open(path).resize(thumb_size, Image.Resampling.LANCZOS)
        
        # محاسبه موقعیت قرارگیری در جدول شبکه‌ای
        col = index % cols
        row = index // cols
        x = col * thumb_size[0]
        y = row * thumb_size[1]
        
        # چسباندن روی بوم اصلی
        grid_image.paste(img, (x, y))
        
    grid_image.save(output_path)
    print("تصویر شبکه‌ای با موفقیت ساخته شد!")

# نمونه فراخوانی برای ۴ تصویر
# list_of_images = ['img1.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg']
# create_image_grid(list_of_images, 'collage_grid.jpg', cols=2)

شما می‌توانید با تغییر متغیر cols به راحتی چیدمان‌های ۳ ستونه یا بیشتر بسازید. این انعطاف‌پذیری باعث می‌شود بدون نیاز به کدهای پیچیده، هر نوع چینشی را مدیریت کنید. اگر به برنامه‌نویسی وب و طراحی فرانت‌اند علاقه‌مند هستید، بد نیست بدانید که الگوهای مشابهی در CSS و جاوااسکریپت برای چیدمان گالری‌ها وجود دارند که در بخش‌های آموزشی ما مثل تکه‌کدهای کاربردی وب به تفصیل بررسی شده‌اند.

جدول مقایسه متدهای ادغام تصویر در PIL

برای انتخاب بهترین متد متناسب با سناریوی پروژه خود، می‌توانید از جدول راهنمای زیر استفاده کنید:

متد ادغام (پایتون) بهترین سناریوی استفاده
Stitching (افقی/عمودی) ساخت تصاویر قبل و بعد (Before/After) یا اتصال شات‌های عریض پانوراما.
Paste با ماسک RGBA افزودن لوگوی ترنسپرنت، ثبت کپی‌رایت، هولوگرام و آیکون روی تصاویر اصلی.
Image.blend (ترکیب خطی) افکت‌های ترنزیشن ویدیو و محو کردن تدریجی دو تصویر در یکدیگر با آلفای متغیر.
Grid Layout (چیدمان شبکه‌ای) ساخت کاتالوگ فروشگاهی و خروجی‌های بهینه برای پست‌های چندتایی شبکه‌های اجتماعی.

عیب‌یابی سریع خطاهای رایج

هنگام کار با تصاویر در پایتون، مواجه شدن با برخی باگ‌ها کاملاً طبیعی است. در ادامه رایج‌ترین خطاها و راه‌حل‌های عملی آن‌ها را بررسی می‌کنیم:

  • خطای ValueError: images do not match
    علت: این خطا زمانی رخ می‌دهد که سایز یا فرمت رنگی تصاویرِ در حال ترکیب، همخوانی ندارند.
    راه‌حل: مطمئن شوید که قبل از چسباندن (paste) یا ادغام، متد resize() را برای هماهنگ‌سازی ابعاد فراخوانی کرده‌اید.
  • سیاه شدن پس‌زمینه تصاویر شفاف (PNG) پس از ذخیره به صورت JPG
    علت: فرمت JPEG از کانال آلفا (شفافیت) پشتیبانی نمی‌کند و پیکسل‌های بدون رنگ را به رنگ تیره تبدیل می‌کند.
    راه‌حل: قبل از ذخیره با فرمت JPEG، تصویر را با متد convert('RGB') تبدیل کنید تا پس‌زمینه ترنسپرنت به سفید یا رنگ دلخواه تبدیل شود.
  • خطای OSError: cannot write mode RGBA as JPEG
    علت: تلاش برای ذخیره مستقیم تصویر حاوی لایه شفافیت به عنوان فایل JPG.
    راه‌حل: فرمت ذخیره‌سازی را روی PNG بگذارید یا حالت رنگی تصویر را قبل از ذخیره به RGB تغییر دهید.

پرسش‌های متداول

چگونه می‌توان چند تصویر با ابعاد کاملاً متفاوت را بدون دفورمه شدن ادغام کرد؟
بهترین کار استفاده از متد crop یا تغییر اندازه متناسب با حفظ نسبت ابعاد (Aspect Ratio) است. شما می‌توانید عرض تصویر کوچک‌تر را مبنا قرار داده و تصویر بزرگ‌تر را بر همان اساس مقیاس‌دهی کنید.

تفاوت متد blend و paste در کتابخانه PIL چیست؟
متد paste یک تصویر را دقیقاً روی هماهنگی‌های یک موقعیت خاص در تصویر دیگر کپی می‌کند (مانند چسباندن برچسب)، در حالی که متد blend دو تصویر هم‌اندازه را با اعمال یک ضریب شفافیت مشخص در تمام سطح تصویر با هم ترکیب می‌کند.

چرا پس از ادغام، کیفیت تصاویر خروجی کاهش پیدا می‌کند؟
هنگام ذخیره تصاویر با فرمت JPEG، پایتون به صورت پیش‌فرض فشرده‌سازی اعمال می‌کند. برای حفظ کیفیت حداکثری، در زمان متد save مقدار آرگومان quality را روی اعداد بالا مانند 95 یا 100 تنظیم کنید.

آیا می‌توان این تصاویر ادغام شده را مستقیماً در صفحات وب نمایش داد؟
بله، شما می‌توانید پس از ذخیره نهایی تصویر روی سرور، آدرس فایل را در تگ‌های HTML نمایش دهید. همچنین در محیط‌های جنگو یا فلسک امکان ارسال تصویر ادغام شده به صورت بایت‌های مستقیم (BytesIO) بدون نیاز به ذخیره‌سازی روی دیسک وجود دارد.

Table of Contents

آخرین نوشته‌ها