İçeriğe geç
IBAN Aracı
Teknik

OCR ile IBAN Okuma: 0/O, 1/I ve 8/B Karışıklıkları

OCR, IBAN'daki sıfırı O, biri I, sekizi B okuyabilir. Kontrol haneleri tek karakterlik hataları her zaman yakalar; birden fazla hatada ise son söz görseldeki numaradadır.

IBAN Aracı Editör Ekibi5 dk okuma

Masada basılı bir belge ve tükenmez kalem
Görsel: kaynak ve lisans bilgisi

Bir dekont fotoğrafından ya da ekran görüntüsünden IBAN okuyan OCR (optik karakter tanıma) yazılımı, en çok birbirine benzeyen karakterlerde hata yapar: sıfır ile O harfi, bir ile I ya da küçük l, beş ile S, sekiz ile B. İyi haber, IBAN'ın kontrol haneleri bu hataların çok büyük kısmını yakalayacak şekilde tasarlanmış. Kötü haber, "yakalamak" ile "düzeltmek" aynı şey değil. Asıl mesele, MOD 97'nin neyi kesin yakaladığını, neyi kaçırabileceğini bilmek ve düzeltme önerisini kullanıcıyı yanıltmadan sunmak.

OCR neden bu karakterleri karıştırır?

OCR motoru pikselleri harf şekilleriyle eşleştirir. Birçok yazı tipinde büyük O ile sıfır yalnızca genişlik farkıyla ayrılır; I, l ve 1 ise bazı yazı tiplerinde neredeyse tek bir dikey çizgidir. Düşük çözünürlüklü bir fotoğrafta, bulanıklık ya da JPEG sıkıştırması bu küçük farkları siler. S ile 5, B ile 8, Z ile 2 ve G ile 6 da köşelerin yuvarlaklığı kaybolduğunda benzeşir. Aynı sorun yalnızca harf-rakam arasında değil, rakamlar arasında da görülür: kötü ışıkta 3 ile 8 veya 5 ile 6 karışabilir.

Bu iki tür hata farklı ele alınır. Türkiye IBAN'ında TR ön ekinden sonra pratikte yalnızca rakam bulunur. Dolayısıyla OCR 26 karakterlik bir TR IBAN'ının gövdesinde O harfi okuduysa, orada bir hata olduğu kesindir ve en olası karşılık sıfırdır. Rakam-rakam karışıklığında ise okunan değer biçim açısından kusursuz görünür. TR14 0001 0050 0123 4567 3901 23 gözle bakıldığında hiçbir şeyi ele vermez; sekizin üç okunduğunu yalnızca kontrol haneleri gösterir.

MOD 97 neyi kesin yakalar, neyi kaçırabilir?

Kontrol hanelerinin hesaplanma yöntemini IBAN MOD 97 nedir? sayfasında anlattık. OCR açısından önemli olan şu: rakam bölümünde tek bir hane yanlış okunursa, IBAN'dan türeyen dev sayı o hanenin basamak değeri kadar değişir. Bu fark, 1 ile 9 arasında bir sayının 10'un bir kuvvetiyle çarpımıdır. 97 asal bir sayıdır; ne 10'un kuvvetlerini ne de 1-9 arasındaki bir sayıyı böler. Bu yüzden fark hiçbir zaman 97'nin katı olamaz; kalan mutlaka değişir. Yani tek hanelik bir okuma hatası her zaman yakalanır. Yan yana iki rakamın yer değiştirmesi için de aynı mantık geçerlidir.

Bunu kendi örneğimizde de denedik. TR140001005001234567890123 üzerinde, kontrol haneleri dahil 24 rakamın her birini diğer dokuz rakamla değiştirdiğimiz 216 varyasyonun hiçbiri MOD 97'den geçmedi; yan yana rakamların yer değiştirdiği 19 varyasyon da reddedildi. İki hanenin aynı anda yanlış okunduğu durumda tablo değişiyor. Aynı IBAN için olası 22.356 çift hata kombinasyonunun 203'ü, yani yaklaşık yüzde 0,9'u, tesadüfen geçerli bir IBAN üretti. Bu oran kuramsal beklenti olan yaklaşık 97'de 1'e yakın.

