2017-06-28 17 views
4

ツールの写真を用紙に貼り付けると、それらの輪郭の輪郭をベクトル化するよう求められます。用紙上にオブジェクトを抽出する

私はコンピュータビジョン関連の問題の初心者です。私が考えたのは、OpenCVとエッジ検出だけでした。

結果は私が想像していたより優れていますが、これはまだ非常に信頼性が低く、特にソース画像が「完璧」でない場合はそうです。

私は彼らが私に与えたレンチの2つの写真を撮った。

opencv bindings for nodeで遊んでた後、私はこの取得:次に

good wrench contour

を、私はあまり良い絵で試してみた:完全inexploitableだ

enter image description here

を。 Canny thresoldを変更することで少し上手くいくことができますが、それは自動化する必要があります(写真が比較的正確であることが前提です)。

だから私はいくつかの質問持っている:

  • 私は右のアプローチを取っていますか? GrabCutはこれに対してより良いですか? GrabcutとCannyのエッジ検出の組み合わせ?私はまだ最後に頂点が必要ですが、私はGrabCutも私が望むことをしていると感じます。
  • 罫線が粗く、特定のエラーがあります。私はapproxPolyDPの乗数を増やすことができますが、良い部分の精度が失われることはありません。
  • 上記に関連して、approxPolyDPのポリゴン簡略化ではなく、輪郭を滑らかにするSavitzky-Golayアルゴリズムを統合しようと考えています。いいアイデアですか?
  • 通常、外側の境界線は、単純なカット可能なブロックを形成する必要があります。その行が不可能なことをするのを避けるために、OpenCLに方法がありますか? - あるいは、問題を検出するだけですか?これらの設定はもちろん不可能ですが、検出が失敗した場合に起こります(2番目の画像のように)。
  • 私は手動で各画像を調整する必要があるので、私は自動Canny thresold計算を行う方法を探しています。あなたはそのための良い例がありますか?
  • エッジ検出前に画像をグレースケールに変換すると、結果が悪くなることがあります。どちらを選ぶべきですか? (!ツールはところで、任意の色のものであってもよい)

ここに私のテストのためのソースです:

const cv = require('opencv'); 

const lowThresh = 90; 
const highThresh = 90; 
const nIters = 1; 

const GRAY = [120, 120, 120]; 
const WHITE = [255, 255, 255]; 

cv.readImage('./files/viv1.jpg', function(err, im) { 
    if (err) throw err; 

    width = im.width() 
    height = im.height() 
    if (width < 1 || height < 1) throw new Error('Image has no size'); 

    const out = new cv.Matrix(height, width); 
    im.convertGrayscale(); 
    im_canny = im.copy(); 
    im_canny.canny(lowThresh, highThresh); 
    im_canny.dilate(nIters); 

    contours = im_canny.findContours(); 

    let maxArea = 0; 
    let biggestContour; 

    for (i = 0; i < contours.size(); i++) { 
    const area = contours.area(i); 
    if (area > maxArea) { 
     maxArea = area; 
     biggestContour = i; 
    } 

    out.drawContour(contours, i, GRAY); 
    } 

    const arcLength = contours.arcLength(biggestContour, true); 
    contours.approxPolyDP(biggestContour, 0.001 * arcLength, true); 

    out.drawContour(contours, biggestContour, WHITE, 5); 

    out.save('./tmp/out.png'); 
    console.log('Image saved to ./tmp/out.png'); 
}); 
+0

不均一なバックグラウンド除去のアルゴリズムを確認してください。 –

+0

@AnderBiguri GrabCutについてお話しますか?私はそれが答えかもしれないともっと考えています。 私はCannyベースのソリューションを使ってGrabCutのオブジェクト境界を判断すると思います。 GrabCutを適用すると、必要に応じて(マスキングを使用して)ユーザによる修正が可能になります。そしてGrabCutの出力から再びエッジを検出します(バックグラウンドが削除されるので、Googleでdetouredイメージを取るときのようにうまく動作します)。実行可能に見えます。 オブジェクトのスケールを決定するには、私はArukcoマーカーを使用すると思います。 –

