ハフ変換

ハフ変換そのものは座標の変換処理なのですが、画像処理では、ハフ変換を用いて画像中の直線部分を抽出するのに用いられます。

ハフ変換と言うだけで、あんに直線検出を指している事が多くあります。

また、ハフ変換を拡張して、円の検出に用いられる場合もあります。

ハフ変換で出来ること

画像の中から、直線が途切れていても、直線らしき部分を抽出したり、前処理でエッジ抽出を行い、輪郭部分を検出する事もできます。

(元画像)

(直線検出)

(元画像)

(輪郭検出)

直線検出のしくみ

まず初めに直線として検出したい場所を二値化して抽出します。

被写体の輪郭を検出したい場合は、SobelCannyなどの前処理を行います。

二値化された座標(XY座標)に関して、X座標をいくつかに分割し、Y軸方向に二値化された座標をカウントします。

このカウントを点を原点に基点に回転させながら、繰り返しカウントを行います。

すると、点が直線的に並んだ時にカウント数が最大となります。

直線なので、逆向き(回転角度が180度反対)の時もカウント数が最大となります。

このカウント数を横軸を回転角度、縦軸をX座標にして、二次元的に表示すると、下図のようになり、カウント値がピークとなるXとθの値から、直線を検出することができます。

ハフ変換のアルゴリズム

点を回転して特定方向に積算することで、直線を見つける事もできるのですが、ハフ変換では、各点を通る直線を回転させ、直線が重なりあう場所をみつける事で、直線を検出します。

点(x, y)を通る線を、下図のようにρθで表すと

$$\rho=x cos\theta+y sin\theta$$

となります。

これは、(x, y)座標が決まっていて、θを与えると、ρが計算できる事になります。

点(x,y)を通る直線をθを0~360°の範囲で刻むと下図のようになります。

この直線をρとθで表すと、下図のようにsinカーブとなります。

 

この処理を各点に関して行うと、点が直線的に並んでいる部分では特定のρとθに集中します。

このρとθの値が集中している点を抽出し、ρとθの値から直線を検出します。

実際のハフ変換

ハフ変換の角度は0~360°で計算すると、必ず180°離れた2か所でρとθが集中するので、0~180°までを計算します。

実際のハフ変換では、エッジ上のxy座標から、θの値を例えば1°おきに0~180°までに対応したρの値を計算し、ρの値の分解能を例えば1などに落として、ρーθの座標系へ投票し、投票した値のカウント数が高い部分が直線となる部分のρ、θとなります。

OpenCV(Python)のサンプルプログラム

import cv2
import math
import numpy as np

# 画像読込
src = cv2.imread('keyboard.jpg', cv2.IMREAD_GRAYSCALE);
# 二値化
_, src = cv2.threshold(src, 200, 255, cv2.THRESH_BINARY)

cv2.imshow("edge image", src)

# ハフ変換
lines = cv2.HoughLines(src, 3, np.pi / 180, 400)

# 結果表示用の画像を作成
dst = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR);

# 直線を描画
line_length = 1000
for line in lines:
    rho = line[0][0]
    theta = line[0][1]
    a = math.cos(theta)
    b = math.sin(theta)
    x0 = a * rho
    y0 = b * rho
    cv2.line(
        dst, 
        (int(x0 - line_length * b), int(y0 + line_length * a)), 
        (int(x0 + line_length * b), int(y0 - line_length * a)), 
        (0, 0, 255), thickness=2, lineType=cv2.LINE_4 )

cv2.imshow("result", dst)

cv2.waitKey()

(処理前の画像)

(処理後画像)

注意事項

ハフ変換を行うと、直線らしい部分が抽出できますが、この直線の位置の精度を高めようと、ハフ変換時のθとρの分解能を高め過ぎると、直線検出の安定性が悪くなります。

そのため、直線の位置精度を高めるには、ハフ変換で直線付近の座標を抽出し、その座標から回帰直線などを求めるようにします。

ハフ変換」への2件のフィードバック

  1. ピンバック: ハフ変換(Hough Transform)による直線・円の検出 | CVMLエキスパートガイド

  2. ピンバック: ハフ変換 (Hough Transform)による直線・円の検出 | CVMLエキスパートガイド

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください