2015-10-19 10 views
10

Pythonを使用してイメージ内のほぼ水平な赤色レーザーラインを検出する最も信頼性の高い方法は何ですか?私は3dレーザースキャンに関連する小さなプロジェクトに取り組んでいます。歪みからの距離を計算するために、イメージ内のレーザーを検出できる必要があります。Pythonを使用してイメージ内のレーザーラインを検出する方法

私は、レーザーラインを含まないことが知られている基準画像Aとレーザーラインを含んでいる画像Bを2つの画像、ひずんでいる可能性があります。例えば

サンプル画像A:

enter image description here

サンプル画像B:

enter image description here

これらはRGBであるが、レーザが赤色であるので、私は青をストリッピングすることにより、いくつかのノイズを除去しますこの機能を使用する緑色チャンネル:

from PIL import Image 
import numpy as np 

def only_red(im): 
    """ 
    Strips out everything except red. 
    """ 
    data = np.array(im) 
    red, green, blue, alpha = data.T 
    im2 = Image.fromarray(red.T) 
    return im2 
私にこれらの画像を取得し

enter image description here

enter image description here

次は、私が試してみて、PIL.ImageChops.difference()を使用して、これら2枚の画像の差をとることにより、より多くのノイズを除去します。理想的には、2つの画像間の露出は同一であり、その違いにはレーザーライン以外は何も含まれない。残念なことに、レーザーが光を加えるので、各画像の露出と全体的な明るさが大きく異なり、結果としてかなりのノイズが残っています。例えば

enter image description here

私の最後のステップは、ラインがどこにあるのと、「最良の推測」を作ることです。私は線がおおよそ水平になり、レーザー線が画像の中で最も明るいものでなければならないことを知っているので、私は各列を走査し、最も明るい画素を持つ行を見つけます。このためのコードは次のとおりです。

import os 
from PIL import Image, ImageOps 
import numpy as np 

x = Image.open('laser-diff.png', 'r') 
x = x.convert('L') 

out = Image.new("L", x.size, "black") 
pix = out.load() 

y = np.asarray(x.getdata(), dtype=np.float64).reshape((x.size[1], x.size[0])) 
print y.shape 
for col_i in xrange(y.shape[1]): 
    col_max = max([(y[row_i][col_i], row_i) for row_i in xrange(y.shape[0])]) 
    col_max_brightness, col_max_row = col_max 
    print col_i, col_max 
    pix[col_i, col_max_row] = 255 

out.save('laser-line.png') 

私は本当に私の距離計算を実行するために必要なのはcol_max値の配列ですが、laser-line.pngは私が成功を視覚化するのに役立ちますし、次のようになります。

enter image description here

ご覧のとおり、見積もりはかなり近いですが、まだノイズの部分があります。ほとんどの場合、レーザーラインがマットブラック仕上げで吸収される画像の左側にあります。

私の精度やスピードを向上させるにはどうすればよいですか?私はこれをRaspberry PiのようなARMプラットフォーム上で実行しようとしています。そのため、コードを実行するにはあまりにも効率が悪いかもしれないと心配しています。

私はNumpyの行列関数を十分に理解していないので、より効率的ではなく、各列をスキャンするための遅いforループを解決する必要がありました。 Numpyの列ごとに最も明るいピクセルを持つ行を見つけるための高速な方法はありますか?

また、レーザーラインを調光せずに差異を実行する前に、画像を均一化する信頼できる方法がありますか?

+0

最後に、y座標が25%〜75%分位にないすべての点を削除することができます。次に、より良い結果を得て、locf..etc –

+0

@ B.Mr.W。を使用して不足している値を記入してください。あなたは部分的に正しいです。レーザーがカメラの下に取り付けられ、焦点面に平行であるため、すべてのレーザーポイントは中央の行より下にある必要があります。つまり、上のすべてのポイントはノイズです。ありがとう。 – Cerin

答えて

1

最初に、ネガティブイメージの強度をポジティブから減算する前に、ネガティブイメージの強度を再スケーリングして、より多くのノイズを除去することができます。例えば、おそらく平均的なintesityの比率でリサイズすることが良い最初の試行かもしれない?

また、閾値を配置しようとすることができます良いどのような値以下でご使用の最大は、それはおそらくあなたのレーザーが、騒々しいポイントではない場合...

を[はいnumpyのが最適な行/ COLを見つけることができますargmax関数を使用します。

1

最初にレーザーである色を入力し、赤色(この場合)のみを残します。次に、同じエフェクトを適用し、結果を確認します。

この場合、汚染された結果がはるかに少なくなります。 Result

紛失したドアの赤を分析する際に問題が発生しました。

+0

私はレーザーの色がわからない、それは赤くて粗いです。私は、シーン内に赤い物体が存在する可能性があるため、すべてが赤色であると仮定することはできません。この解決法は自動化されなければならないので、各画像にレーザーの色を手動で表示することはできません。 – Cerin

+0

画像を使ってグラフをスクロールします。おそらく最も大きな方法はレーザーラインを見つけることです。あなたのグラフの入り口には、2つの黒いピクセルと2つの白いピクセルが隣接するピクセルを持つピクセルがあります。 –

1

私は何かしようとしました。私はそれが完全に堅牢だとは思わない。しかし、あなたの例では、それは比較的うまく機能します。

私はあなたの「差」画像のエッジを検出するために賢いエッジ検出を使用しました。そして、this tutorialのようにハフライン変換を適用しました。 処理された画像から始めました(コードでlineDetection.jpgと呼んでいます)。ここ

enter image description here

最終スクリプト処理された画像上で検出された緑色の線で

import cv2 
import numpy as np 

img = cv2.imread('lineDetection.jpg') 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
edges = cv2.Canny(gray,10,100) 
minLineLength = 50 
maxLineGap = 20 
lines = cv2.HoughLinesP(edges,0.05,np.pi/5000,10,minLineLength,maxLineGap) 
print(len(lines)) 
for i in range(len(lines)): 
    x1,y1,x2,y2 = lines[i][0] 
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2) 

cv2.imwrite('houghlines5.jpg',img) 

あります。 (あなたがよりよい効果のために、元の画像にそれを追加することもできます)

enter image description here

はそれがお役に立てば幸いです。

関連する問題