+0

このシステムはどのように動作するように意図されていますか?私はなぜマシンビジョンシステムの[照明は重要なコンポーネントです](http://www.ni.com/white-paper/6901/en/)と聞いていますが、画像には...まあ、そうではありません理想的に見える。最初の写真はかなりまともですが、中でも明るい円形のグラデーションが見えます。 2番目はかなりひどいです。もしあなたがそれを修正できれば、多くの作業や失敗の可能性をかなり省くことができます(実行可能であると仮定して)。 –

答えて

1

あなたが画像をクリーンアップするためにいくつかの前処理を追加する必要があります。シャドウ、照明の不足、ツールの輝きなどのために画像の輝度が大きく変化するため、画像を均等にする必要があります。これは、現在不十分な照明や高い輝きを放っている地域で、より良い反応を得るのに役立ちます。

ここではC++でのヒストグラム平坦化にOpenCVのチュートリアルです:http://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.html

希望これは

EDIT役立ちます: あなたは、いくつかの損失関数に基づく自動しきい値を持つことができます(?)。たとえば、次のようにします。ツールがフレーム内に完全にキャプチャされることがわかっている場合は、x = 10からx = 800(つまり)の各列で高い値を取得する必要があります。 x = 10からx = 800までの各列で高い値が得られるまで、しきい値を引き下げていくことができます。これは非常に素朴な方法ですが、画像を生成するので興味深い実験ですオブジェクトの配置を制御できます。

+0

ありがとう!はい、私はそれが大きく助けることができると思います。しかし、私はCannyのために自動的に決定された閾値は、この場合同じ仕事をする可能性があると考えていますが、より単純です。 しかし私は私のアプローチを変更し、パイプラインにGrabCutを追加すると思います。(質問に対する私のコメントを参照してください) –

+0

@MorganTouvereyQuilling grabcutによる私の素早い視線は半自動プロセスであることを示しています。私はあなたが自動アプローチを必要としていたという印象を受けました。私は答えを編集して、自動閾値を設定する非常に素朴な方法を示しています。 –

+0

あなたは正しいです、十分正確ではありません。プロセスはできるだけ自動化されていなければなりません。しかし、処理されたすべての画像が人間によってチェックされ、エラーがなければならないため、ユーザ対話が可能です。私は、エッジ検出が完璧になるまでユーザが写真を撮らなければならないと考えていましたが、GrabCutを使用したこれらのユーザにとってははるかに簡単です。とにかく、助けてくれてありがとう、多分それが助けになるだろう、そしてダンが上で述べたように、ライトは重要だから、ヒストグラム均等化が多くの状況に役立つと確信しているので、アップフォートを与える。 –

1

また、画像をadaptive thresholdから実行してみることもできます。このタイプの二値化は、たとえ一貫性のない照明/陰影であっても、このような場合に前景と背景をセグメント化するのにかなり熟練しています(上記の2番目の例では問題があるようです)。 Adathreshではパラメータの微調整が必​​要になりますが、ツール全体がバックグラウンドから分割されると、Cannyエッジの検出によってより一貫した結果が得られるはずです。

輪郭の粗さについては、findContoursモードをhereの​​のいずれかのモードに設定してみてください。

+0

ありがとう@DCSmith、私はあなたがそれを言及した後に適応閾値をテストしました。そして、それは白紙に非常に興味深い結果を与えることができます。それにも欠点があります(影に感性を高めることを含む)ので、私は私の場合、直接エッジ検出で同等の結果が得られると言います。このアプローチはバックグラウンドがはっきりと分かれば非常に良い結果をもたらすことができるので、私はあなたにアップヴォートも与えます。私はこれと直接エッジ検出の間でまだ選択しなかったし、最終的にこれを選択すれば答えを受け入れるだろう。 –

関連する問題