web-dev-qa-db-ja.com

Python OpenCVでHoughLinesを使用して画像の垂直線と水平線を検出する方法は?

キャリブレーションチェスボードのしきい値を取得しようとしています。マイクロチェス盤を観察するとほこりがあるため、チェス盤の角を直接検出することはできません。いくつかの方法を試してみましたが、HoughLinesPが最も簡単なアプローチのようです。しかし、結果は良くありません。私の結果を改善するには?

import numpy as np
import cv2

img = cv2.imread('lines.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
print img.shape[1]
print img.shape
minLineLength=100
lines = cv2.HoughLinesP(image=edges,rho=0.02,theta=np.pi/500, threshold=10,lines=np.array([]), minLineLength=minLineLength,maxLineGap=100)

a,b,c = lines.shape
for i in range(a):
    cv2.line(img, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 3, cv2.LINE_AA)
    cv2.imwrite('houghlines5.jpg',img)

下の図からわかるように、チェス盤を取得できません。線は多くの方向にプロットされています...(元の画像: https://s22.postimg.org/iq2b91xq9/droite_Image_00000.jpg

enter image description here

15
user3601754

Rhoに小さすぎる値を使用しています。

以下のコードを試してください:-

import numpy as np
import cv2

gray = cv2.imread('lines.jpg')
edges = cv2.Canny(gray,50,150,apertureSize = 3)
cv2.imwrite('edges-50-150.jpg',edges)
minLineLength=100
lines = cv2.HoughLinesP(image=edges,rho=1,theta=np.pi/180, threshold=100,lines=np.array([]), minLineLength=minLineLength,maxLineGap=80)

a,b,c = lines.shape
for i in range(a):
    cv2.line(gray, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 3, cv2.LINE_AA)
    cv2.imwrite('houghlines5.jpg',gray)

rho値、pi値、およびmaxLineGapの変化が異常値を減らすことに注意してください。

入力画像Input Image

エッジ画像Edges Image

出力画像Output Image

その他-初心者向けのヒント

  1. 多くのコンピュータービジョンアルゴリズムは、入力がどのようにあるべきかについて、特定の仮定を前提としています。 Proof-of-Conceptを構築するときは、このようなアルゴリズムを適用する前に、生成した中間入力を常に表示するようにしてください。

  2. 迅速なハックのために、アルゴリズムがいくつかのパラメーターを受け入れる場合、これらのパラメーターの可能な値でforループを使用し、結果がどのように変化するかを確認します。 リンク これらの可能な値を迅速に生成する方法に関する回答。

  3. アルゴリズムを実際に理解するには、必要に応じてwikiまたはさらに良いソースを読んでください。そして、再び/まだ上記のハックを行います(ポイント2)。それはあなたの理解をさらに明確にします。

33
saurabheights

コメントとしてこれを書きたいのですが、残念ながらできません。 minLineLengthとminLineGapを変更する必要があります。または、もしあなたが見つけなければならないその二乗だけなら、私はすべての線を取得し、それらの間の角度をチェックして正方形に沿ってのみ線を取得します。私は以前にHoughLinePを使用しましたが、これは上記の2つの引数にほぼ基づいています。さらに、バイラテラルフィルタリングを使用してみてください。メディアンフィルターを使用したシャープニングが役に立たない場合、私は本当に役立ちます。

バイラテラルフィルター

1
Rick M.