Pratik anlamı: Kötü bir fotoğrafta birden fazla karakter yanlış okunduysa, sonucun MOD 97'den geçmesi okumanın doğru olduğunu kanıtlamaz. Geçerli çıkan IBAN'ı da görseldeki numarayla karakter karakter karşılaştırın. Biçimsel geçerlilik ayrıca hesabın kime ait olduğunu hiç göstermez.

Düzeltme önerisi üretmek: güvenli bir yaklaşım

Kendi uygulamanızda OCR kullanıyorsanız, geçersiz bir sonucu doğrudan reddetmek yerine düzeltme önerisi sunmak kullanıcıya zaman kazandırır. Ama öneriyi sessizce uygulamak tehlikelidir. Aşağıdaki fonksiyon iki aşamalı çalışıyor ve sonucu hiçbir zaman kendisi seçmiyor:

javascript
// TR IBAN'ında ülke kodundan sonra yalnızca rakam beklenir.
const HARF_RAKAM = { O: "0", Q: "0", D: "0", I: "1", L: "1", S: "5", B: "8", Z: "2", G: "6" };
// OCR'ın sık karıştırdığı rakam çiftleri (görsel benzerlik).
const BENZER_RAKAM = { 0: "86", 1: "7", 3: "8", 5: "6", 6: "58", 7: "1", 8: "306" };

function mod97(iban) {
  let r = 0;
  for (const ch of iban.slice(4) + iban.slice(0, 4)) {
    const v = parseInt(ch, 36);
    r = (r * (v < 10 ? 10 : 100) + v) % 97;
  }
  return r;
}

function ocrTrIbanAdaylari(okunan) {
  const temiz = okunan.toUpperCase().replace(/[\s.\-]/g, "");
  if (!temiz.startsWith("TR")) return { durum: "TR değil", adaylar: [] };
  const govde = [...temiz.slice(2)].map((c) => HARF_RAKAM[c] ?? c).join("");
  if (!/^\d{24}$/.test(govde)) return { durum: "okunamadı", adaylar: [] };
  const iban = "TR" + govde;
  if (mod97(iban) === 1) {
    return { durum: iban === temiz ? "geçerli" : "harf düzeltmesiyle geçerli", adaylar: [iban] };
  }
  // Tek karakterlik rakam karışıklıklarını dene; sonucu asla otomatik seçme.
  const adaylar = [];
  for (let i = 2; i < iban.length; i++) {
    for (const alt of BENZER_RAKAM[iban[i]] ?? "") {
      const aday = iban.slice(0, i) + alt + iban.slice(i + 1);
      if (mod97(aday) === 1) adaylar.push(aday);
    }
  }
  return { durum: "kontrol hanesi tutmuyor", adaylar };
}

İlk aşama, TR gövdesindeki harfleri en olası rakama çevirir. Bu dönüşüm yalnızca Türkiye gibi hesap bölümünün pratikte tamamen rakam olduğu ülkeler için savunulabilir. İngiltere IBAN'ında banka kodu harftir; aynı tabloyu orada uygulamak doğru bir IBAN'ı bozar. İkinci aşama, dönüşümden sonra da MOD 97 tutmuyorsa, görsel olarak karışabilen rakamları her konumda tek tek deneyip geçerli sonuç verenleri listeler.

Node.js üzerinde denediğimizde TR14 OOO1 OO5O O123 4567 89O1 23 ve O, I, S, B karışık okunmuş bir başka kopya "harf düzeltmesiyle geçerli" sonucunu ve doğru IBAN'ı verdi. Sekizin üç okunduğu TR14 0001 0050 0123 4567 3901 23 için tek bir aday çıktı ve bu aday orijinal IBAN'dı. Kontrol hanesi bozuk TR150001005001234567890123 için ise hiç aday çıkmadı; fonksiyon uydurma bir düzeltme üretmek yerine boş liste döndürdü. Adaylar birden fazlaysa hepsini gösterin; tek aday varsa bile kullanıcıya görselle karşılaştırmasını söyleyin.

Benzer tablo elle yazım için de işe yarar. Klavyede O ile sıfırın karıştırıldığı durumlarda IBAN yazım kontrolü aracı şüpheli karakterleri işaretler, IBAN hata bulucu ise hatanın türünü açıklar.

Sitedeki dekont aracı nasıl çalışıyor?

