17

「震え」関数を使用するmatlabのように速度ベクトルをプロットしようとしていますhttp://www.mathworks.com/help/techdoc/ref/quiver.html

OpenCV ライブラリを使用して、同じ方法論を C++ に移植する必要があります。

いくつかのオプティカル フロー法があると聞いたことがあります。たとえば、ルーカスとカナデ (cvCalOpticalFlowLK)、ホーンとシュンク (cvCalOpticalFlowHS)、またはブロック マッチング法 (cvCalOpticalFlowBM) です。

ただし、これらの関数はすべて 2 つの画像を使用しますが、指紋を処理しているため、1 つの画像を使用する必要があります。

親切に私を助けてください...

[編集] 解決策が見つかりました

void cvQuiver(IplImage*Image,int x,int y,int u,int v,CvScalar Color,
                                            int Size,int Thickness){
cv::Point pt1,pt2;
double Theta;
double PI = 3.1416;

if(u==0)
    Theta=PI/2;
else
    Theta=atan2(double(v),(double)(u));

pt1.x=x;
pt1.y=y;

pt2.x=x+u;
pt2.y=y+v;

cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line


Size=(int)(Size*0.707);


if(Theta==PI/2 && pt1.y > pt2.y)
    {
    pt1.x=(int)(Size*cos(Theta)-Size*sin(Theta)+pt2.x);
    pt1.y=(int)(Size*sin(Theta)+Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line

    pt1.x=(int)(Size*cos(Theta)+Size*sin(Theta)+pt2.x);
    pt1.y=(int)(Size*sin(Theta)-Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line
  }
else{
    pt1.x=(int)(-Size*cos(Theta)-Size*sin(Theta)+pt2.x);
    pt1.y=(int)(-Size*sin(Theta)+Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line

    pt1.x=(int)(-Size*cos(Theta)+Size*sin(Theta)+pt2.x);
    pt1.y=(int)(-Size*sin(Theta)-Size*cos(Theta)+pt2.y);
    cv::line(Image,pt1,pt2,Color,Thickness,8);  //Draw Line
    }

}
4

3 に答える 3

29

ここで現在の回答を完成させていますが、各矢印の先端の適切なサイズを指定できません。MATLAB では、次の図に示すように、矢印がほぼドットの場合は先端がなく、長い矢印の場合は大きな先端が表示されます。

ここに画像の説明を入力

この効果を得るには、矢印の長さの範囲で各矢印の「先端サイズ」を正規化する必要があります。次のコードはトリックを行います

    double l_max = -10;

    for (int y = 0; y < img_sz.height; y+=10)                                                           // First iteration, to compute the maximum l (longest flow)
    {
        for (int x = 0; x < img_sz.width; x+=10)
        {
            double dx = cvGetReal2D(velx, y, x);                                                        // Gets X component of the flow
            double dy = cvGetReal2D(vely, y, x);                                                        // Gets Y component of the flow

            CvPoint p = cvPoint(x, y);

            double l = sqrt(dx*dx + dy*dy);                                                             // This function sets a basic threshold for drawing on the image

            if(l>l_max) l_max = l;
        }
    }


    for (int y = 0; y < img_sz.height; y+=10)
{
    for (int x = 0; x < img_sz.width; x+=10)
    {
        double dx = cvGetReal2D(velx, y, x);                                                        // Gets X component of the flow
        double dy = cvGetReal2D(vely, y, x);                                                        // Gets Y component of the flow

        CvPoint p = cvPoint(x, y);

        double l = sqrt(dx*dx + dy*dy);                                                             // This function sets a basic threshold for drawing on the image
        if (l > 0)
        {
            double spinSize = 5.0 * l/l_max;                                                        // Factor to normalise the size of the spin depeding on the length of the arrow

            CvPoint p2 = cvPoint(p.x + (int)(dx), p.y + (int)(dy));
            cvLine(resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA);

            double angle;                                                                           // Draws the spin of the arrow
            angle = atan2( (double) p.y - p2.y, (double) p.x - p2.x );

            p.x = (int) (p2.x + spinSize * cos(angle + 3.1416 / 4));
            p.y = (int) (p2.y + spinSize * sin(angle + 3.1416 / 4));
            cvLine( resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA, 0 );

            p.x = (int) (p2.x + spinSize * cos(angle - 3.1416 / 4));
            p.y = (int) (p2.y + spinSize * sin(angle - 3.1416 / 4));
            cvLine( resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA, 0 );

        }
   }
}

これは、この OpenCV コードがどのように見えるかの例です

ここに画像の説明を入力

これが他の人が同じ問題をグーグルで検索するのに役立つことを願っています.

于 2012-06-06T19:26:09.443 に答える
4

cvCalOpticalFlowLKは速度ベクトルをプロットせず、これらの速度ベクトルを計算しますこれらのベクトルがない場合は、この関数を 2 つのイメージで呼び出す必要があります。既にこれらのベクトルがあり、それらをプロットしたいだけだと思います。

この場合、cv::line 関数を使用できます。次に例を示します。

cv::line(yourImage, cv::Point(baseX, baseY), cv::Point(endX, endY));

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

于 2012-04-15T16:00:42.540 に答える