2010-10-14 13 views
7

मैं दो अलग-अलग स्रोतों से कुछ पाठ ओसीआर कर रहा हूं। वे प्रत्येक अलग-अलग जगहों पर गलतियां कर सकते हैं, जहां वे अक्षरों के एक पत्र/समूह को पहचान नहीं पाएंगे। अगर वे कुछ पहचान नहीं पाते हैं, तो इसे एक के साथ बदल दिया गया है? उदाहरण के लिए, यदि शब्द Roflcopter है, तो एक स्रोत Ro?copter लौटा सकता है, जबकि दूसरा, Roflcop?er। मुझे एक ऐसा फ़ंक्शन चाहिए जो दो मैचों के समतुल्य हो, चाहे ? एस के लिए अनुमति दे। उदाहरण:दो वाइल्डकार्ड तारों से मेल खाने के लिए सुरुचिपूर्ण तरीका

>>> def match(tn1, tn2): 
    tn1re = tn1.replace("?", ".{0,4}") 
    tn2re = tn2.replace("?", ".{0,4}") 

    return bool(re.match(tn1re, tn2) or re.match(tn2re, tn1)) 

>>> match("Roflcopter", "Roflcop?er") 
True 
>>> match("R??lcopter", "Roflcopter") 
True 

विभिन्न स्थानों में लेकिन यह वे दोनों जब काम नहीं करता है रों:

match("Ro?copter", "Roflcop?er") --> True 
match("Ro?copter", "Roflcopter") --> True 
match("Roflcopter", "Roflcop?er") --> True 
match("Ro?co?er", "Roflcop?er") --> True 

अब तक मैं एक ओसीआर एक आदर्श एक के साथ नियमित अभिव्यक्ति का उपयोग करके मिलान कर सकते हैं?

>>> match("R??lcopter", "Roflcop?er") 
False 
+0

कृपया एक टैग के रूप में पायथन जोड़ें। आप किस संस्करण का उपयोग कर रहे हैं, बीटीडब्ल्यू? –

+0

संस्करण 2.5.2 अतिरिक्त व्हाइटस्पेस – Claudiu

उत्तर

2

इस विचार के लिए हामिश ग्रुबिजान को धन्यवाद। प्रत्येक ? मेरे ocr'd नामों में 0 से 3 अक्षरों से कहीं भी हो सकता है।

>>> list(expQuestions("?flcopt?")) 
['flcopt', '[email protected]', '[email protected]@', '[email protected]@@', '@flcopt', '@[email protected]', '@[email protected]@', '@[email protected]@@', '@@flcopt', '@@[email protected]', '@@[email protected]@', '@@[email protected]@@', '@@@flcopt', '@@@[email protected]', '@@@[email protected]@', '@@@[email protected]@@'] 

तो मैं दोनों का विस्तार और उसकी मिलान समारोह है, जो मैं matchats कहा जाता है का उपयोग करें:: मुझे क्या संभव विस्तार की एक सूची के लिए प्रत्येक स्ट्रिंग का विस्तार है

रूप
def matchOCR(l, r): 
    for expl in expQuestions(l): 
     for expr in expQuestions(r): 
      if matchats(expl, expr): 
       return True 
    return False 

वर्क्स वांछित:

>>> matchOCR("Ro?co?er", "?flcopt?") 
True 
>>> matchOCR("Ro?co?er", "?flcopt?z") 
False 
>>> matchOCR("Ro?co?er", "?flc?pt?") 
True 
>>> matchOCR("Ro?co?e?", "?flc?pt?") 
True 


मिलान समारोह:

def matchats(l, r): 
    """Match two strings with @ representing exactly 1 char""" 
    if len(l) != len(r): return False 
    for i, c1 in enumerate(l): 
     c2 = r[i] 
     if c1 == "@" or c2 == "@": continue 
     if c1 != c2: return False 
    return True 

और विस्तार समारोह, जहां cartesian_product करता है सिर्फ इतना है कि:

def expQuestions(s): 
    """For OCR w/ a questionmark in them, expand questions with 
    @s for all possibilities""" 
    numqs = s.count("?") 

    blah = list(s) 
    for expqs in cartesian_product([(0,1,2,3)]*numqs): 
     newblah = blah[:] 
     qi = 0 
     for i,c in enumerate(newblah): 
      if newblah[i] == '?': 
       newblah[i] = '@'*expqs[qi] 
       qi += 1 
     yield "".join(newblah) 