Dekonttan IBAN bulma aracı, açık kaynak Tesseract motorunun WebAssembly sürümünü paketleyen tesseract.js kütüphanesini kullanıyor. Görsel tarayıcınızda işleniyor; fotoğraf ya da okunan metin sunucuya gönderilmiyor. Okunan metinden IBAN'a benzeyen diziler ayıklanıyor ve her biri sitedeki diğer araçlarla aynı doğrulamadan geçiyor: uzunluk, karakter yapısı ve MOD 97.

Araç düzeltme yapmıyor. Gövdesinde O harfi okunmuş bir IBAN'ı bulur ve "geçersiz" olarak gösterir, ama sıfıra çevirip "geçerli" demez. Bu yaklaşımın iki iyi gerekçesi var: düzeltilmiş bir sonucun kaynağa sadık olduğunu görsel karşılaştırma olmadan bilemeyiz ve geçerli görünen yanlış bir IBAN, geçersiz görünen bir IBAN'dan daha tehlikelidir. Bir sınırlamayı da bilin: kontrol hanelerinden biri harf okunursa (örneğin TR14 yerine TRI4), metin IBAN kalıbına uymadığı için araç o satırı hiç yakalamayabilir. Böyle durumlarda "okunan ham metni göster" seçeneğiyle metni açın, numarayı kopyalayıp düzeltin ve metinden IBAN bulma aracına yapıştırın.

tesseract.js belgelerinde de belirtildiği gibi kütüphane PDF dosyalarını doğrudan okumuyor. PDF dekontunuz varsa IBAN'ın göründüğü bölümün ekran görüntüsünü alıp o görüntüyü yükleyin.

Daha iyi okuma için görsel ipuçları

Tesseract'ın kalite belgeleri, motorun taranmış sayfalarda en az 300 DPI civarında çözünürlükte iyi çalıştığını, eğik satırların satır ayrıştırmasını belirgin biçimde bozduğunu ve düzensiz arka plan aydınlatmasının siyah-beyaza çevirme adımını zorlaştırdığını anlatıyor. Telefon fotoğrafı için bunun karşılığı şu:

  • Kırpın. Görseli yalnızca IBAN'ın bulunduğu bölgeye yakın kırpmak hem harflerin piksel boyutunu büyütür hem de tutar, tarih gibi başka rakamların karışmasını azaltır. Etrafta birkaç milimetrelik boşluk bırakın; belgeler metnin kenara yapışmasının da sorun çıkardığını belirtiyor.
  • Düz tutun. Kâğıdı masaya yatırıp telefonu tam üstünden tutun. Açılı çekim satırları eğer.
  • Işığı eşitleyin. Yarısı gölgede kalan bir dekont, bir tarafta harflerin kalınlaşmasına diğer tarafta silinmesine yol açar. Parlak kâğıtta flaş yansıması da karakterleri yutabilir.
  • Mümkünse ekran görüntüsü kullanın. Banka uygulamasındaki IBAN'ın ekran görüntüsü, başka bir ekranın fotoğrafından neredeyse her zaman daha temizdir.

Görseli paylaşmadan önce de düşünün: bir dekont ya da ekran görüntüsü IBAN'ın yanında ad, tutar ve bakiye gibi bilgiler taşıyabilir. Bu riskleri ekran görüntüsüyle IBAN paylaşmak rehberinde ele aldık. Formunuzda OCR sonucunu kullanıcıya düzenlenebilir bir alanda gösterecekseniz, alanın yapıştırma ve hata mesajı davranışını formlarda IBAN alanı tasarımı yazısında ayrıntılı ele aldık.

Kaynaklar

  1. Tesseract belgeleri: Improving the quality of the output
  2. tesseract.js (GitHub)
  3. Swift: IBAN (ISO 13616) ve IBAN Registry

Yazıların nasıl hazırlanıp güncellendiğini metodoloji sayfasında anlatıyoruz. Hata gördüyseniz bize yazın.

Sık sorulan sorular

Büyük olasılıkla, ama kesin değil. Tek karakterlik okuma hataları MOD 97'ye her zaman takılır. Birden fazla karakter yanlış okunduğunda sonuç tesadüfen geçerli çıkabilir; bu yüzden numarayı görselle karşılaştırın. Geçerli sonuç hesap sahibini de doğrulamaz.

İlgili yazılar

İlgili araçlar