Yukarıdaki sorunu çözmek için soruma kendim egzersiz yapmaya karar verdim. İstediğim, OpenCV'deki KNearest veya SVM özelliklerini kullanarak basit bir OCR uygulamak. Ve aşağıda ne yaptığımı ve nasıl olduğunu. (sadece KNearest'in basit OCR amaçları için nasıl kullanılacağını öğrenmek içindir).
1) İlk sorum OpenCV örnekleri ile gelen letter_recognition.data dosyası hakkındaydı. O dosyanın içinde ne olduğunu bilmek istedim.
Bir mektubu ve o mektubun 16 özelliğini içerir.
Ve this SOF
onu bulmama yardım etti. Bu 16 özellik makalede açıklanmıştır Letter Recognition Using Holland-Style Adaptive Classifiers
. (Sonunda bazı özellikleri anlamadığım halde)
2) Tüm bu özellikleri anlamadan bildiğim için, bu yöntemi yapmak zordur. Başka makaleler denedim, ama yeni başlayanlar için hepsi biraz zordu.
So I just decided to take all the pixel values as my features.
(Doğruluk veya performans konusunda endişelenmedim, sadece en azından en az doğrulukla çalışmasını istedim)
Eğitim verilerim için aşağıdaki görüntüyü aldım:
(Antrenman verilerinin daha az olduğunu biliyorum. Ancak, tüm harfler aynı yazı tipi ve boyutta olduğu için bunu denemeye karar verdim).
Verileri eğitime hazırlamak için OpenCV'de küçük bir kod hazırladım. Aşağıdaki şeyleri yapar:
- Görüntüyü yükler.
- Rakamları seçer (açıkçası yanlış tespitleri önlemek için kontur bulma ve harflerin alanı ve yüksekliği üzerinde kısıtlamalar uygulayarak).
- Sınırlayıcı dikdörtgeni bir harfin çevresine çizer ve bekleyin
key press manually
. Bu sefer kutudaki harfe karşılık gelen rakam tuşuna basıyoruz .
- Karşılık gelen sayı tuşuna basıldığında, bu kutuyu 10x10 değerine yeniden boyutlandırır ve bir diziye (burada, örnekler) 100 piksel değeri ve başka bir diziye karşılık gelen manuel olarak girilen basamağı (burada yanıtlar) kaydeder.
- Ardından her iki diziyi ayrı txt dosyalarına kaydedin.
Rakamların manuel olarak sınıflandırılmasının sonunda, tren verilerindeki (train.png) tüm rakamlar kendimiz manuel olarak etiketlenir, görüntü aşağıdaki gibi görünecektir:
Aşağıda yukarıdaki amaç için kullandığım kod (tabii ki, çok temiz değil):
import sys
import numpy as np
import cv2
im = cv2.imread('pitrain.png')
im3 = im.copy()
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)
thresh = cv2.adaptiveThreshold(blur,255,1,1,11,2)
################# Now finding Contours ###################
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
samples = np.empty((0,100))
responses = []
keys = [i for i in range(48,58)]
for cnt in contours:
if cv2.contourArea(cnt)>50:
[x,y,w,h] = cv2.boundingRect(cnt)
if h>28:
cv2.rectangle(im,(x,y),(x+w,y+h),(0,0,255),2)
roi = thresh[y:y+h,x:x+w]
roismall = cv2.resize(roi,(10,10))
cv2.imshow('norm',im)
key = cv2.waitKey(0)
if key == 27: # (escape to quit)
sys.exit()
elif key in keys:
responses.append(int(chr(key)))
sample = roismall.reshape((1,100))
samples = np.append(samples,sample,0)
responses = np.array(responses,np.float32)
responses = responses.reshape((responses.size,1))
print "training complete"
np.savetxt('generalsamples.data',samples)
np.savetxt('generalresponses.data',responses)
Şimdi eğitim ve test bölümüne giriyoruz.
Test bölümü için ben eğitmek için kullandığım aynı tür harfleri olan görüntü altında kullandım.
Eğitim için aşağıdakileri yapıyoruz :
- Daha önce kaydettiğimiz txt dosyalarını yükleyin
- kullandığımız bir sınıflandırıcı örneği oluşturun (burada, KNearest)
- Sonra verileri eğitmek için KNearest.train işlevini kullanıyoruz
Test amaçlı olarak aşağıdakileri yapıyoruz:
- Test için kullanılan resmi yüklüyoruz
- görüntüyü daha önceki gibi işleyin ve her basamağı kontur yöntemlerini kullanarak çıkarın
- Bunun için sınırlayıcı kutu çizin, ardından 10x10 değerine yeniden boyutlandırın ve piksel değerlerini daha önce olduğu gibi bir dizide saklayın.
- Sonra verdiğimiz öğeye en yakın öğeyi bulmak için KNearest.find_nearest () işlevini kullanırız. (Şanslıysa, doğru rakamı tanır.)
Son iki adımı (eğitim ve test) aşağıdaki tek koda ekledim:
import cv2
import numpy as np
####### training part ###############
samples = np.loadtxt('generalsamples.data',np.float32)
responses = np.loadtxt('generalresponses.data',np.float32)
responses = responses.reshape((responses.size,1))
model = cv2.KNearest()
model.train(samples,responses)
############################# testing part #########################
im = cv2.imread('pi.png')
out = np.zeros(im.shape,np.uint8)
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,1,1,11,2)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt)>50:
[x,y,w,h] = cv2.boundingRect(cnt)
if h>28:
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
roi = thresh[y:y+h,x:x+w]
roismall = cv2.resize(roi,(10,10))
roismall = roismall.reshape((1,100))
roismall = np.float32(roismall)
retval, results, neigh_resp, dists = model.find_nearest(roismall, k = 1)
string = str(int((results[0][0])))
cv2.putText(out,string,(x,y+h),0,1,(0,255,0))
cv2.imshow('im',im)
cv2.imshow('out',out)
cv2.waitKey(0)
Ve işe yaradı, aşağıda elde ettiğim sonuç:
Burada% 100 doğrulukla çalıştı. Bunun tüm basamakların aynı tür ve aynı boyutta olması nedeniyle olduğunu düşünüyorum.
Ama her şekilde, bu yeni başlayanlar için gitmek için iyi bir başlangıç (umarım).