[opencv]ハフライン変換(画像内のラインの検出)

4_13_ハフライン変換-OpenCV中国語公式ドキュメント

ハフ変換の概念を理解します。-画像内の線を検出するためにそれを使用する方法を見ていきます。-次の関数が表示されます:cv.HoughLines()、cv.HoughLinesP()

要約

  1. ハフ変換は、数学的な形式で表現できる場合、任意の形状を検出するための一般的な手法です。 形状が少し壊れたり変形したりしても検出できます。線でどのように機能するかを見ていきます。(原理は少し不明確です)
  2. ハフ変換を適用する前に、しきい値を適用するか、キャニーエッジ検出を使用してください。
  3. 確率的ハフ変換は、私たちが見ているハフ変換の最適化です。すべての点を考慮しているわけではありません。代わりに、ポイントのランダムなサブセットのみを取得します。これは、ライン検出に十分です。しきい値を下げる必要があるだけです。

コンテンツ

 仮説

ハフ変換が線を処理する方法

OpenCVでのハフマン変換

確率的ハフ変換(最適化アルゴリズム)


 仮説

ハフ変換は、数学的な形式で表現できる場合、任意の形状を検出するための一般的な手法です。形状が少し壊れたり変形したりしても検出できます。線でどのように機能するかを見ていきます。

線は、y = mx + cとして、またはパラメトリックにρ=xcosθ+ysinθとして表すことができます。ここで、ρは原点から線までの垂直距離であり、θはこの垂直線と水平軸が反時計回りに形成する角度です。方向の測定(方向は座標系の表現方法によって異なります。この表現はOpenCVで使用されます)。以下の画像をご覧ください。

1

したがって、線が原点の下を通過する場合、正のρと180未満の角度になります。線が原点より上にある場合は、角度を180未満、180以下にします。ρは負の値を取ります。垂直線は0度、水平線は90度になります。

ハフ変換が線を処理する方法

任意の線は、2つの項(ρ、θ)で表すことができます。

  1. 最初に2D配列またはアキュムレータを作成し(2つのパラメータの値を保持するため)、最初にそれを0に設定します。行がρを示し、列がθを示すとします。
    配列のサイズは、必要な精度によって異なります角度を1度まで正確にしたい場合は、180列が必要です。
    ρの場合、可能な最大距離は画像の対角線の長さです。
    したがって、1ピクセルの精度で、線の数を画像の対角線の長さにすることができます。

100x100中央に水平線がある画像の画像を考えてみましょう。線の最初の点を取ります。(x,y)あなたはその価値を知っています。ここで一次方程式に、値θ= 0,1,2、..... 180を入れて、ρを取得することを確認します。各ペア(ρ、θ)について、アキュムレータの対応する(ρ、θ)セルは値を1ずつインクリメントします。したがって、アキュムレータでは、セル(50,90)=1および他のいくつかのセルになります。

さて、ラインの2番目のポイント。上記と同じようにします。(ρ、θ)に対応するセルの値をインクリメントします。今回は、セル(50,90)=2実際には、(ρ、θ)値に投票しています。ライン上の各ポイントに対してこのプロセスを続行します。各ポイントで、セル(50,90)が増加または投票しますが、他のセルは投票する場合としない場合があります。このようにして、最終的に、セル(50,90)の投票数が最も多くなります。したがって、アキュムレータで最大投票数を検索すると、(50,90)の値が得られます。これは、この画像の線が原点から50度、原点から90度であることを意味します。画像は下のアニメーションでうまく表示されています(画像クレジット:Amos Storkey)

これは、ハフ変換が線に対してどのように機能するかです。簡単です。Numpyを使用して自分で実装できるかもしれません。下の図は、アキュムレータを示しています。特定の場所にある輝点は、それらが画像内の可能な線のパラメータであることを示しています。(画像提供:ウィキペディア)

OpenCVでのハフマン変換

上で説明したものはすべて、OpenCV関数** cv.HoughLines **()にカプセル化されています。math:(rho,theta)値の配列という1つだけを返します。

ρはピクセル単位で、θはラジアン単位です。

  • 最初のパラメーターである入力画像はバイナリ画像である必要があるため、ハフ変換を適用する前に、しきい値を適用するか、キャニーエッジ検出を使用します。
  • 2番目と3番目のパラメーターは、それぞれρとシータの精度です。
  • 4番目のパラメーターはしきい値です。これは、行の最低投票と見なす必要があることを意味します。投票数は、ライン上のポイント数によって異なることを忘れないでください。したがって、これは検出する必要のある最小の線の長さを表します。
import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLines(edges,1,np.pi/180,200)
for line in lines:
    rho,theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))
    cv.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv.imwrite('houghlines3.jpg',img)

以下の結果を確認してください 

確率的ハフ変換(最適化アルゴリズム)

ハフ変換では、2つのパラメーターを持つ行であっても、多くの計算が必要であることがわかります。確率的ハフ変換は、私たちが見ているハフ変換の最適化です。すべての点を考慮しているわけではありません。代わりに、ポイントのランダムなサブセットのみを取得します。これは、ライン検出に十分ですしきい値を下げる必要があるだけです。ハフ空間でのハフ変換と確率的ハフ変換を比較した下の図を参照してください。(画像クレジット:Franck Bettingerのホームページ)

OpenCVの実装は、Matas、J.とGalambos、C.およびKittler、JVに基づいています。ProgressiveProbabilisticHoughTransformを使用した行のロバストな検出[145]。使用される関数は**cv.HoughLinesP**()です。2つの新しい引数があります。--minLineLength- 最小行長 。この長さより短いセグメントは拒否されます。--maxLineGap- 線分 として扱うことができる線分の間の最大ギャップ。

何よりも、行の2つの端点を直接返します。前のケースでは、ラインのパラメータのみを取得し、すべてのポイントを見つける必要があります。ここでは、すべてが単純明快です。

import cv2 as cv
import numpy as np
img = cv.imread(cv.samples.findFile('sudoku.png'))
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize = 3)
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
    x1,y1,x2,y2 = line[0]
    cv.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv.imwrite('houghlines5.jpg',img)

次の結果を参照してください。

おすすめ

転載: blog.csdn.net/dujuancao11/article/details/122451097