天天看點

OCR的有效資料增強

作者:不秃頭程式員
OCR的有效資料增強

背景

我面臨着需要盡可能準确識别手寫金額的挑戰。難點在于保持誤判率低于0.01%。由于資料集中樣本數量固定,是以資料增強是合乎邏輯的選擇。快速搜尋未發現針對光學字元識别(OCR)的現成方法。是以,我挽起袖子,親自建立了一個資料增強例程。它在訓練過程中被使用,并幫助我的模型實作了目标。繼續閱讀以了解詳情。

通過每次訓練圖像時引入小的變化,模型不太可能過拟合,更容易泛化。我将其與TROCR一起使用,但任何其他模型也應該受益。

測試設定

由于無法分享來自專有資料集的圖像,我原本想使用IAM手寫資料庫的樣本,但我未收到使用權限的回複。是以,我為示範建立了一些自己的示例。

我将使用OpenCV和albumentations庫進行三種類型的修改:形态學、噪聲和變換。

OpenCV是一個衆所周知的計算機視覺庫。Albumentations是一個相對較新的Python庫,用于進行簡單但功能強大的圖像增強。

還有一個不錯的示範網站,你可以在其中嘗試albumentations的功能。但由于無法使用自己的圖像進行測試,是以我建立了一個Jupyter筆記本,用于在本文中渲染所有增強的圖像。請随時在Colab中打開并進行實驗。

我們将首先展示單獨的修改,附有一些解釋,然後讨論将它們結合在一起的技術。我将假設所有圖像都是灰階的,并已經進行了對比度增強(例如,CLAHE)。

第一種增強技術:形态學修改

這些與結構的形狀有關。簡單來說:它們可用于使文本行看起來像用細或粗筆寫的。它們被稱為腐蝕和膨脹。不幸的是,這些目前還沒有包含在albumentations庫中,是以我必須借助opencv來實作。

為了産生像是使用寬線寬度筆的效果,我們可以膨脹原始圖像:

OCR的有效資料增強

另一方面,腐蝕(順便說一下)模拟了使用細筆寫的效果:

OCR的有效資料增強

在這裡要小心,最後一個參數——即疊代次數——不要設定得太高(這裡設定為3),否則手寫完全被去除。

cv2.dilate(img, kernel,iterations=random.randint(1, 3))           

對于我們的資料集,我們隻能将其設定為1,是以這确實取決于你的資料。

第二種增強技術:引入噪聲

我們可以從圖像中删除黑色像素,也可以添加白色像素。有幾種方法可以實作這一點。我嘗試了許多方法,但這是我的簡短清單:

黑色下降顔色的RandomRain非常有害。即使對我來說,仍然很難閱讀文本。這就是為什麼我選擇将其發生的機會設定得很低的原因:

OCR的有效資料增強

RandomShadow會用不同強度的線模糊文本:

OCR的有效資料增強

PixelDropout輕松将随機像素變為黑色:

OCR的有效資料增強

與黑色滴落相比,具有白色滴落顔色的RandomRain使文字解體,進而增強了訓練的難度。就像當拍攝了影印一份傳真的照片時看到的低品質一樣。可以将此變換發生的機率設定得更高。

OCR的有效資料增強

在較小程度上,PixelDropout到白色也會産生相同的效果。但它更多地導緻圖像普遍褪色:

OCR的有效資料增強

第三種增強技術:變換

ShiftScaleRotate:在這裡要小心參數。盡量避免一些文本被切斷并超出原始尺寸。同時進行縮放和旋轉。確定不要過度使用太大的參數。否則,第一個樣本的機會更大。你可以看到它實際上将文本移出圖像。通過選擇較大的邊界框,可以防止這種情況——有效地在文本周圍添加更多的空白。

OCR的有效資料增強

模糊。老(但金貴)可靠的技術。将以不同的強度執行。

OCR的有效資料增強

大結局:将它們全部組合在一起:

