11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pythonで直線検出するアルゴリズム

Last updated at Posted at 2019-09-18

直線検知のアルゴリズム

Pythonで画像内の直線検知を行うアルゴリズムを書く。(2019年)

直線検知の主なアルゴリズム

  • Hough変換
  • LSD(Line Segment Detector)
    • Pylsd
    • OpenCV

※OpenCV3.4.4ではLSDはあるが、4.1.0からは削除されている。
代わりにFastLineDetectorというものがあるが、まだ試していない。(2019年9月18日現在)

各アルゴリズムの中身

ハフ変換

簡単に言うと多数決で直線を検出する方法
画像上のすべての点に対してその点を通る直線を検出し、直線を表すパラメータ群を輝度値で重み付けしていく。
重み付けされた直線を画像に書いていくと、直線が多く通る部分が濃くなり、直線だとわかる。
image.png
画像引用 amos storkey

LSD

輝度勾配とLevel Lineの角度を計算する。
輝度勾配は明るさに勾配を表し、LevelLineは異なる領域と分けられる線分を示す。
LevelLineのと勾配によって以下のような図を作成し、領域の推定を行う。
その後、領域を矩形に近似することで直線を検出する。
image.png
画像引用

メリット、デメリット

  • Hough変換

    • メリット
      • 固定の形式であればパラメータにより最適化できる。
    • デメリット
      • パラメータ探索をグリッドサーチしないと行けないので時間がかかる。
      • 探索精度は高いが演算不可が高い。(低いHoughLinePというものもあるが精度が下がる。)
  • LSD(LineSegmentDetetor)

    • メリット
      • パラメータの設定が不要
    • デメリット
      • パラメータの設定が出来ない分、入力画像の前処理を行ったりして精度を上げないといけない(?) ※検証中

所感

Hough変換よりもLSDでの直線検知の方が使いやすくて、精度も高い気がする。
LSDはOpenCVで実装されていたが権利周りで違反していたようで削除された。
代わりにFastLineDetectorが実装されている。(OpenCV==4.1.0)
Pylsdというものもあるので検証を行ってみて精度の高い方を使用したほうがいい気がした。

使い方

Hough_transform.py
import cv2

src = 'hoge.png' #入力画像のパス
img = cv2.imread(src)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_bitwise = cv2.bitwise_not(gray)
lines = cv2.HoughLinesP(gray2, rho=1, theta=np.pi/360, threshold=80, minLineLength=80, maxLineGap=5) #全探索
# lines = cv2.HoughLinesP(gray2, rho=1, theta=np.pi/360, threshold=80, minLineLength=80, maxLineGap=5) #確率的探索
for line in lines:
    x1, y1, x2, y2 = line[0]
    # draw line
    lines_img = cv2.line(img, (x1,y1), (x2,y2), (0,0,255), 1)
cv2.imwrite('lined_hoge.png', lines_img) 

パラメータ説明はここ参照

Opencv_lsd.py
import cv2

src = 'hoge.png' #入力画像のパス
img = cv2.imread(src)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
mono, th2 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)

LSD = cv2.createLineSegmentDetector()
lines, width, prec, nfa = LSD.detect(src)
lines = lines.tolist()
for idx,l in enumerate(lines):
    x1,y1,x2,y2 = l[0][0],l[0][1],l[0][2],l[0][3]
    # draw line
    lines_img = cv2.line(img, (x1,y1), (x2,y2), (0,0,255), 1)
cv2.imwrite('lined_hoge.png', lines_img)

Pylsdを使用する際はインストールに注意が必要そう。
python3に対応させるには以下の方法でインストール
pip install 'ocrd-fork-pylsd == 0.0.3'
参考:pythonの直線検出は間違いなくOpenCVではなくPylsdが優れている

Pylsd.py
from pylsd.lsd import lsd

src = 'hoge.png' #入力画像のパス
img = cv2.imread(src)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# gray = cv2.GaussianBlur(gray,(5,5),5) # ガウシアンフィルタを使用した方が良いらしい
linesL = lsd(gray)
for line in linesL:
    x1, y1, x2, y2 = map(int,line[:4])
    lines_img = cv2.line(img, (x1,y1), (x2,y2), (0,0,255), 1)
cv2.imwrite('lined_hoge.png', lines_img)
11
11
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
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?