OpenCVで画像から直線を検出したいです。
cv2.HoughLinesP 関数を使えば良いぞ。
ただ、その前に前処理をしないと上手く直線が検出されない。
✔️ 本記事のテーマ
OpenCVで直線を検出する方法
✔️ 読者さんへの前置きメッセージ
本記事は「OpenCV の cv2.HoughLinesP 関数」について書いています。
この記事を読むことで
「cv2.HoughLinesP の使い方 や 直線検出に必要な前処理」
について理解できます。
OpenCVを使うことで画像中の直線を検出することができます。
OpenCVを応用すれば、直線を検出することで、画像から検出した直線を消すこともできます。
この記事では、OpenCV を使って、直線を検出する方法を手順ごとに解説します。
それでは、解説していきましょう。
OpenCV で直線を検出するサンプルコード
OpenCV で直線を検出するサンプルコードは以下のようになります。
この記事ではこのサンプルコードに沿って解説していきます。
import cv2
import numpy as np
img = cv2.imread("./sample.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
reversed_gray = cv2.bitwise_not(gray)
lines = cv2.HoughLinesP(reversed_gray, rho=1, theta=np.pi/360, threshold=80, minLineLength=400, maxLineGap=5)
for line in lines:
x1, y1, x2, y2 = line[0]
line_img = cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 3)
cv2.imwrite("sample_after.png", line_img)
このサンプルコードによって
↑このような画像から
↑このような直線(赤線部分)を検出することができます。
では、順番に解説していきましょう。
OpenCV で直線を検出する手順
OpenCVで画像中から直線を検出する手順は以下の通りです。
- 画像の読み込み
- 画像のグレースケール化
- 画像のビットを反転させる
- 画像中から直線を検出する
- 検出した直線を書き込む
- 画像の書き出し
1~3までは画像から正しく直線を検出するための前処理です。
画像処理は前処理が大切で、
この前処理が上手くできていないとOpenCVを使っても綺麗に直線を検出できません。
では、直線を検出する方法を手順ごとに解説していきましょう。
画像の読み込み
まず、OpenCVで画像処理を行うために対象の画像を読み込みます。
画像の読み込みにはOpenCV のcv2.imread関数を使います。
以下のように、対象の画像パスを引数で指定することで、画像の読み込みを行えます。
img = cv2.imread("./sample.png")
なお、OpenCV の cv2.imread関数については
「OpenCVで画像を読み込む方法【Python】」
の記事で詳しく解説しています。
画像のグレースケール化
次に、画像のグレースケール化を行います。
画像をグレースケールにすることで後続のcv2.HoughLinesP 関数にインプットすることができます。
画像のグレースケール化には OpenCV のcv2.cvtColor関数を使います。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
なお、OpenCV の cv2.cvtColor関数については
「OpenCVでグレースケール画像を簡単に作成する【Python】」
の記事で詳しく解説しています。
画像のビットを反転させる
さらに、グレースケール化した画像をビット反転します。
ビット反転させることで、画像の白黒を入れ替えます。
reversed_gray = cv2.bitwise_not(gray)
これにより、白が多いカレンダー画像を黒中心にすることで
直線の位置をより明確にすることができます。
ちなみに、この手順を飛ばすと次の線分検出で、
直線ではない部分が直線とみなされてしまい、異常な数の直線を検出してしまいます。
画像中から直線を検出する
ここまでの前処理が完了したら、直線を検出していきましょう。
直線の検出には cv2.HoughLinesP 関数を使用します。
lines = cv2.HoughLinesP(reversed_gray, rho=1, theta=np.pi/360, threshold=80, minLineLength=400, maxLineGap=5)
cv2.HoughLinesP 関数は戻り値として検出した線の座標を Ndarray で返します。
[ [x1, y1, x2, y2], [x1, y1, x2, y2], … ]
という値が返ってくるイメージです。
また、cv2.HoughLinesP 関数は与える引数が重要になってきます。
それぞれ解説しましょう。
cv2.HoughLinesP 関数の第1引数: img
第1引数: img は画像データ です。
ここまでで前処理を実施した画像データを渡しましょう。
サンプルコードでは ビット反転画像 reversed_gray を渡しています。
cv2.HoughLinesP 関数の第2引数: rho
第2引数: rho は直角座標点と直線の距離です。
float 型で指定します。
この引数は少し専門的 & 値を細かに調整する必要がない ので、
デフォルト値で特に問題ないかと思います。
cv2.HoughLinesP 関数の第3引数: theta
第3引数: theta は直角座標点と直線の角度です。
float 型で指定します。
この引数も第2引数と同じくデフォルト値で特に問題ないかと思います。
cv2.HoughLinesP 関数の第4引数: threshold
第4引数: threshold は 直線とみなすための閾値です。
Int 型で指定します。
直線上にある点の数がこの値以上となった時に直線とみなされます。
今回の画像サイズくらいであれば、100前後を渡しておけばOKです。
cv2.HoughLinesP 関数の第5引数: minLineLength
第5引数: minLineLength は直線とみなす最小の長さです。
Int 型で指定します。
この 第5引数 が処理結果の鍵を握っています。
単位は px です。
ここで指定した値以上の長さの直線を検出対象とします。
minLineLength を大きく設定しすぎると、取得すべき直線が検出されず、
小さく設定しすぎると、不要な線(文字中の線など)まで取得してしまいます。
cv2.HoughLinesP 関数の第6引数: maxLineGap
第6引数: maxLineGap は同一直線とみなす点間隔の長さです。
2つの点が1線上にある場合に、
点と点の間の間隔が指定した数値より小さければ、同一の直線として検出します。
検出した直線を書き込む
lines には検出した直線の数だけの座標配列が格納されているので、
それらを for 文で回しながら、線分を書き込んでいきます。
for line in lines:
x1, y1, x2, y2 = line[0]
line_img = cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 3)
cv2.imwrite("sample_after.png", line_img)
直線の描画にはcv2.line関数を使用しています。
なお、OpenCV の cv2.line関数については
「【OpenCV】cv2.line関数の使い方【線分を描画する】」
の記事で詳しく解説しています。
画像の書き出し
最後に、検出した直線を書き込んだ画像データを画像ファイルとして書き出します。
画像データの書き出しにはOpenCV のcv2.imwrite関数を使います。
第1引数に画像データ、第2引数に保存先のファイルパスを指定します。
cv2.imwrite("sample_after.png", line_img)
なお、OpenCV の のcv2.imwrite関数については
「OpenCVで画像を保存する方法【Python】」
の記事で詳しく解説しています。
画像処理プログラミングを独学で勉強するなら
画像から直線を検出する方法について解説しました。
OpenCVは画像処理には欠かすことのできないライブラリです。
もし、OpenCVについて独学でスキルをつけるなら、以下の書籍がオススメです。
この書籍はOpenCVの基礎から応用までを
丁寧にかつ詳細に解説しています。
OpenCVのほぼ全てを網羅しているとも言えるほどの徹底ぶりなので、
関数のリファレンスとしても使用することができます。
本記事で解説したcv2.HoughLinesP関数も掲載されています。
エンジニアとしての自身の価値をチェックする(完全無料)
エンジニアとして、
自分の価値がどれくらいのものかご存知でしょうか?
エンジニアとしてIT業界に身を置いていると
今の会社でずっと働くのか、フリーランスとして独立するのか …
と様々な選択肢があります。
どの選択肢が正解なのかを見極めるためにも、選択肢を広げるためにも
自身の価値を知っておくことはとても重要です。
TechClips ME では、
職務経歴書をアップロードするだけで企業からのスカウトを受けることができます。
▼▼▼▼▼
▲▲▲▲▲
しかもTechClips MEでは想定年収を企業から提示してくれるので、
自身の価値を数字で分かりやすくたしかめることができます。
登録はもちろん完全無料なので、一度登録してみると良いかもしれません。
コメント