2017年9月27日水曜日

OpencvSharpでパノラマ画像を作成する

OpenCVでC++の場合のサンプルコードは沢山見かけるのですが、
C#版が無かったので投稿します。

Surfとかはライセンスの関係の問題でOpenCVに付属していないようです。
なので代わりにAKAZEを利用しています。

処理速度や特徴点抽出には申し分ないと思うのでコピペ利用でOKだと思います。



void hoge()
{
    var src = new Mat[2];
    var dst = new Mat[2];
    Mat outImg = new Mat();
    KeyPoint[] keypoints1;
    KeyPoint[] keypoints2;
    var descripter1 = new MatOfFloat();
    var descripter2 = new MatOfFloat();
    var result = new Mat();

    src[0] = Cv2.ImRead("2.JPG");
    src[1] = Cv2.ImRead("1.JPG");
    dst[0] = new Mat();
    dst[1] = new Mat();
    Cv2.CvtColor(src[0], dst[0], ColorConversionCodes.BGR2GRAY);
    Cv2.CvtColor(src[1], dst[1], ColorConversionCodes.BGR2GRAY);

    var akaze = AKAZE.Create();
    akaze.DetectAndCompute(dst[0], null, out keypoints1, descripter1);
    akaze.DetectAndCompute(dst[1], null, out keypoints2, descripter2);

    var matcher = new BFMatcher();
    var matches = matcher.Match(descripter1, descripter2);

    Cv2.DrawMatches(src[0], keypoints1, src[1], keypoints2, matches, outImg);

    using (new Window("OutImg", outImg))
    {
        Cv2.WaitKey();
    }

    //画像合体
    var size = matches.Length;
    var getPoints1 = new Vec2f[size];
    var getPoints2 = new Vec2f[size];

    for (var a = 0; a < size; a++)
    {
        var pt1 = keypoints1[matches[a].QueryIdx].Pt;
        var pt2 = keypoints2[matches[a].TrainIdx].Pt;
        getPoints1[a][0] = pt1.X;
        getPoints1[a][1] = pt1.Y;
        getPoints2[a][0] = pt2.X;
        getPoints2[a][1] = pt2.Y;
        Debug.WriteLine($"{pt2.X - pt1.X}, {pt2.Y - pt1.Y}");
    }

    var hom = Cv2.FindHomography(InputArray.Create(getPoints1), InputArray.Create(getPoints2), HomographyMethods.Ransac);

    Cv2.WarpPerspective(src[0], result, hom, new Size(src[0].Cols * 2.0, src[0].Rows * 2.0));
    for (int y = 0; y < src[0].Rows; y++)
    {
        for (int x = 0; x < src[0].Cols; x++)
        {
            result.Set(y, x, src[1].At<Vec3b>(y, x));
        }
    }

    using (new Window("result", result))
    {
        Cv2.WaitKey();
    }
}
コメントを投稿

Androider