นี่คือความคิด เราแยกปัญหานี้ออกเป็นหลายขั้นตอน:
กำหนดพื้นที่สี่เหลี่ยมผืนผ้าโดยเฉลี่ย จากนั้นเราก็จะค้นหารูปทรงและตัวกรองโดยใช้พื้นที่สี่เหลี่ยมผืนผ้าของขอบเขต เหตุผลที่เราทำเช่นนี้เป็นเพราะการสังเกตว่าลักษณะทั่วไปใด ๆ จะมีขนาดใหญ่มากเท่านั้นในขณะที่เสียงรบกวนขนาดใหญ่จะขยายพื้นที่สี่เหลี่ยมขนาดใหญ่ จากนั้นเราจะกำหนดพื้นที่เฉลี่ย
ลบเส้นโครงร่างขนาดใหญ่ออก เราวนซ้ำรูปทรงอีกครั้งและลบรูปทรงขนาดใหญ่หากมี5x
ขนาดใหญ่กว่าพื้นที่รูปทรงเฉลี่ยโดยการกรอกในรูปทรง แทนที่จะใช้พื้นที่เกณฑ์คงที่เราใช้เกณฑ์ไดนามิกนี้เพื่อความทนทานที่มากขึ้น
ขยายกับเคอร์เนลแนวตั้งกับตัวละครที่เชื่อมต่อ แนวคิดนี้ใช้ประโยชน์จากการสังเกตที่จัดตัวละครในคอลัมน์ การขยายด้วยเคอร์เนลแนวตั้งทำให้เราเชื่อมโยงข้อความเข้าด้วยกันดังนั้นจะไม่มีเสียงรบกวนในรูปร่างที่รวมกันนี้
ลบเสียงขนาดเล็ก ตอนนี้ข้อความที่จะเก็บไว้เชื่อมต่อกันเราจะค้นหารูปทรงและลบรูปทรงใด ๆ ที่เล็กกว่า4x
พื้นที่รูปทรงเฉลี่ย
Bitwise- และเพื่อสร้างภาพใหม่ เนื่องจากเรามีรูปทรงที่ต้องการเพื่อสวมหน้ากากของเราเท่านั้นเราจึงใช้ค่าบิต - และเพื่อรักษาข้อความและรับผลของเรา
นี่คือการสร้างภาพของกระบวนการ:
เรากำหนดเกณฑ์ของ Otsuเพื่อให้ได้ภาพไบนารีจากนั้นค้นหาเส้นขอบเพื่อกำหนดพื้นที่เส้นโครงสี่เหลี่ยมผืนผ้าโดยเฉลี่ย จากที่นี่เราจะลบเส้นโครงร่างขนาดใหญ่ที่เน้นด้วยสีเขียวโดยการกรอกเส้นขอบ
ต่อไปเราจะสร้างเคอร์เนลแนวตั้งและขยายเพื่อเชื่อมต่ออักขระ ขั้นตอนนี้เชื่อมโยงข้อความที่ต้องการทั้งหมดเพื่อเก็บและแยกสัญญาณเสียงออกเป็นส่วนย่อย
ตอนนี้เราค้นหารูปทรงและตัวกรองโดยใช้พื้นที่รูปร่างเพื่อขจัดเสียงรบกวนขนาดเล็ก
นี่คืออนุภาคเสียงที่ถูกลบทั้งหมดที่เน้นสีเขียว
ผลลัพธ์
รหัส
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()
หมายเหตุ:การประมวลผลภาพแบบดั้งเดิมนั้น จำกัด อยู่แค่การกำหนดค่าใหม่การดำเนินการทางสัณฐานวิทยาและการกรองรูปร่าง (การประมาณรูปร่างพื้นที่สัดส่วนภาพหรือการตรวจจับหยดน้ำ) เนื่องจากภาพอินพุตอาจแตกต่างกันไปตามขนาดตัวอักษรการหาวิธีแก้ปัญหาแบบเอกเทศจึงค่อนข้างยาก คุณอาจต้องการฝึกอบรมตัวจําแนกของคุณเองด้วยการเรียนรู้ด้วยเครื่อง / การเรียนรู้เชิงลึกเพื่อหาวิธีแก้ปัญหาแบบไดนามิก