ただの備忘録
主要処理はclass内に記述
入力はコマンド上に ファイル名,使用画像の順で入力
当たり前だが別ディレクトリにいると動かない
コマンドプロンプトに文字化けがでたら大体いる場所が違うので確認すること。
import cv2
import sys
import numpy as np
import matplotlib.pyplot as plt
一度の膨張+収縮でノイズを消す
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()
輪郭抽出
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の差を出すことでも似たようなことができる
行っている計算が同じかは不明、要確認
文字の縁取りが出来ている。
問題の垂直線抽出部分
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()
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にあります。