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();
}
}