การล้างอิมเมจสำหรับ OCR


9

ฉันพยายามล้างรูปภาพสำหรับ OCR: (บรรทัด)

ป้อนคำอธิบายรูปภาพที่นี่

ฉันจำเป็นต้องลบบรรทัดเหล่านี้เพื่อประมวลผลภาพต่อไปและบางครั้งฉันก็ใกล้เข้ามามาก แต่หลายครั้งที่เกณฑ์ใช้เวลามากเกินไปจากข้อความ:

    copy = img.copy()
    blur = cv2.GaussianBlur(copy, (9,9), 0)
    thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,30)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
    dilate = cv2.dilate(thresh, kernel, iterations=2)

    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 > 300:
            x,y,w,h = cv2.boundingRect(c)
            cv2.rectangle(copy, (x, y), (x + w, y + h), (36,255,12), 3)

แก้ไข: นอกจากนี้การใช้ตัวเลขคงที่จะไม่ทำงานในกรณีที่แบบอักษรเปลี่ยนไป มีวิธีทั่วไปในการทำเช่นนี้?


2
บรรทัดเหล่านี้บางส่วนหรือบางส่วนของพวกเขามีลักษณะเดียวกันกับข้อความทางกฎหมายและมันจะเป็นการยากที่จะกำจัดพวกเขาโดยไม่ทำลายข้อความที่ถูกต้อง หากสิ่งนี้นำไปใช้คุณอาจมุ่งเน้นไปที่ข้อเท็จจริงที่ว่าพวกเขามีความยาวมากกว่าตัวอักษรและแยกได้บ้าง ดังนั้นขั้นตอนแรกอาจเป็นการประมาณขนาดและความใกล้ชิดของตัวละคร
Yves Daoust

@YvesDaoust เราจะค้นหาความสนิทสนมของตัวละครได้อย่างไร (เนื่องจากการกรองตามขนาดล้วนได้รับการผสมกับตัวละครหลายครั้ง)
K41F4r

1
คุณสามารถค้นหาระยะทางไปยังเพื่อนบ้านที่ใกล้เคียงที่สุดได้ทุกหยด จากนั้นโดยการวิเคราะห์ฮิสโทแกรมของระยะทางคุณจะพบขีด จำกัด ระหว่าง "ปิด" และ "แตกต่าง" (คล้ายกับโหมดการกระจาย) หรือระหว่าง "ล้อมรอบ" และ "แยก"
Yves Daoust

ในกรณีที่มีเส้นเล็ก ๆ หลายเส้นอยู่ใกล้กันเพื่อนบ้านที่ใกล้ที่สุดของพวกเขาจะไม่เป็นเส้นเล็ก ๆ อีกหรือไม่ การคำนวณระยะทางเฉลี่ยกับ blobs อื่น ๆ ทั้งหมดนั้นแพงเกินไปหรือไม่
K41F4r

"เพื่อนบ้านที่ใกล้เคียงที่สุดของพวกเขาจะไม่เป็นสายเล็ก ๆ อีกหรือไม่": คัดค้านดีให้เกียรติของคุณ ในความเป็นจริงกลุ่มส่วนสั้น ๆ ที่ใกล้ไม่แตกต่างจากข้อความที่ถูกต้อง แต่ในการจัดเรียงไม่น่าจะสมบูรณ์ คุณอาจต้องจัดกลุ่มชิ้นส่วนของเส้นที่แตกใหม่ ฉันไม่แน่ใจว่าระยะทางเฉลี่ยสำหรับทุกคนจะช่วยคุณได้
Yves Daoust

คำตอบ:


14

นี่คือความคิด เราแยกปัญหานี้ออกเป็นหลายขั้นตอน:

  1. กำหนดพื้นที่สี่เหลี่ยมผืนผ้าโดยเฉลี่ย จากนั้นเราก็จะค้นหารูปทรงและตัวกรองโดยใช้พื้นที่สี่เหลี่ยมผืนผ้าของขอบเขต เหตุผลที่เราทำเช่นนี้เป็นเพราะการสังเกตว่าลักษณะทั่วไปใด ๆ จะมีขนาดใหญ่มากเท่านั้นในขณะที่เสียงรบกวนขนาดใหญ่จะขยายพื้นที่สี่เหลี่ยมขนาดใหญ่ จากนั้นเราจะกำหนดพื้นที่เฉลี่ย

  2. ลบเส้นโครงร่างขนาดใหญ่ออก เราวนซ้ำรูปทรงอีกครั้งและลบรูปทรงขนาดใหญ่หากมี5xขนาดใหญ่กว่าพื้นที่รูปทรงเฉลี่ยโดยการกรอกในรูปทรง แทนที่จะใช้พื้นที่เกณฑ์คงที่เราใช้เกณฑ์ไดนามิกนี้เพื่อความทนทานที่มากขึ้น

  3. ขยายกับเคอร์เนลแนวตั้งกับตัวละครที่เชื่อมต่อ แนวคิดนี้ใช้ประโยชน์จากการสังเกตที่จัดตัวละครในคอลัมน์ การขยายด้วยเคอร์เนลแนวตั้งทำให้เราเชื่อมโยงข้อความเข้าด้วยกันดังนั้นจะไม่มีเสียงรบกวนในรูปร่างที่รวมกันนี้

  4. ลบเสียงขนาดเล็ก ตอนนี้ข้อความที่จะเก็บไว้เชื่อมต่อกันเราจะค้นหารูปทรงและลบรูปทรงใด ๆ ที่เล็กกว่า4xพื้นที่รูปทรงเฉลี่ย

  5. 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()

หมายเหตุ:การประมวลผลภาพแบบดั้งเดิมนั้น จำกัด อยู่แค่การกำหนดค่าใหม่การดำเนินการทางสัณฐานวิทยาและการกรองรูปร่าง (การประมาณรูปร่างพื้นที่สัดส่วนภาพหรือการตรวจจับหยดน้ำ) เนื่องจากภาพอินพุตอาจแตกต่างกันไปตามขนาดตัวอักษรการหาวิธีแก้ปัญหาแบบเอกเทศจึงค่อนข้างยาก คุณอาจต้องการฝึกอบรมตัวจําแนกของคุณเองด้วยการเรียนรู้ด้วยเครื่อง / การเรียนรู้เชิงลึกเพื่อหาวิธีแก้ปัญหาแบบไดนามิก


1
ในกรณีที่ตัวอักษรที่ใหญ่กว่านี้จะไม่ลบข้อความด้วยหรือไม่
K41F4r

ใช่มันอาจดังนั้นคุณจะต้องปรับค่าพื้นที่เกณฑ์ สำหรับวิธีการแบบไดนามิกที่มากขึ้นความคิดคือการกำหนดพื้นที่ตัวละครโดยเฉลี่ยแล้วใช้มันเป็นเกณฑ์
nathancy

ดูเหมือนว่าเฉพาะเจาะจงเกินไปสำหรับตัวอย่างการใช้พื้นที่เฉลี่ยจะยังคงลบข้อความจำนวนมากซึ่งทำให้ผลลัพธ์ของ OCR แย่ลง
K41F4r

คุณมีตัวอย่างภาพอื่นที่คุณสามารถเพิ่มในโพสต์ได้หรือไม่
nathancy

1
การค้นหาโซลูชันที่ใช้งานได้ในทุกสถานการณ์โดยใช้เทคนิคการประมวลผลภาพแบบเดิมนั้นค่อนข้างยาก คุณอาจต้องการตรวจสอบตัวจําแนกของคุณเองโดยใช้การเรียนรู้ลึก โชคดี!
nathancy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.