2016-07-13 6 views
3

私は現在黒と緑のドットからなる画像を作りました。私はその画像を印刷してカメラでクリックしました。 opencvでこの画像をスキャンするプログラム。ここでの画像は以下のとおりです。この画像から緑色の円を特定してください

enter image description here

これは私がこのコードで円をスキャンし、それらのそれぞれをループを実行することができています....しかし、今私が欲しいのコード

image = imread("ImageTryse.jpg", 1); // Read the image 
cv::resize(image, image, Size(800, 800), 0, 0, cv::INTER_CUBIC); 
Mat image_gray = IncreaseContrast(image); 
cvtColor(image_gray, image_gray, CV_BGR2GRAY); 
vector<vec3f> circles1; 
HoughCircles(image_gray, circles1, CV_HOUGH_GRADIENT, 2, 10, 100, 22, 10, 17); 

です天気を知るためには、サークルは緑色か黒色か....私はそれをどうすればいいのかわかりません....私はhsvに変換しようとしましたが、この問題を解決するのに役立ちます....

+0

実際、これはHSVではなくBGRで検出する方が簡単かもしれないと思います。検出されたディスクの赤色(または青色)成分に対する緑色成分の比率を調べてみましたか? – beaker

+0

@ビーカー、それはまったくナンセンスです。 BGR <-> HSV変換は完全に全単射である。 –

+0

私はコードとサンプルを使って問題を解決し、その答えを編集しました。チェックアウトしてください! –

答えて

1

OpenCVにはという機能があります(C++ではcv2.InRange、Java-Core.InRange)です。この関数では、2つのScalarオブジェクトを提供します.1つは色範囲のBGRカラーを開始し、もう1つは終了です。それはあなたに白いピクセルのマスクを返します:白い色は範囲にあり、黒はありません。詳細情報HEREHoughCirclesの前にInRangeに電話することをお勧めします。どのサークルが緑色であるのではなく、緑色のオブジェクトが円であるかを判別する方が簡単です。私は、HSVを開始するとINRANGE機能を実行し、

  • まずScalar(37, 38, 70)Scalar(85, 255, 200)を終了値:

    私はあなたの問題を解決するため、この方法を試してきました。 ScalarにRGBまたはBGRの値を入れていないことに注意してください。これはHSVカラー(H(0-180)、S(0-255)、V(0-255)の範囲で、THIS答えで書かれています):

enter image description here

  • あなたのコードで行うよう第二に、私はHoughCirclesのalgorythmを実行します。

enter image description here

見ての通りどこそれがshoul、1円がありますそうでなければ、サークルは両方の写真のサイズが異なっていてもよい。 InRange関数の値を使って、色の選択を改善し、円を丸くしてより完璧にし、HoughCirclesを使ってランダムな不要な円を回避することを強くお勧めします。また、私はCanny algorythm(Cannyエッジ検出器)を実験して、それらのオブジェクトの中心をクリアすることをお勧めします。結果が改善するかもしれません。

コードはJavaであるが、あなたの懸念は主にINRANGE機能であるとして、あなたは簡単にそれを理解する必要があります。最後に

Mat src = new Mat(); 
Mat circles = new Mat(); 
Mat result; 

Utils.bitmapToMat(Image, src); 
Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2HSV); 

Core.inRange(src, new Scalar(37, 38, 70), new Scalar(85, 255, 200), src); 
Imgproc.HoughCircles(src, circles, Imgproc.CV_HOUGH_GRADIENT, 2, 30, 100, 22, 10, 17); 

result = new Mat(src.rows(), src.cols(), CvType.CV_8UC1, new Scalar(0,0,0)); 
for (int i = 0; i < circles.cols(); i++) 
{ 
    double[] circle = circles.get(0, i); 
    if (circle == null) break; 
    Point center = new Point(Math.round(circle[0]), Math.round(circle[1])); 
    int radius = (int)Math.round(circle[2]); 
    Imgproc.circle(result, center, radius, new Scalar(255, 0, 0)); 
} 
return result; 

を、でも正しい値を持つこのalgorythmは完璧ではないかもしれません。適切な値で本当に素晴らしい結果を生み出すことは可能だと思います(私は悲しいことにそれらを見つけ出す時間がなかったので、私はあなたに任せます)。しかし、完璧な結果が必要な場合は、より広い幽霊の中で。たとえば、(あなたが指定したように)カラー画像にCanny関数を呼び出すと、円やその他のオブジェクトの非常に正確な輪郭を得ることができます。そして、たとえば、それらの輪郭にHoughCircles関数を実行し、それらのデータを持って、円の外にあるすべてのピクセルをクリアすることができます。 InRangeを使用すると、サークルの色をチェックして並べ替えることができます...しかしこれは単なる理論的なことです。何があなたの心に来るものすべてをお試しください。この実験により、更新された現在の結果より正確な結果が得られる場合があります。がんばろう!

+0

ありがとう、私はjavaを理解し、C++に移植することができます.... –

+0

私はinrange関数について知っていましたが、私はその値を見つけることができませんでした....あなたは私がそれを行うことができる方法を提案することができますか? –

+0

実際に私はこの機能についてはごくわずかな経験があります。私はインターネットでHSVカラーピッカーを見つけて、お好みの色のおおよその範囲を探してみることをお勧めします。バランスを見つけるのに数回かかるかもしれませんが、それが私が考えることができる唯一の方法です。 –

1

私はちょうどHSVアプローチで試してみましたが、ほとんど試行錯誤して、緑色の領域だけが現れる範囲を見つけることができました。緑色の円の位置を示す白いピクセルでイメージを取得すると、HoughCirclesを呼び出すことができます。

HSVの範囲は、(103142160)

私は、これは問題を解決を期待する(32,22,0)です。 :)

関連する問題