2016-06-12 13 views
10

Görüntülerin metin alanını python 2.7 ve opencv 2.4.9 kullanarak bulmak ve çevresinde dikdörtgen bir alan çizmek istiyorum. Aşağıdaki örnek resimde gösterildiği gibi.Python ve opencv kullanarak bir görüntüdeki metin alanını algıla

Görüntü işleme konusunda yeniyim, bu yüzden nasıl yapılacağı hakkında bir fikir sahibi olun.

building blueprint with labeled rooms

+0

Mümkünse, OpenCV 3.1 kullanın ve [sahne metin algılama] (https://github.com/Itseez/opencv_contrib/blob/master/modules/text/samples/textdetection.cpp) özelliğini kullanın. – flowfree

+0

@flowfree Projenin diğer bileşenleri olduğundan onu yükseltemiyorum. – User9412

+0

Görüntüdeki rengi aramak zorundasınız. Ancak görüntünüzde benzer renkte olması bu yüzden zor olabilir. İçinde sadece metin arıyorsanız 'tesseract' isimli bir kütüphane var –

cevap

27

bir resimdeki metni algılama konusunda gitmek için birden fazla yolu vardır.

Durumunuza da cevap verebileceğinden, this question here'a bakmanızı öneririm. Python'da bulunmasa da, kod C++ 'dan python'a kolayca çevrilebilir (Sadece API'ya bakın ve yöntemleri C++' dan python'a dönüştürmeyin, çok zor değil. Kendi kodum için kendi kodunu denediğimde kendim yaptım.) . Buradaki çözümler sizin durumunuz için çalışmayabilir, ancak bunları denemenizi öneririz.

Ben aşağıdaki işlemi yapacağını bu konuda gitmek için olsaydı:

Hazırlık resim: düzenlemek istediğiniz tüm resimlerinizin kabaca gerçek tasarım oluşur Sağladığınız biri gibiyse bir dizi gri renk ve metin her zaman siyahtır. Önce siyah olmayan (veya zaten beyaz olan) tüm içeriği beyazlatırdım. Bunu yapmak sadece soldaki siyah metni bırakacaktır.

# must import if working with opencv in python 
import numpy as np 
import cv2 

# removes pixels in image that are between the range of 
# [lower_val,upper_val] 
def remove_gray(img,lower_val,upper_val): 
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 
    lower_bound = np.array([0,0,lower_val]) 
    upper_bound = np.array([255,255,upper_val]) 
    mask = cv2.inRange(gray, lower_bound, upper_bound) 
    return cv2.bitwise_and(gray, gray, mask = mask) 

Artık sahip olduğunuz tek şey siyah metindir, hedef bu kutuları almaktır. Daha önce de belirtildiği gibi, bunun için farklı yollar vardır.

Kontur Genişliği (cc)

metin alanı bulmak için, tipik bir şekilde Transform Boris Epshtein Eyal Ofek ve Yonatan Wexler tarafından "Detecting Text in Natural Scenes with Stroke Width Transform " de gösterildiği gibi çizgi genişliği dönüşüm kullanarak metin bölgeleri bulabilirsiniz. Dürüst olmak gerekirse, eğer bu kadar hızlı ve güvenilir ise, bu yöntem benim aşağıdaki kodumdan daha verimli bir yöntemdir. Yine de, blueprint tasarımını kaldırmak için yukarıdaki kodu kullanabilir ve ,, swt algoritmasının genel performansına yardımcı olabilir. Kendi algoritmalarını uygulayan, ancak çok ham olduğu ve belgelerin eksik olduğu belirtildiği . Açıkçası, bu kütüphaneyi python ile kullanabilmek için bir sarıcıya ihtiyaç duyulacak ve şu anda teklif edilen resmi bir tane göremiyorum.

Bağladığım kitaplık CCV. Uygulamalarınızda kullanılması amaçlanan, algoritmaları yeniden oluşturmayacak bir kütüphanedir. Dolayısıyla bu, OP'nin yorumlarda belirtildiği gibi "İlk Prensipler" den istemek istediği aleyhine kullanılan bir araçtır. Yine de, algoritmayı kendiniz kodlamak istemiyorsanız bunu bilmek faydalıdır.


Ev demlendi Olmayan SWT Yöntem

her resim için meta veri varsa, her görüntüde etiketli kaç oda bildiren, bir xml dosyasında demek, o zaman bu xml dosyaya erişebilir görüntüde kaç tane etiket olduğuna dair verileri alın ve bu sayıyı num_of_labels numaralı değişkene koyun. Şimdi resminizi alın ve belirttiğiniz belirli bir hızda aşınan, her döngüdeki görüntüde dış konturları bularak ve num_of_labels ile aynı sayıda dış kontur oluşturduktan sonra döngüyü durduran bir süre boyunca geçirin. Sonra her kontürün sınırlayıcı kutusunu bulup bitirdiniz.Yukarıdaki metoda

# erodes image based on given kernel size (erosion = expands black areas) 
def erode(img, kern_size = 3): 
    retval, img = cv2.threshold(img, 254.0, 255.0, cv2.THRESH_BINARY) # threshold to deal with only black and white. 
    kern = np.ones((kern_size,kern_size),np.uint8) # make a kernel for erosion based on given kernel size. 
    eroded = cv2.erode(img, kern, 1) # erode your image to blobbify black areas 
    y,x = eroded.shape # get shape of image to make a white boarder around image of 1px, to avoid problems with find contours. 
    return cv2.rectangle(eroded, (0,0), (x,y), (255,255,255), 1) 

# finds contours of eroded image 
def prep(img, kern_size = 3):  
    img = erode(img, kern_size) 
    retval, img = cv2.threshold(img, 200.0, 255.0, cv2.THRESH_BINARY_INV) # invert colors for findContours 
    return cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # Find Contours of Image 

# given img & number of desired blobs, returns contours of blobs. 
def blobbify(img, num_of_labels, kern_size = 3, dilation_rate = 10): 
    prep_img, contours, hierarchy = prep(img.copy(), kern_size) # dilate img and check current contour count. 
    while len(contours) > num_of_labels: 
     kern_size += dilation_rate # add dilation_rate to kern_size to increase the blob. Remember kern_size must always be odd. 
     previous = (prep_img, contours, hierarchy) 
     processed_img, contours, hierarchy = prep(img.copy(), kern_size) # dilate img and check current contour count, again. 
    if len(contours) < num_of_labels: 
     return (processed_img, contours, hierarchy) 
    else: 
     return previous 

# finds bounding boxes of all contours 
def bounding_box(contours): 
    bBox = [] 
    for curve in contours: 
     box = cv2.boundingRect(curve) 
    bBox.append(box) 
    return bBox 

elde edilen kutular çevreleyici etiketlerin alanı olur, ve kutular orijinal görüntüye uygulanan bu, orjinal tasarımın bir parçasını içerebilir. Bundan kaçınmak için, yeni bulunan kutularınız aracılığıyla ilgi bölgeleri yapın ve beyaz alanı düzeltin. O roi'nin şeklini yeni kutun gibi sakla.

Belki fazla etiket görüntüde nasıl olacağını bilmenin hiçbir yolu yoktur. Eğer durum buysa, o zaman çantanıza en uygun olanı bulup istediğiniz lekeleri elde edene kadar erozyon değerleri ile oynamanızı tavsiye ederim.

Yoksa tasarımını çıkardıktan sonra, kalan içeriğine hatlarını bulmak deneyin ve birbirlerine olan mesafelerine dayalı bir dikdörtgenin içine sınırlayıcı kutuları birleştirebilirsiniz. Eğer kutuları bulundu sonra

, sadece orijinal görüntüye göre bu kutuları kullanın ve yapılacaktır. 3 sorunuza yorum belirtildiği gibi

, zaten sahne metin tespiti için bir araç vardır OpenCV


Sahne Metin Algılama Modülü OpenCV 3'te (metin algılama belge verilmez) Yaptığın anlıyorum sürümleri değiştirme yeteneğine sahip değil, aynı soruya sahip olanlar ve eski bir opencv sürümü ile sınırlı olmayanlar için, bunu sonuna eklemeye karar verdim. Sahne metni algılama için dokümantasyon basit bir google arama ile bulunabilir.

metin tespiti için opencv modülü ayrıca bir açık kaynak metin tanıma modülü tessaract uygulayan metin tanıma ile birlikte gelir. Tessaract'ın düşüşü ve bu nedenle opencv'nin sahne metni tanıma modülü, ticari uygulamalar kadar rafine edilmemesi ve kullanmak için çok zaman harcanmasıdır. Böylece, performansının düşmesi, ancak kullanımı ücretsizdir, bu yüzden metin tanıma da istiyorsanız, para ödemeden elimizden gelenin en iyisi.

Bağlantılar: Dürüst

, ben uygulanmasında detaylı bir şekilde sağlamak amacıyla hem opencv ve görüntü işleme tecrübe ve uzmanlığa sahip değil onların metin algılama modülü. SWT algoritması ile aynı. Son birkaç ay içinde bu konuya yeni girmiştim, ama daha fazla öğrenirken bu cevabı düzenleyeceğim.

+1

Bu konu hakkında okuyorum ve sizin için yararlı olabilecek SWT Python'u üzerinde birkaç uygulama var: [1] https://github.com/marrrcin/swt-python [2] https: // github.com/mypetyak/StrokeWidthTransform – m33n

İlgili konular