5

キャニーフィルターと輪郭検出機能に基づいて、ビデオカメラ/ウェブカメラを使用して、任意の形状のオブジェクトを検出するプログラムを作成しようとしています。これが私のプログラムです:

int main( int argc, char** argv )
{
CvCapture *cam;
CvMoments moments;
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours = NULL;
CvSeq* contours2 = NULL;
CvPoint2D32f center;
int i;

cam=cvCaptureFromCAM(0);
if(cam==NULL){
    fprintf(stderr,"Cannot find any camera. \n");
    return -1;
}
while(1){
    IplImage *img=cvQueryFrame(cam);
    if(img==NULL){return -1;}
    IplImage *src_gray= cvCreateImage( cvSize(img->width,img->height), 8, 1);
    cvCvtColor( img, src_gray, CV_BGR2GRAY );
    cvSmooth( src_gray,  src_gray, CV_GAUSSIAN, 5, 11);
    cvCanny(src_gray, src_gray, 70, 200, 3);

    cvFindContours( src_gray, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
    if(contours==NULL){ contours=contours2;}
    contours2=contours;
    cvMoments(contours, &moments, 1);

    double m_00 = cvGetSpatialMoment( &moments, 0, 0 );
    double m_10 = cvGetSpatialMoment( &moments, 1, 0 );
    double m_01 = cvGetSpatialMoment( &moments, 0, 1 );
    float gravityX = (m_10 / m_00)-150;
    float gravityY = (m_01 / m_00)-150;
    if(gravityY>=0&&gravityX>=0){
        printf("center point=(%.f, %.f) \n",gravityX,gravityY); }

    for (; contours != 0; contours = contours->h_next){
        CvScalar color = CV_RGB(250,0,0);
        cvDrawContours(img,contours,color,color,-1,-1, 8, cvPoint(0,0));
    }

    cvShowImage( "Input", img );
    cvShowImage( "Contours", src_gray );
    cvClearMemStorage(storage);
    if(cvWaitKey(33)>=0) break;
}
cvDestroyWindow("Contours");
cvDestroyWindow("Source");
cvReleaseCapture(&cam);
}

このプログラムは、カメラによってキャプチャされたすべての輪郭を検出し、輪郭の平均座標が出力されます。私の質問は、オブジェクトのより正確な (x,y) 位置を取得できるように、1 つのオブジェクト/輪郭のみを除外する方法です。可能であれば、(x,y) 座標を使用してオブジェクトの中心をマークする方法を教えてもらえますか?

前もって感謝します。乾杯

p/s: 申し訳ありませんが、まだスクリーンショットをアップロードできませんでした。何かお役に立てれば、こちらのリンクをご覧ください。

編集:私の質問をより明確にするために:

  • たとえば、上のスクリーンショットから正方形のみを除外したい場合、どうすればよいですか?
  • 除外したいオブジェクトには最大の輪郭領域があり、最も重要なことは、直線や曲線ではなく、形状 (任意の形状) を持っていることです。
  • 私はまだ滑らかでキャニーな値を試しているので、誰かが私のプログラムを使用して輪郭を検出するのに問題がある場合は、値を変更してください.
4

2 に答える 2

8

かなり簡単に解決できると思います。輪郭検出の前に、いくつかの形態学的操作を提案します。また、小さい要素を「除外」して、画像内に残っている唯一の要素として最大の要素を取得することをお勧めします。

私は提案します:

  • (直線または曲線)を除外する場合:「線」と「形状」の境界を自分でどのように考えるかを決定する必要があります。厚さが5ピクセル以上のすべてのオブジェクトをオブジェクトと見なし、幅が5ピクセル未満のオブジェクトを線と見なすとします。構造化要素として5x5の正方形または3ピクセルサイズの菱形を使用する形態学的開口部がこれを処理します。

  • 一般に小さなオブジェクトを除外する場合:オブジェクトが任意の形状である場合、純粋に形態学的な開口部は機能しません。代数的な開口部を実行する必要があります。特殊なタイプの代数的開口部は、領域開口部です。これは、(ピクセル)領域が特定のしきい値よりも小さい画像内のすべての連結成分を削除する操作です。興味のないオブジェクトのサイズに上限がある場合、または興味のあるオブジェクトのサイズに下限がある場合は、その値をしきい値として使用する必要があります形態学的な開口部を大きくしても同様の効果が得られる可能性がありますが、それほど柔軟ではありません。

  • 最大のものを除くすべてのオブジェクトを除外するために:接続されたコンポーネントを最小のものから最大のものに削除するように聞こえます。接続されたコンポーネントにラベルを付けてみてください。バイナリ(白黒画像)では、この画像変換は、グレースケール画像を作成し、背景に0(黒)のラベルを付け、各コンポーネントに異なる増加するグレー値を付けることで機能します。最終的に、各オブジェクトのピクセルは異なる値でマークされます。これで、グレーレベルのヒストグラムを見るだけで、ピクセル数が最も多いグレー値を見つけることができます。他のすべてのグレーレベルを0(黒)に設定すると、画像に残っているオブジェクトは最大のものだけになります。

提案は、最も単純なものから最も複雑なものまで書かれています。それでも、OpenCVはこれらのいずれにも役立つと思います。形態学的侵食、拡張、開閉はOpenCVで実装されています。自分で代数的オープニング演算子を作成する必要があると思います(またはOpenCVの基本的な形態を組み合わせて遊ぶ)が、OpenCVは、連結成分のラベル付けと、結果のグレースケール画像のヒストグラムの調査の両方に役立つと確信しています。

最後に、1つのオブジェクトのピクセルだけが残っている場合は、キャニー輪郭検出を行います。

于 2012-10-12T12:53:55.313 に答える
2

これは、OpenCV 自体では (簡単に) 解決できないブロブ処理の問題です。cvBlobsLib を見てください。このライブラリは、接続されたコンポーネントのラベル付けのための関数/クラスで OpenCV を拡張したものです。

http://opencv.willowgarage.com/wiki/cvBlobsLib

于 2012-10-12T12:24:22.230 に答える