ठीक है, मैंने उपरोक्त समस्या को हल करने के लिए अपने प्रश्न पर खुद को कसरत करने का निर्णय लिया। मैं जो चाहता था वह OpenCV में KNearest या SVM सुविधाओं का उपयोग करके एक सरल ओसीआर लागू करना है। और नीचे मैंने क्या और कैसे किया। (यह केवल साधारण ओसीआर उद्देश्यों के लिए KNearest का उपयोग करना सीखने के लिए है)।
1) मेरा पहला प्रश्न letter_recognition.data फ़ाइल के बारे में था जो OpenCV नमूनों के साथ आता है। मैं जानना चाहता था कि उस फाइल के अंदर क्या है।
इसमें एक अक्षर होता है, साथ ही उस अक्षर की 16 विशेषताएं होती हैं।
और this SOF
मुझे इसे खोजने में मदद की। इन 16 विशेषताओं को कागज में समझाया गया है Letter Recognition Using Holland-Style Adaptive Classifiers
। (हालांकि मुझे इसकी कुछ विशेषताएं समझ में नहीं आईं)
2) चूंकि मैं जानता था, उन सभी विशेषताओं को समझे बिना, उस विधि को करना मुश्किल है। मैंने कुछ अन्य कागज़ात आज़माए, लेकिन सभी शुरुआत के लिए थोड़े मुश्किल थे।
So I just decided to take all the pixel values as my features.
(मैं सटीकता या प्रदर्शन के बारे में चिंतित नहीं था, मैं सिर्फ यह काम करना चाहता था, कम से कम सटीकता के साथ)
मैंने अपने प्रशिक्षण डेटा के लिए छवि नीचे दी है:
(मुझे पता है कि प्रशिक्षण डेटा की मात्रा कम है। लेकिन, चूंकि सभी पत्र एक ही फ़ॉन्ट और आकार के हैं, इसलिए मैंने इस पर प्रयास करने का फैसला किया है)।
प्रशिक्षण के लिए डेटा तैयार करने के लिए, मैंने OpenCV में एक छोटा कोड बनाया। यह निम्नलिखित बातें करता है:
- यह छवि को लोड करता है।
- अंकों का चयन करता है (स्पष्ट रूप से समोच्च खोजने और झूठे प्रतिबंधों से बचने के लिए पत्र और क्षेत्र की ऊंचाई पर बाधाओं को लागू करके)।
- बाउंडिंग आयत को एक अक्षर के चारों ओर खींचता है और प्रतीक्षा करता है
key press manually
। इस बार हम बॉक्स में अक्षर के अनुरूप अंक कुंजी दबाते हैं ।
- एक बार संबंधित अंक कुंजी दबाए जाने के बाद, यह इस बॉक्स को 10x10 पर आकार देता है और एक सरणी (यहां, नमूने) में 100 पिक्सेल मान बचाता है और इसी प्रकार मैन्युअल रूप से किसी अन्य सरणी (यहां, प्रतिक्रियाएं) में अंक दर्ज करता है।
- फिर अलग-अलग txt फ़ाइलों में दोनों सरणियों को सहेजें।
अंकों के मैनुअल वर्गीकरण के अंत में, ट्रेन डेटा (train.png) में सभी अंकों को स्वयं द्वारा लेबल किया जाता है, छवि नीचे दी गई होगी:
नीचे दिए गए कोड का उपयोग मैंने उपरोक्त उद्देश्य के लिए किया है (बेशक, इतना साफ नहीं):
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)
अब हम प्रशिक्षण और परीक्षण भाग में प्रवेश करते हैं।
परीक्षण भाग के लिए मैंने नीचे दी गई छवि का उपयोग किया, जिसमें उसी प्रकार के अक्षर हैं जिन्हें मैं प्रशिक्षित करता था।
प्रशिक्षण के लिए हम निम्नानुसार हैं :
- पहले से हमारे द्वारा सहेजे गए txt फ़ाइलों को लोड करें
- हमारे द्वारा उपयोग किए जा रहे क्लासिफायर का एक उदाहरण बनाएं (यहां, यह KNearest है)
- फिर हम डेटा को प्रशिक्षित करने के लिए KNearest.train फ़ंक्शन का उपयोग करते हैं
परीक्षण प्रयोजनों के लिए, हम निम्नानुसार हैं:
- हम परीक्षण के लिए उपयोग की जाने वाली छवि को लोड करते हैं
- पहले की तरह छवि को संसाधित करें और समोच्च विधियों का उपयोग करके प्रत्येक अंक निकालें
- इसके लिए बाउंडिंग बॉक्स ड्रा करें, फिर 10x10 का आकार बदलें, और अपने पिक्सेल मूल्यों को पहले से किए गए सरणी में स्टोर करें।
- उसके बाद हम दिए गए आइटम को खोजने के लिए KNearest.find_nearest () फ़ंक्शन का उपयोग करते हैं। (यदि भाग्यशाली है, तो यह सही अंक को पहचानता है।)
मैंने नीचे दिए गए एकल कोड में अंतिम दो चरण (प्रशिक्षण और परीक्षण) शामिल किए हैं:
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)
और यह काम किया, नीचे मुझे जो परिणाम मिला है:
यहां इसने 100% सटीकता के साथ काम किया। मुझे लगता है कि यह इसलिए है क्योंकि सभी अंक समान और समान आकार के हैं।
लेकिन किसी भी तरह, यह शुरुआती लोगों के लिए जाने के लिए एक अच्छी शुरुआत है (मुझे आशा है कि)।