OCR için temizlik resmi


9

OCR için görüntüleri temizlemeye çalışıyorum: (satırlar)

resim açıklamasını buraya girin

Bazen görüntüyü daha fazla işlemek için bu satırları kaldırmam gerekiyor ve oldukça yakınlaşıyorum ama çoğu zaman eşik metinden çok fazla zaman alıyor:

    copy = img.copy()
    blur = cv2.GaussianBlur(copy, (9,9), 0)
    thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,30)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
    dilate = cv2.dilate(thresh, kernel, iterations=2)

    cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]

    for c in cnts:
        area = cv2.contourArea(c)
        if area > 300:
            x,y,w,h = cv2.boundingRect(c)
            cv2.rectangle(copy, (x, y), (x + w, y + h), (36,255,12), 3)

Düzenleme: Ayrıca, yazı tipi değiştiğinde sabit sayılar kullanmak çalışmaz. Bunu yapmanın genel bir yolu var mı?


2
Bu satırlardan bazıları veya parçaları, yasal metinle aynı özelliklere sahiptir ve geçerli metni bozmadan onlardan kurtulmak zor olacaktır. Bu geçerliyse, karakterlerden daha uzun ve biraz izole oldukları gerçeğine odaklanabilirsiniz. Yani ilk adım karakterlerin büyüklüğünü ve yakınlığını tahmin etmek olabilir.
Yves Daoust

@Yvesdaoust Karakterlerin yakınlığını nasıl bulabilirim? (yalnızca boyuta göre filtreleme çoğu zaman karakterlerle karıştığından)
K41F4r

1
Her damla için en yakın komşusuna olan mesafeyi bulabilirsiniz. Sonra mesafelerin histogram analizi ile, "yakın" ve "ayrı" (dağılım modu gibi bir şey) veya "çevrili" ve "izole" arasında bir eşik bulacaksınız.
Yves Daoust

Birbirine yakın çok sayıda küçük çizgi olması durumunda, en yakın komşusu diğer küçük çizgi olmaz mı? Diğer tüm damlalara ortalama mesafeyi hesaplamak çok maliyetli olur mu?
K41F4r

"En yakın komşuları diğer küçük çizgi olmaz mıydı?": İyi itiraz, Onurun. Aslında, bir sürü yakın kısa segment, yasal olmayan metinden farklı değildir, ancak tamamen olası olmayan bir düzenlemede. Kırık çizgilerin parçalarını yeniden gruplamanız gerekebilir. Herkese ortalama mesafenin sizi kurtaracağından emin değilim.
Yves Daoust

Yanıtlar:


14

İşte bir fikir. Bu sorunu birkaç adıma ayırıyoruz:

  1. Ortalama dikdörtgen kontur alanını belirleyin. Daha sonra konturları buluruz ve konturun sınırlayıcı dikdörtgen alanını kullanarak filtreleriz . Bunu yapmamızın nedeni, tipik bir karakterin sadece o kadar büyük olacağı, büyük gürültü ise daha büyük bir dikdörtgen alana yayılacağı gözlemidir. Daha sonra ortalama alanı belirleriz.

  2. Büyük aykırı konturları çıkarın. Konturları tekrar tekrarlıyoruz ve 5xkonturu doldurarak ortalama kontur alanından daha büyükse büyük konturları çıkarıyoruz. Sabit bir eşik alanı kullanmak yerine, daha fazla sağlamlık için bu dinamik eşiği kullanıyoruz.

  3. Karakterleri bağlamak için dikey bir çekirdekle genişletin . Fikir, karakterlerin sütunlar halinde hizalandığı gözleminden yararlanmaktır. Dikey bir çekirdekle dilatasyon yaparak metni birleştiririz, böylece gürültü bu kombine konturda yer almaz.

  4. Küçük gürültüyü giderin . Saklanacak metin bağlandığına göre, konturları buluyoruz ve 4xortalama kontur alanından daha küçük konturları kaldırıyoruz .

  5. Bitsel ve görüntüyü yeniden oluşturmak için . Sadece maskemizi korumak için konturlar istediğimizden, bitsel olarak ve metni korumak ve sonucumuzu almak için.


İşte sürecin bir görselleştirmesi:

Biz Otsu 'eşik ikili bir görüntü elde etmek için daha sonra hatlarını bulmak ortalama dikdörtgen kontur alanı belirlemek için. Buradan konturları doldurarak yeşil renkle vurgulanmış büyük aykırı konturları kaldırıyoruz

resim açıklamasını buraya girin resim açıklamasını buraya girin

Daha sonra karakterleri bağlamak için dikey bir çekirdek ve dilate yapıyoruz . Bu adım, gürültüyü tek tek lekelere ayırmak için istenen tüm metni bağlar.

resim açıklamasını buraya girin

Şimdi küçük gürültüyü gidermek için kontur alanını kullanarak konturlar ve filtreler buluyoruz

resim açıklamasını buraya girin

İşte yeşil ile vurgulanan tüm çıkarılan gürültü parçacıkları

resim açıklamasını buraya girin

Sonuç

resim açıklamasını buraya girin

kod

import cv2

# Load image, grayscale, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Determine average contour area
average_area = [] 
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    average_area.append(area)

average = sum(average_area) / len(average_area)

# Remove large lines if contour area is 5x bigger then average contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = w * h
    if area > average * 5:  
        cv2.drawContours(thresh, [c], -1, (0,0,0), -1)

# Dilate with vertical kernel to connect characters
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,5))
dilate = cv2.dilate(thresh, kernel, iterations=3)

# Remove small noise if contour area is smaller than 4x average
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < average * 4:
        cv2.drawContours(dilate, [c], -1, (0,0,0), -1)

# Bitwise mask with input image
result = cv2.bitwise_and(image, image, mask=dilate)
result[dilate==0] = (255,255,255)

cv2.imshow('result', result)
cv2.imshow('dilate', dilate)
cv2.imshow('thresh', thresh)
cv2.waitKey()

Not: Geleneksel görüntü işleme eşikleme, morfolojik işlemler ve kontur filtreleme (kontur yaklaşımı, alan, en boy oranı veya damla algılama) ile sınırlıdır. Giriş görüntüleri karakter metni boyutuna göre değişebileceğinden, tekil bir çözüm bulmak oldukça zordur. Dinamik bir çözüm için kendi sınıflandırıcıyı makine / derin öğrenme ile eğitmek isteyebilirsiniz.


1
Daha büyük bir yazı tipi olması durumunda bu metin de silinmez mi?
K41F4r

Evet olabilir, bu nedenle eşik alanı değerini ayarlamanız gerekir. Daha dinamik bir yaklaşım için bir fikir ortalama karakter alanını belirlemek ve bunu eşik olarak kullanmaktır
nathancy

Örneğe çok özel görünmektedir, ortalama alanı kullanmak, metni
K41F4r

Yayına ekleyebileceğiniz başka bir örnek giriş resminiz var mı?
nathancy

1
Geleneksel görüntü işleme tekniklerini kullanarak her durumda çalışan bir çözüm bulmak oldukça zordur. Derin öğrenmeyi kullanarak kendi sınıflandırıcınızı eğitmek isteyebilirsiniz. İyi şanslar!
nathancy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.