यहाँ एक विचार है। हम इस समस्या को कई चरणों में तोड़ते हैं:
औसत आयताकार समोच्च क्षेत्र निर्धारित करें। हम फिर समोच्च का पता लगाते हैं और समोच्च के आयत क्षेत्र का उपयोग करके फ़िल्टर करते हैं । हम ऐसा करते हैं इसका कारण यह है कि कोई भी विशिष्ट चरित्र केवल इतना बड़ा होगा जबकि बड़ा शोर बड़े आयताकार क्षेत्र को फैलाएगा। हम तब औसत क्षेत्र निर्धारित करते हैं।
बड़े बाहरी रूपरेखा निकालें। हम फिर से आकृति के माध्यम से पुनरावृत्ति करते हैं और बड़े समोच्चों को हटा देते हैं यदि वे 5x
समोच्च में भरकर औसत समोच्च क्षेत्र से बड़े होते हैं । एक निश्चित सीमा क्षेत्र का उपयोग करने के बजाय, हम इस गतिशील सीमा का उपयोग अधिक मजबूती के लिए करते हैं।
वर्णों को जोड़ने के लिए एक ऊर्ध्वाधर कर्नेल के साथ पतला । विचार अवलोकन का लाभ उठाता है कि कॉलम में अक्षर संरेखित किए जाते हैं। एक ऊर्ध्वाधर कर्नेल के साथ पतला करके हम पाठ को एक साथ जोड़ते हैं ताकि शोर इस संयुक्त समोच्च में शामिल नहीं होगा।
छोटा शोर निकालें । अब जबकि रखने के लिए पाठ जुड़ा हुआ है, हम आकृति पाते हैं और 4x
औसत समोच्च क्षेत्र की तुलना में किसी भी आकृति को हटाते हैं।
बिटवाइज़-और छवि का पुनर्निर्माण करने के लिए । चूंकि हमारे पास अपने मुखौटे को रखने के लिए केवल वांछित आकृति हैं, हम बिटवाइज़-और पाठ को संरक्षित करने और अपना परिणाम प्राप्त करने के लिए।
यहाँ प्रक्रिया का एक दृश्य है:
हम ओत्सु की दहलीज एक द्विआधारी छवि प्राप्त करते हैं फिर औसत आयताकार समोच्च क्षेत्र निर्धारित करने के लिए आकृति पाते हैं। यहाँ से हम से हरे रंग में हाइलाइट बड़े बाहरी आकृति को दूर आकृति भरने
हम एक निर्माण अगला खड़ी गिरी और फैलने पात्रों कनेक्ट करने के लिए। यह कदम शोर को अलग-अलग बूँद में रखने और अलग करने के लिए सभी वांछित पाठ को जोड़ता है।
अब हम छोटे शोर को दूर करने के लिए समोच्च क्षेत्र का उपयोग करके समोच्च और फ़िल्टर पाते हैं
यहां सभी हटाए गए शोर कणों को हरे रंग में हाइलाइट किया गया है
परिणाम
कोड
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()
नोट: पारंपरिक छवि प्रसंस्करण थ्रेसहोल्ड, रूपात्मक संचालन और समोच्च फ़िल्टरिंग (समोच्च सन्निकटन, क्षेत्र, पहलू अनुपात या बूँद का पता लगाने) तक सीमित है। चूंकि इनपुट चित्र वर्ण पाठ आकार के आधार पर भिन्न हो सकते हैं, एक विलक्षण समाधान खोजना काफी कठिन है। आप एक गतिशील समाधान के लिए मशीन / गहन सीखने के साथ अपने स्वयं के क्लासिफायरियर प्रशिक्षण में देखना चाहते हैं।