Python ile Toplu Görsel Optimizasyon: Pillow & OpenCV Kullanımı

Python, Pillow ve OpenCV ile toplu görsel optimizasyonu yaparak e-ticaret görsellerini hızlı, tutarlı ve web uyumlu hale getirin.

2024-11-20

Bir E-ticaret müşterimiz bize şöyle geldi: 12.000 ürün görseli var, hepsi farklı boyut ve formatta, tümünün standartlaştırılması gerekiyor. Grafiker elle yapıyor, günlerce sürüyor, aynı iş her katalog güncellemesinde tekrarlanıyor. Python ile otomatize ettiğimizde aynı iş 20 dakikaya indi. İnsan müdahalesi sıfır, tekrar edilebilir, ücretsiz.

Bu yazı o görsel optimizasyonu çözümünün altındaki teknik yaklaşımı anlatıyor.

Neden Toplu Görsel İşlemeye İhtiyaç Duyulur?

E-ticaret platformları, içerik yönetim sistemleri ve medya arşivleri zamanla binlerce hatta milyonlarca görsel biriktiriyor. Bu görsellerin tek tek elle işlenmesi hem zaman kaybı hem de insan hatasına açık bir süreç.

Toplu görsel işlemenin en sık karşılaşılan kullanım senaryoları şunlar:

  • E-ticaret ürün fotoğraflarını standart boyuta getirme
  • Web sitesi için ağır görselleri site hız optimizasyonu kapsamında optimize etme
  • Arşiv fotoğraflarını WebP formatına dönüştürme
  • Sosyal medya paylaşımları için farklı en-boy oranlarında kırpma

Python + Pillow + OpenCV Mimarisi

İki kütüphanenin birbirini tamamlayan özellikleri var:

Pillow format dönüştürme, temel yeniden boyutlandırma ve metadata yönetiminde güçlü. JPEG, PNG, WebP, TIFF, BMP dahil onlarca formatı destekliyor. EXIF verilerini koruyarak işlem yapabiliyorsunuz.

OpenCV ise piksel düzeyinde manipülasyon, yüz/nesne algılama ile akıllı kırpma gibi gelişmiş işlemler için tercih ediliyor. Özellikle içerik odaklı kırpma (smart crop) yaparken OpenCV’nin nesne algılama özelliklerini kullanmak sonuçları dramatik biçimde iyileştiriyor.

Temel Mimari

from PIL import Image
import cv2
import json
import os
from pathlib import Path

class ImageProcessor:
    def __init__(self, config_path: str):
        with open(config_path) as f:
            self.config = json.load(f)

    def process_directory(self, input_dir: str, output_dir: str, dry_run: bool = False):
        images = list(Path(input_dir).glob("**/*"))
        images = [i for i in images if i.suffix.lower() in self.config["supported_formats"]]

        for img_path in images:
            if dry_run:
                self._preview(img_path)
            else:
                self._process(img_path, output_dir)

JSON Tabanlı Konfigürasyon

Esnek ayar yönetimi için tüm parametreleri bir JSON dosyasında tutuyoruz. Bu sayede teknik olmayan ekip üyeleri bile temel ayarları değiştirebiliyor:

{
  "supported_formats": [".jpg", ".jpeg", ".png", ".webp", ".tiff"],
  "output_format": "webp",
  "quality": 85,
  "resize": {
    "enabled": true,
    "max_width": 1920,
    "max_height": 1080,
    "maintain_aspect_ratio": true
  },
  "crop": {
    "enabled": false,
    "width": 800,
    "height": 600,
    "smart_crop": true
  },
  "strip_metadata": false,
  "naming": "{original_name}_optimized"
}

Dry-Run: İşlem Öncesi Önizleme

Binlerce görsele uygulamadan önce sonucu görmek kritik önem taşıyor. Dry-run modu gerçek işlem yapmadan ne olacağını raporluyor:

def _preview(self, img_path: Path):
    with Image.open(img_path) as img:
        original_size = img_path.stat().st_size / 1024
        estimated_output = self._estimate_size(img)

        print(f"[DRY RUN] {img_path.name}")
        print(f"  Boyut: {img.size[0]}x{img.size[1]} -> {self._target_size(img)}")
        print(f"  Dosya: {original_size:.1f}KB -> ~{estimated_output:.1f}KB")
        print(f"  Format: {img.format} -> {self.config['output_format'].upper()}")

