2

私はまだ最後のプログラムに取り組んでおり、最終的に問題を解決する方法 (最大の輪郭をフィルタリングする方法) を見つけましたが、新しい質問、またはむしろ問題があります。

ご覧のとおり、ビデオのエッジを検索するために Canny アルゴリズムを使用しています。ただし、検出に使用するオブジェクトには特定の色がないため、オブジェクトの色が周囲の色とほぼ同じである場合 (たとえば、オブジェクトが銀で背景が白の場合)、オブジェクトのエッジが消えて取得できません。オブジェクトの輪郭。

今のところ、OpenCV で利用可能なすべてのエッジ フィルタリング アルゴリズムをテストしますが、作業を短くするために、 canny よりも最適な (または少なくとも優れた) アルゴリズムを推奨するためにあなたの助けが必要です。今、私はソーベルをテストしましたが、結果はキャニーのものよりも優れていません. 可能であれば、参照用の良い例にリンクしてください。

コード:

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;
    CvSeq* current_contour = contours;
    double largestArea = 0;
    CvSeq* largest_contour = NULL;
    while (current_contour != NULL){
        double area = fabs(cvContourArea(current_contour,CV_WHOLE_SEQ, false));       
        if(area > largestArea){
            largestArea = area;
            largest_contour = current_contour;
        }
        current_contour = current_contour->h_next;
    }

    cvMoments(largest_contour, &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&&m_00>=3000){
        printf("center point=(%.f, %.f), Area = %.f \n",gravityX,gravityY,m_00); }


    if(m_00>=3000){
        CvScalar color = CV_RGB(250,0,0);
        cvDrawContours(img,largest_contour,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);
}

...そして最後に、長い間待っていた例の写真:

まず、良いもの(私の黒い財布) 良いもの

第二に、失敗(オレンジ色のボックス) 失敗

最後に、別の失敗 (ホワイト ボックス) 白い失敗

PS、いくつかのメモ:

  • オブジェクトには特定の形状、色、またはサイズがないため、IMO の最善の策は、オブジェクトを色でフィルタリングするのではなく、オブジェクトのエッジを見つけることです。
  • オブジェクトを保持するので、指でオブジェクトのエッジを変更または非表示にすることができます。
  • 私はビデオ処理プログラムに取り組んでいるので、処理時間が短く、必要な処理能力が少ないほど良いです。
  • 私のプログラムは、最大の輪郭を除外し、赤色で塗りつぶします (最初の図を参照)。

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

4

1 に答える 1

1

あなたの問題はエッジ検出アルゴリズムではありません。あなたの問題は、アルゴリズム パラメーターをハード コーディングしていて、それがスローされたすべての画像に対して魔法のように機能することを期待していることです。また、cvCannyCanny オペレーターが既にスムージングを行っているため、使用前に画像をスムージングする必要はありません。

あなたが達成したいことが少し明確になったので、私は提案することができます: 各フレームを個別に見るのではなく、ビデオで作業してください. カメラが固定されていて、物体を持った手が動いている場合、形状の検出は背景減算によって簡単です。カメラが固定されていない場合でも、手を検出して(PDF リンク)、そこから作業することができます。また、その他のアプリケーション固有の知識を使用してください (たとえば、アイテムは画面の中央にあり、手はアイテムの下にあります)。

于 2012-10-22T12:28:18.527 に答える