+0

कूल, एक त्वरित नज़र में - मेरा एकमात्र मुद्दा परिवर्तनीय नामों के साथ है :) ओह, आपको भी चिंता करने की ज़रूरत है? और @ पाठ का वैध हिस्सा होने के नाते और विशेष प्रतीक नहीं। इसके बजाय @ मैं कुछ ऐसा चुनूंगा जो इसके बजाय गैर-मुद्रित है। नवीनतम पायथन यूनिकोड है, इसलिए आपके पास अजीब पात्रों के लिए पर्याप्त जगह है। '>> weird_ch = chr (255) >>> weird_ch '\ xff'' –

+0

हाँ मैंने उन मानों को चुना है? और @ आमतौर पर तारों में दिखाई नहीं देते हैं। और हाँ, मैं नहीं जानता था कि उन चरों को क्या कहना है और मैं आलसी था ... बीमार शायद 2 महीनों में इसे डिबग कर रहा है। कम से कम 'newblah' वर्णनात्मक है कि यह एक नया' blah' है ... तरह .. – Claudiu

+0

गौड, मैं एक ऐसे लड़के के साथ काम करता हूं जो आपके जैसा ही है। लड़का मुझे इससे नफरत करता है जब उसकी बग इसे मेरी प्लेट में बनाती है। :) मजेदार बात यह है कि वह इसे लिखने के बाद अपने कोड महीने पढ़ सकता है। उत्कृष्ट स्मृति होने के कारण मिश्रित आशीर्वाद हो सकता है। –

2

ठीक है, एक समय तक? एक चरित्र के अनुरूप है, तो मैं एक कलाकार और एक कॉम्पैक्ट पर्याप्त विधि का सुझाव दे सकता हूं।

def match(str1, str2): 
    if len(str1) != len(str2): return False 
    for index, ch1 in enumerate(str1): 
     ch2 = str2[index] 
     if ch1 == '?' or ch2 == '?': continue 
     if ch1 != ch2: return False 
    return True 

>>> ================================ RESTART ================================ 
>>> 
>>> match("Roflcopter", "Roflcop?er") 
True 
>>> match("R??lcopter", "Roflcopter") 
True 
>>> 
>>> match("R??lcopter", "Roflcop?er") 
True 
>>> 

संपादित करें: पार्ट बी), मस्तिष्क गोज़ मुक्त अब।

def sets_match(set1, set2): 
    return any(match(str1, str2) for str1 in set1 for str2 in set2) 

>>> ================================ RESTART ================================ 
>>> 
>>> s1 = set(['a?', 'fg']) 
>>> s2 = set(['?x']) 
>>> sets_match(s1, s2) # a? = x? 
True 
>>> 
+0

के साथ? अक्सर एक चरित्र होता है, लेकिन यह 2 या 3 वर्णों के साथ-साथ – Claudiu

+0

@ क्लाउडियो भी हो सकता है, उस मामले में मैं ए) पहले स्ट्रिंग को संभव स्ट्रिंग्स (संभावनाएं सीमित हैं) के सेट में विस्तारित करता हूं, और बी) फिर दो सेटों को छेड़छाड़ करते हैं उम्मीदवारों और खालीपन की जांच ('isdisjoint')। भाग बी) छोटा है, मैं इसके लिए कोड जोड़ सकता हूं। किसी कारण से मैं भाग ए पर फंस गया हूं)। लेकिन, जोश ने एक ऐसी विधि का सुझाव दिया है जो ओसीआर 100% पर भरोसा नहीं करेगा, जो आवश्यक हो सकता है। –

+0

हम्म भाग ए यह संभव नहीं है। आइए केवल लोअरकेस अक्षर कहें, फिर? उपज (26 + 26^2 + 26^3) संभावनाएं, दो? वह^2 उत्पन्न करेगा, जो पहले से ही 334 मिलियन है। – Claudiu

1

Levenshtein distance का उपयोग करना उपयोगी हो सकता है। यह एक मूल्य देगा कि स्ट्रिंग एक दूसरे के समान कैसे हैं। यह काम करेगा अगर वे अलग-अलग लंबाई भी हैं। लिंक शुरू करने के लिए आपको कुछ psuedocode है।

