public static Bitmap DrawTwoImages(Bitmap img1, Bitmap img2, List <ValueTuple <Descriptor, Descriptor> > match) { var offset = 20; var width = img1.Width + img2.Width + offset; var height = Math.Max(img1.Height, img2.Height) + offset; var result = new Bitmap(width + 2 * offset, height + 2 * offset); using (var g = Graphics.FromImage(result)) { g.DrawImage(img1, offset, offset, img1.Width, img1.Height); g.DrawImage(img2, 2 * offset + img1.Width, 2 * offset, img2.Width, img2.Height); } foreach (var(d1, d2) in match) { InterestingPoint from = d1.Point, to = d2.Point; DrawLine(result, offset + from.getX(), offset + from.getY(), (int)from.Radius, 2 * offset + to.getX() + img1.Width, 2 * offset + to.getY(), (int)to.Radius ); } return(result); }
private static List <int> GetInliers(List <ValueTuple <Descriptor, Descriptor> > matches, List <double> homography) { var inliers = new List <int>(); for (var i = 0; i < matches.Count; i++) { var match = matches[i]; InterestingPoint a = match.Item1.Point, b = match.Item2.Point; var point = Transform(homography, a.getX(), a.getY()); var distance = MathHelper.SqrtOfSqrSum(point.Item1 - b.getX(), point.Item2 - b.getY()); if (distance < Threshold) { inliers.Add(i); } } return(inliers); }
private static List <double> FindCurrentHomography(List <ValueTuple <Descriptor, Descriptor> > matches, List <int> choices, bool reverse) { double[,] Homography = new double[2 * choices.Count, MatrixWidth]; var index = 0; foreach (var value in choices) { var match = matches[value]; InterestingPoint a = match.Item1.Point, b = match.Item2.Point; if (reverse) { (a, b) = (b, a); } int i1 = 2 * index, i2 = 2 * index + 1; Homography[i1, 0] = a.getX(); Homography[i1, 1] = a.getY(); Homography[i1, 2] = 1; Homography[i1, 3] = 0; Homography[i1, 4] = 0; Homography[i1, 5] = 0; Homography[i1, 6] = -b.getX() * a.getX(); Homography[i1, 7] = -b.getX() * a.getY(); Homography[i1, 8] = -b.getX(); Homography[i2, 0] = 0; Homography[i2, 1] = 0; Homography[i2, 2] = 0; Homography[i2, 3] = a.getX(); Homography[i2, 4] = a.getY(); Homography[i2, 5] = 1; Homography[i2, 6] = -b.getY() * a.getX(); Homography[i2, 7] = -b.getY() * a.getY(); Homography[i2, 8] = -b.getY(); index++; } var m = Homography.GetLength(1); var n = Homography.GetLength(1); var k = Homography.GetLength(0); var mat = new double[m, n]; alglib.rmatrixgemm(m, n, k, 1, Homography, 0, 0, 1, Homography, 0, 0, 0, 0, ref mat, 0, 0 ); // SV decomposition. A = U * S * V^T m = mat.GetLength(0); n = mat.GetLength(1); alglib.rmatrixsvd(mat, m, n, 2, 0, 2, out var w, out var u, out _); var minIndex = Array.IndexOf(w, w.Min()); var scale = 1 / u[MatrixWidth - 1, minIndex]; var result = new List <double>(); for (var i = 0; i < MatrixWidth; i++) { result.Add(scale * u[i, minIndex]); } return(result); }
private static Vector CalculateForPointWithRotation(Mat gradient, Mat dx, Mat dy, double expScale, int gridSize, double radius, int binsCount, InterestingPoint center, double alpha, bool affine) { var centerX = center.getX() / (1 << center.Octave); var centerY = center.getY() / (1 << center.Octave); var size = (int)(radius * 2 + 1); var blockSize = size / gridSize; var step = 2 * Math.PI / binsCount; double cos = Math.Cos(-alpha), sin = Math.Sin(-alpha); var bins = new Dictionary <ValueTuple <int, int>, List <double> >(); for (var u = -radius; u < radius; u++) { for (var v = -radius; v < radius; v++) { int x = (int)(centerX + u), y = (int)(centerY + v); var magnitude = gradient.GetPixel(x, y, BorderWrapType.Wrap); var theta = Math.Atan2(dy.GetPixel(x, y, BorderWrapType.Wrap), dx.GetPixel(x, y, BorderWrapType.Wrap)); if (theta < 0) { theta += Math.PI * 2; } var rotatedU = u * cos + v * sin; var rotatedV = v * cos - u * sin; var row = (rotatedV + size / 2D) / blockSize; var column = (rotatedU + size / 2D) / blockSize; if (column < 0 || column >= gridSize || row < 0 || row >= gridSize) { continue; } magnitude *= Math.Exp(expScale * (rotatedU * rotatedU + rotatedV * rotatedV)); var rotatedTheta = theta + alpha; if (rotatedTheta > Math.PI * 2) { rotatedTheta -= Math.PI * 2; } var ratio = rotatedTheta % step / step; var leftBin = Math.Min((int)Math.Floor(rotatedTheta / step), binsCount - 1); var rightBin = (leftBin + 1) % binsCount; if (!bins.ContainsKey(((int)row, (int)column))) { bins.Add(((int)row, (int)column), Enumerable.Repeat(0D, binsCount).ToList()); } if (!affine) { PutToBins(bins, (int)row, (int)column, 1, leftBin, rightBin, ratio, magnitude); } else { var i = (int)row; if (row - i <= 0.5) { i--; } var j = (int)column; if (column - j <= 0.5) { j--; } var ki = 1 - Math.Abs(column - (j + 0.5)); var kj = 1 - Math.Abs(row - (i + 0.5)); PutToBins(bins, i, j, ki * kj, leftBin, rightBin, ratio, magnitude); PutToBins(bins, i, j + 1, (1 - ki) * kj, leftBin, rightBin, ratio, magnitude); PutToBins(bins, i + 1, j, ki * (1 - kj), leftBin, rightBin, ratio, magnitude); PutToBins(bins, i + 1, j + 1, (1 - ki) * (1 - kj), leftBin, rightBin, ratio, magnitude); } } } var result = new Vector(gridSize * gridSize * binsCount); for (var i = 0; i < gridSize; i++) { for (var j = 0; j < gridSize; j++) { for (var k = 0; k < binsCount; k++) { double value = 0; if (bins.ContainsKey((i, j))) { value = bins[(i, j)][k];