Büyükler için · tarayıcıda görüntü işleme + Python cv2Bitirme
Bitirme projesi: belge tarayıcı
Telefonla eğik çekilmiş bir sayfa fotoğrafından düz, okunur, siyah-beyaz bir tarama üreten hat: kenar, kontur, perspektif düzeltme ve uyarlamalı eşik. Önce tarayıcıda, sonra kendi Python kodunla.
Belge tarayıcı hattı
Bitirme projesinin tamamı: gri → Gauss → Canny → genişletme → en büyük dörtgen kontur → perspektif düzeltme → uyarlamalı eşik. Her aşamayı tek tek gör, parametreleri değiştir, kendi fotoğrafını yükle.
3B masa ve sanal kamera
Masada A4 bir belge ve iğne deliği modeliyle bir kamera. Kamerayı yükselt, döndür, yaklaştır: görüntü bu kameradan gerçekten üretilir (her pikselin ışını masa düzlemiyle kesiştirilir). Sonra köşe bulma ve perspektif düzeltme aynı görüntüye uygulanır; gerçek köşelerle karşılaştırılır.
Senaryo
Kullanıcı masadaki bir sayfanın fotoğrafını çeker. Program sayfanın dört köşesini bulur (bulamazsa kullanıcıdan dört tıklama ister), sayfayı A4 oranında düzler, gölge ve düzensiz ışığa rağmen yazıyı temiz bir siyah-beyaz görüntüye çevirir ve PNG olarak kaydeder. Bir klasördeki tüm fotoğrafları toplu işleyebilir.
Gereksinimler (test edilebilir)
- G1: Test setindeki 20 fotoğrafın en az 17'sinde köşeler otomatik bulunur; bulunan her köşe elle işaretlenmiş köşeye 2 %'lik (görüntü köşegeninin) mesafeden yakındır.
- G2: Köşe bulunamazsa program çökmez; kullanıcıdan dört nokta ister ve aynı hattı sürdürür.
- G3: Çıktı A4 oranındadır (1 : 1,414 ± %2) ve satırlar yataydan en fazla 1° sapar.
- G4: Düzensiz ışıkta (bir yanı gölgede) çekilmiş sayfada zemin beyaz kalır: zeminin %95'i 255.
- G5: 12 MP bir fotoğraf dizüstü bilgisayarda 1 saniyeden kısa sürede işlenir (işlem önce 1000 px'e küçültülür, köşeler geri ölçeklenir).
- G6: Komut satırı arayüzü: tarayici.py girdi_klasoru cikti_klasoru [--debug]; --debug her aşamanın ara görüntüsünü kaydeder.
Mimari
- onisle(img) → küçültme ölçeği ve gri, bulanık görüntü (2. ve 4. üniteler).
- kenarlar(gri) → Canny + genişletme ile kapalı sınırlar (5. ve 6. üniteler).
- kose_bul(kenar) → en büyük dışbükey dörtgen kontur, sıralı dört köşe ya da None (7. ünite).
- duzle(img, koseler) → homografi ve warpPerspective, A4 oranında hedef (9. ünite).
- taranmis(duz) → uyarlamalı eşik ya da black-hat ile siyah-beyaz (3. ve 6. üniteler).
- Her fonksiyon saf: görüntü alır, görüntü/değer döner; G/Ç (dosya, kamera, tıklama) yalnız ana modülde.
Test planı
- Birim: kose_sirala dört noktayı her girdi sırasında aynı sıraya koyar (24 permütasyon).
- Birim: sentetik eğik dikdörtgen (bilinen köşeler) üretip kose_bul'un 2 px içinde bulduğunu sına (bu dersteki örnek sahne gibi).
- Birim: duzle sonrası dört köşe hedef dikdörtgenin köşelerine 0,5 px içinde düşer (gidiş-dönüş).
- Kabul: 20 fotoğraflık altın set; G1, G3 ve G4 ölçütlerini hesaplayan bir betik ve sonuç tablosu.
- Performans: 20 fotoğrafın ortalama ve en kötü işlem süresi; G5'i aşan fotoğraf sayısı.
- Hata durumları: boş görüntü, tamamen siyah görüntü, sayfa yok, iki sayfa yan yana.
Demo ve sunum
- Canlı demo: o an çekilen bir fotoğrafı tara, --debug ara görüntülerini göster.
- Başarısız bir örneği göster ve nedenini aşama aşama açıkla (hangi aşama, hangi parametre).
- Test tablosu: G1–G6 için ölçülen değerler ve geçti/kaldı.
- Sonraki adım önerisi: OCR (Tesseract) ya da kamerada canlı köşe izleme.
Başlangıç kodu
import cv2
import numpy as np
def order(pts):
s, d = pts.sum(1), np.diff(pts, axis=1).ravel()
return np.float32([pts[s.argmin()], pts[d.argmin()], pts[s.argmax()], pts[d.argmax()]])
def find_quad(img, canny=(50, 150), min_frac=0.2):
gray = cv2.GaussianBlur(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), (5, 5), 0)
edges = cv2.dilate(cv2.Canny(gray, *canny), np.ones((3, 3), np.uint8)) # kopuk kenarları birleştir
cnts, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
area = img.shape[0] * img.shape[1]
for cnt in sorted(cnts, key=cv2.contourArea, reverse=True)[:5]:
approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True)
if len(approx) == 4 and cv2.contourArea(approx) > min_frac * area and cv2.isContourConvex(approx):
return order(approx.reshape(4, 2).astype(np.float32))
return None # G5: bulunamazsa kullanıcıya sor
def scan(img, width=840):
quad = find_quad(img)
if quad is None:
return None, None
tl, tr, br, bl = quad
ratio = max(np.linalg.norm(bl - tl), np.linalg.norm(br - tr)) / max(np.linalg.norm(tr - tl), np.linalg.norm(br - bl))
W, H = width, int(width * ratio) # kenar uzunluklarından en-boy oranı
M = cv2.getPerspectiveTransform(quad, np.float32([[0, 0], [W - 1, 0], [W - 1, H - 1], [0, H - 1]]))
flat = cv2.warpPerspective(img, M, (W, H))
g = cv2.cvtColor(flat, cv2.COLOR_BGR2GRAY)
bw = cv2.adaptiveThreshold(g, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 25, 12) # gölgeye dayanıklı
return bw, quad
img = cv2.imread('girdi.png')
bw, quad = scan(img)
if bw is None:
print('belge bulunamadı')
cv2.imwrite('cikti.png', img)
else:
print('köşeler:', quad.astype(int).tolist(), 'çıktı:', bw.shape)
cv2.imwrite('cikti.png', bw)Teslimler
- 3. üniteden sonraÖneri ve test seti
Kapsam, gereksinimler (G1–G6) ve 20 fotoğraflık altın set: her fotoğrafta köşeler elle işaretlenmiş (JSON).
Eşikleme: sabit eşik, Otsu ve uyarlamalı eşik - 6. üniteden sonraÖn işleme ve kenarlar
onisle ve kenarlar fonksiyonları, --debug çıktıları ve birim testleri.
Morfolojik işlemler: aşındırma, genişletme, açma, kapama - 7. üniteden sonraKöşe bulma
kose_bul ve kose_sirala; altın sette G1 ölçümü ve başarısız örneklerin listesi.
Konturlar ve şekil öznitelikleri: say, ölç, sınıflandır - 9. üniteden sonraDüzleme ve tarama
duzle ve taranmis; G3 ve G4 ölçümleri, elle köşe girişi (G2).
Geometrik ve perspektif dönüşümler: döndür, ölçekle, düzle - 12. üniteden sonraDemo ve rapor
Komut satırı aracı, performans ölçümü (G5), test tablosu, 5 dakikalık demo ve kısa rapor.
Video ve arka plan çıkarma: hareket, leke, iz ve sayım