आप कुछ इस तरह से खत्म करेंगे:

>>> match("Roflcopter", "Roflcop?er") 
1 
>>> match("R??lcopter", "Roflcopter") 
2 
>>> match("R?lcopter", "Roflcop?er") 
3 

तो तुम एक अधिकतम सीमा जिसके नीचे आप कहते हैं कि वे मेल खा सकता है हो सकता था।

+2

ओसीआर ने नहीं रखा है तो यह एक अच्छा तरीका है? जहां यह होना चाहिए। हालांकि, यह विधि आपको यह भी बताएगी कि तार 'ए' और 'डब्ल्यू' एक छोटी दूरी के अलावा हैं, लेकिन ओसीआर दो अलग-अलग नहीं बता सकता है। सादे दहलीज की तुलना में कुछ स्मार्ट मीट्रिक की आवश्यकता है। –

+0

@ हैमिश ग्रुबिजन: मैं सहमत हूं। शायद एक सामान्य अंतर बेहतर होगा। कुछ 'लेवेनशेटिन/लम्बाई' की तरह। बेशक, यह शायद मुद्दों भी है। जैसा कि आपने कहा था, ठेठ ओसीआर परिणामों के कुछ विचार शामिल करने के लिए उपयोगी होंगे। – JoshD

1

यह विकल्पों में से सबसे pythonic नहीं हो सकता है, लेकिन एक ? वर्णों की संख्या मैच के लिए अनुमति दी है, तो निम्न उलटे पांव लौटने खोज चाल है:

def match(a,b): 
    def matcher(i,j): 
     if i == len(a) and j == len(b): 
      return True 
     elif i < len(a) and a[i] == '?' \ 
      or j < len(b) and b[j] == '?': 
      return i < len(a) and matcher(i+1,j) \ 
       or j < len(b) and matcher(i,j+1) 
     elif i == len(a) or j == len(b): 
      return False 
     else: 
      return a[i] == b[j] and matcher(i+1,j+1) 

    return matcher(0,0) 

इसे मिलान करने के लिए और अधिक कड़े होने के लिए अनुकूलित किया जा सकता है। इसके अलावा, स्टैक स्पेस को बचाने के लिए, अंतिम मामला (i+1,j+1) को गैर-पुनरावर्ती समाधान में परिवर्तित किया जा सकता है।

संपादित करें: नीचे प्रतिक्रियाओं के जवाब में कुछ और स्पष्टीकरण।/NFAs (सुंदर कोड, ओ रेली 2007 या Jurafsky & मार्टिन, वाणी और भाषा प्रसंस्करण को Kernighan के योगदान, अप्रेंटिस हॉल 2009 देखें) इस सरलीकृत regexes के लिए एक अनुभवहीन मिलान एल्गोरिथ्म का रूपांतरण है।

यह कैसे काम करता है: matcher फ़ंक्शन (0,0) से शुरू होने वाले स्ट्रिंग/पैटर्न दोनों के माध्यम से पुनरावर्ती चलता है। यह (len(a),len(b)) दोनों स्ट्रिंग्स के अंत तक पहुंचने पर सफल होता है; यह विफल रहता है जब यह दो असमान पात्रों या एक स्ट्रिंग के अंत का सामना करता है जबकि अन्य स्ट्रिंग में मिलान करने के लिए वर्ण अभी भी होते हैं।

जब matcher या तो स्ट्रिंग में एक चर (?) का सामना करना पड़ता (माना a), यह दो बातें कर सकते हैं: या तो चर (शून्य पात्रों मिलान) छोड़, या b में अगले वर्ण छोड़ लेकिन की ओर इशारा करते रखने a में चर, इसे और अधिक वर्णों से मेल करने की अनुमति देता है।

+0

हम्म मुझे यह पसंद है। इस बारे में सोचते समय मैंने संक्षेप में डीएफए के बारे में याद दिलाया, और आपका बहुत अधिक अनुकरण करता है। मुझे बस इसे 3 जंगली वर्णों से मेल खाने के लिए समायोजित करना होगा .. – Claudiu

+0

यह दिलचस्प लग रहा है, लेकिन क्या आप इसे थोड़ा सा तोड़ सकते हैं - यहां क्या चल रहा है? –

+0

मैंने एक स्पष्टीकरण और कुछ संदर्भ जोड़े। –

संबंधित मुद्दे