Bu çıktıyı bir CSV’ye de yazabiliyorsunuz — sonra Excel’de inceleyip onay verdikten sonra asıl işlemi başlatıyorsunuz.

Desteklenen Format ve Operasyonlar

Formatlar

  • JPEG — kalite parametresiyle kayıplı sıkıştırma
  • PNG — şeffaflık desteği, kayıpsız
  • WebP — modern web standardı, JPEG’e göre %25-35 daha küçük
  • TIFF — yayıncılık ve baskı için yüksek kalite arşiv

Operasyonlar

Resize (Yeniden Boyutlandırma): En-boy oranını koruyarak veya tam boyuta crop ile dolduruarak çalışıyor. Küçültme için Lanczos, büyütme için bicubic interpolasyon kullanıyoruz.

Crop (Kırpma): Standart merkez-kırpma veya OpenCV ile akıllı kırpma. Akıllı kırpma ana nesneyi kadraja almaya çalışıyor.

Format Dönüştürme: Kaynak format ne olursa olsun hedef formata çevirme. PNG’den WebP’ye geçişte dosya boyutları ortalama %40 küçülüyor.

Performans: Binlerce Görsel için Optimizasyon

Python’un concurrent.futures modülüyle işlemi paralel hale getiriyoruz:

from concurrent.futures import ThreadPoolExecutor, as_completed

def process_bulk(self, images: list, output_dir: str):
    with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
        futures = {executor.submit(self._process, img, output_dir): img for img in images}

        for future in as_completed(futures):
            img = futures[future]
            try:
                result = future.result()
                print(f"[OK] {img.name} -> {result['saved_kb']:.1f}KB tasarruf")
            except Exception as e:
                print(f"[HATA] {img.name}: {e}")

Tipik bir 8 çekirdekli makinede 10.000 görseli işleme süresi:

  • Sıralı: ~45 dakika
  • Paralel (8 thread): ~7 dakika

Pratik Karar Rehberi: Hangi Durum İçin Hangi Araç?

Bu çözümün ne zaman kullanılacağına karar vermek için basit bir rehber:

Pillow yeterli mi? Standart yeniden boyutlandırma, format dönüştürme ve EXIF yönetimi için evet. Ürün fotoğrafı standartlaştırması, arşiv dönüştürme ve web optimizasyonu Pillow ile çözülür.

OpenCV eklemeli misiniz? İçerik odaklı kırpma (ürün nesnesini otomatik ortalama), yüz algılama ile profil fotoğrafı kırpma veya görüntü kalite analizi yapmanız gerekiyorsa evet.

Paralel işleme ne zaman şart? 1.000 görselin üzerinde. Altında fark etmeyebilirsiniz; üstünde sıralı işleme sabahı akşama getirebilir.

Sonuç

Python + Pillow + OpenCV kombinasyonu, kurumsal ölçekte görsel işleme ihtiyaçlarını karşılayan güçlü ve esnek bir çözüm sunuyor. JSON tabanlı konfigürasyon ile farklı projeler için farklı profiller oluşturup yönetebilirsiniz. Dry-run modu sayesinde büyük arşivlere uygulamadan önce güvenle test edebilirsiniz.

Bu yaklaşım Barlas Dijital’in KOBİ’ler için geliştirdiği otomasyon çözümlerinin somut bir örneği: standart bir araç satın almak yerine ihtiyaca özel ve tekrar kullanılabilir bir çözüm. E-ticaret ve otomasyonun birleştiği Defys gibi projelerde bu tür standartlaştırma işleri operasyonel yükü ciddi biçimde azaltır. 12.000 görseli her katalog güncellemesinde saatler harcayarak işlemek yerine aynı işi 20 dakikada tamamlamak, hem maliyet hem de ekip kapasitesi açısından ölçülebilir bir fark yaratıyor. Benzer bir otomasyon ihtiyacınız varsa veya mevcut görsel işleme süreçlerinizi optimize etmek istiyorsanız bizimle iletişime geçin.