

OCRをかける際になんらかの要因でノイズが入ったとします。

直線に近いものであればハフ変換抽出で削除することができます。  
↓このような削除する方法もあります。  
<http://www.morethantechnical.com/2015/02/05/using-hidden-markov-models-for-
staff-line-removal-in-omr-wcode/>

文字とノイズの黒の濃さが異なれば二値化で飛ばせますし、  
文字とノイズの線の太さが異なれば膨張・収縮でもいけそうですが  
以下のような

①濃さが同じ  
②太さも同じ  
③湾曲している

ノイズ線を削除することは可能でしょうか？  
ノイズ入ったままOCRの学習モデルをつくればよい、  
というのもありますが現実的には難しいと考えておりまして  
何かロジックで解決できないか質問させてください。

[![画像の説明をここに入力](https://i.stack.imgur.com/dmU6g.png)](https://i.stack.imgur.com/dmU6g.png)

最終的な補正した結果のイメージ画像は以下になります。

[![画像の説明をここに入力](https://i.stack.imgur.com/bAVdd.png)](https://i.stack.imgur.com/bAVdd.png)


CC BY-SA 3.0
2018-04-17T05:25:13.233
43309
2018-04-20T15:33:48.527
28179
question
python c++ opencv 画像
OCRするときの湾曲ノイズ線の削除方法


「濃さが同じ・太さが同じ」という設定が難しいですね。

日本語が分かる人なら、「ノイズ線」がノイズで、取り消し線つまり「埼玉県 ~~浦和区 高砂~~
3-15-1」ではないと認識できます（なぜなら、そういう住所はありえないので）。  
しかしながら、日本語が分からない人にとっては、ノイズなのか取り消し線なのか分からないので、本質的には、高レベルの認識が必要になると思います。

高レベルの認識を諦めれば、色々とアプローチはあると思いますが、二通りの方法を考えたので書いておきます。どちらも満足の行く結果にはなりませんが。

## 方法1

文字の領域を探して、それ以外の場所を背景画素値で埋めてしまう。  
具体的には、２値化してy軸方向に文字領域を足し、その頻度が少ない領域を背景にしてしまいます。  
[![処理例](https://i.stack.imgur.com/X8Cxt.png)](https://i.stack.imgur.com/X8Cxt.png)  
ご覧の通り、x軸が文字の領域と重なっているノイズ線は消えないという問題があります。

[code]

    import numpy as np
    import cv2
    import matplotlib.pyplot as plt
    
    file = "./saitama.png"
    original_img = cv2.imread(file)
    gray_img = cv2.cvtColor(original_img, cv2.COLOR_BGR2GRAY)
    (height, width) = gray_img.shape
    
    gray_img = cv2.GaussianBlur(gray_img, (5,5), 0)
    ret,th_img = cv2.threshold(gray_img, 100, 255, cv2.THRESH_BINARY)
    # th_img = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
    th_img= cv2.bitwise_not(th_img)
    hist = np.sum(th_img, axis=0)
    # mean = np.mean(hist)
    neighborhood = 200
    th_index = neighborhood // 2
    extend_hist = np.zeros((width+neighborhood*2))
    extend_hist[neighborhood:width+neighborhood] = hist
    
    for x in range(width):
        x_extend = x + neighborhood
        around_hist = extend_hist[x_extend-neighborhood:x_extend+neighborhood]
        th = np.sort(around_hist)[th_index]
        if (hist[x] < th):
            mean = np.mean(original_img[:,x])
            original_img[:,x] = mean * np.ones((height, 3))
    
    disp_img = cv2.cvtColor(th_img, cv2.COLOR_GRAY2RGB)
    x = np.arange(0, width, 1)
    plt.subplot(2,1,1)
    plt.plot(x, hist)
    plt.subplot(2,1,2)
    plt.imshow(original_img)
    plt.show()
    
[/code]

## 方法2

滑らかな曲線のクラスに対する一般化ハフ変換を考え、投票数が多い、つまり、一定の長さより長い曲線を検出して消す。  
この方法の問題として、今回の例での「高」の字のようにノイズ線と重なっている部分があると消えてしまいます。  
また、仮定として、ノイズ線がシグナルより長いとしているので、文字より短いノイズ線は消えません。  
また、設定した滑らかな曲線のクラスから外れるノイズ線（例えば、急激に曲がるノイズ線など）も消えません。


CC BY-SA 3.0
2018-04-20T15:33:48.527
43442
2018-04-20T15:33:48.527
18595
43309
answer