LoginSignup
1
4

モルフォロジー演算(Morphological Transformations)を用いた垂直線検出

Last updated at Posted at 2023-06-20

ただの備忘録

主要処理はclass内に記述
入力はコマンド上に ファイル名,使用画像の順で入力
当たり前だが別ディレクトリにいると動かない
コマンドプロンプトに文字化けがでたら大体いる場所が違うので確認すること。

import cv2
import sys
import numpy as np
import matplotlib.pyplot as plt

変換前元画像
moto.png

一度の膨張+収縮でノイズを消す

def cleanIsolatedPoints(img,kernel):
    img = 255-img #色反転
    erosion = cv2.erode(img,kernel,iterations = 1)
    delation = cv2.dilate(img,kernel,iterations = 1)
    img = 255-img
    print(img.shape)
    plt.imshow(img,cmap="gray")
    plt.show()

1.png

輪郭抽出

def findLinesCanny(gray_image):
    gray_image = 255 - gray_image
    t_lower = 110 
    t_upper = 150

    edge = cv2.Canny(gray_image,t_lower,t_upper)
    plt.imshow(edge, cmap="gray"))
    plt.show()

参考:Carry関数の解説(英語)
Lower,Upperを変えるとしきい値が変わる

※dilateとerodeの差を出すことでも似たようなことができる
 行っている計算が同じかは不明、要確認
2.png

文字の縁取りが出来ている。

問題の垂直線抽出部分

def detectVerticalLines(gray):
    vertical = np.copy(gray)

    vertical = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 75, -3)
    rows = vertical.shape[1]
    #数字を大きくすると分割が細かくなる とりあえずここからいじる
    vertical_size = rows // 50
    #ここの第2引数を(vertical_size, 1)にすると水平線検出になる
    verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1,vertical_size))
    vertical = cv2.erode(vertical, verticalStructure)
    vertical = cv2.dilate(vertical, verticalStructure)
    # return resulting image
    plt.imshow(vertical , cmap="gray")
    plt.show()

3.png

cv2.adaptiveThreshold関数の引数は以下の通り
参考:Opencvの関数説明サイト

引数 内容
1 画像
2 閾値を超えたときに出力する値
3 計算方法の指定
4 Threshold Typeの指定
5 平均値を出すための計算領域のサイズ
6 平均値から引く定数 しきい値の微調整に使用

T(x,y) = (第5引数で指定した領域内の平均値)-(第6引数)
がしきい値となり、その値を超えると第2引数の値に変換するようになっている。
そのため、第5引数を大きくすると、より大雑把な区分けになる。

第5引数には奇数のみ指定可能
第6引数は小数も可能(double)

各引数について
第3引数:第5引数で指定した領域内の平均をとるか、ガウス分布によって重み付けを行うかの指定ができる。
ガウス分布を使う場合は、cv2.ADAPTIVE_THRESH_GAUSSIAN_C
とすればOK。平均でうまくいかないときに試す。

第4引数:二値への変換

THRESH_BINARY

dst(x,y) = \begin{cases}
    Maxvalue(第2引数) &     IF(src(x,y)>T(x,y)) \\
    0 &    それ以外
  \end{cases}

もしその位置の値(色)が、しきい値よりも大きければ第2引数で指定した色(今回は白)に、そうでなければ黒にする。
THRESH_BINARY_INVはこの場合分けが逆になるだけなので省略。
cv2.THRESH_BINARYかcv2.THRESH_BINARY_INVの二択。OTSUなどは指定できない。

コードはGitHubにあります。

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4