這就是力量所在。我們可以随機組合這些效果,建立每個訓練時期都包含的獨特圖像。需要謹慎考慮,不要做太多相同類型的方法。我們可以使用albumentation庫中的OneOf函數來實作這一點。OneOf包含一系列可能的變換,正如其名稱所暗示的那樣,将僅以機率P執行其中的一個。是以,将做更多或更少相似的變換分組是有意義的,以避免過度使用。以下是該函數:

import random
import cv2
import numpy as np
import albumentations as A

#gets PIL image and returns augmented PIL image
def augment_img(img):
  #only augment 3/4th the images
  if random.randint(1, 4) > 3:
      return img

  img = np.asarray(img)     #convert to numpy for opencv

  # morphological alterations
  kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
  if random.randint(1, 5) == 1:
    # dilation because the image is not inverted
    img = cv2.erode(img, kernel, iterations=random.randint(1, 2))
  if random.randint(1, 6) == 1:
    # erosion because the image is not inverted
    img = cv2.dilate(img, kernel,iterations=random.randint(1, 1))

  transform = A.Compose([

    A.OneOf([
      #add black pixels noise
      A.OneOf([
             A.RandomRain(brightness_coefficient=1.0, drop_length=2, drop_width=2, drop_color = (0, 0, 0), blur_value=1, rain_type = 'drizzle', p=0.05), 
              A.RandomShadow(p=1),
              A.PixelDropout(p=1),
         ], p=0.9),

      #add white pixels noise
      A.OneOf([
              A.PixelDropout(dropout_prob=0.5,drop_value=255,p=1),
             A.RandomRain(brightness_coefficient=1.0, drop_length=2, drop_width=2, drop_color = (255, 255, 255), blur_value=1, rain_type = None, p=1), 
        ], p=0.9),
    ], p=1),

    #transformations
    A.OneOf([
            A.ShiftScaleRotate(shift_limit=0, scale_limit=0.25, rotate_limit=2, border_mode=cv2.BORDER_CONSTANT, value=(255,255,255),p=1),
            A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0, rotate_limit=8, border_mode=cv2.BORDER_CONSTANT, value=(255,255,255),p=1),
            A.ShiftScaleRotate(shift_limit=0.02, scale_limit=0.15, rotate_limit=11, border_mode=cv2.BORDER_CONSTANT, value=(255,255,255),p=1),  
            A.Affine(shear=random.randint(-5, 5),mode=cv2.BORDER_CONSTANT, cval=(255,255,255), p=1)          
       ], p=0.5),
    A.Blur(blur_limit=5,p=0.25),
  ])
  img = transform(image=img)['image']  
  image = Image.fromarray(img)   
  return image           

P代表事件發生的機會。它是一個介于0和1之間的值,其中1表示它總是發生,0表示永遠不會發生。

是以,讓我們看看它在實際操作中的效果:

OCR的有效資料增強

看起來相當不錯,對吧?

另一種方法:

在EASTER 2.0論文中,他們提出了TACo技術。它代表平鋪和破壞。(哈哈)它能夠實作這樣的效果:

OCR的有效資料增強

我還沒有嘗試過這個方法,因為我的直覺告訴我原始圖像被破壞得太厲害。在我看來,如果我看不懂它,計算機也一樣。然而,當考慮到作為人類,如果看到'TA█O',你可能會猜到它是'TACO'。我們會看周圍的字母,而taco是一個常見的詞。但是一個有字典支援的計算機可能會将其解讀為'TAMO',這恰好是英語中表示“日本灰”的一個詞。

結論

我們讨論了許多圖像操作以及它們對OCR任務的好處。我希望這對你有所幫助,或者至少給了你一些嘗試的靈感。你可以将我的方法作為基準,但可能需要微調一些參數,使其完美适應你的資料集。請告訴我你的模型準确性提高了多少!

我在這個Jupyter筆記本中公開了這個技術。

https://github.com/Toon-nooT/notebooks/blob/main/OCR_data_augmentations.ipynb

參考引用

https://opencv.org/

https://albumentations.ai/

https://fki.tic.heia-fr.ch/databases/iam-handwriting-database

https://arxiv.org/abs/2205.14879

https://github.com/Toon-nooT/notebooks