/// <summary> /// Classical Multidimensional Scaling /// </summary> public void Run() { // creates distance matrix int size = CityDistance.GetLength(0); Mat t = new Mat(size, size, MatType.CV_64FC1, CityDistance); // adds Torgerson's additive constant to t double torgarson = Torgerson(t); t += torgarson; // squares all elements of t t = t.Mul(t); // centering matrix G Mat g = CenteringMatrix(size); // calculates inner product matrix B Mat b = g * t * g.T() * -0.5; // calculates eigenvalues and eigenvectors of B Mat values = new Mat(); Mat vectors = new Mat(); Cv2.Eigen(b, values, vectors); for (int r = 0; r < values.Rows; r++) { if (values.Get<double>(r) < 0) values.Set<double>(r, 0); } //Console.WriteLine(values.Dump()); // multiplies sqrt(eigenvalue) by eigenvector Mat result = vectors.RowRange(0, 2); { var at = result.GetGenericIndexer<double>(); for (int r = 0; r < result.Rows; r++) { for (int c = 0; c < result.Cols; c++) { at[r, c] *= Math.Sqrt(values.Get<double>(r)); } } } // scaling Cv2.Normalize(result, result, 0, 800, NormTypes.MinMax); // opens a window using (Mat img = Mat.Zeros(600, 800, MatType.CV_8UC3)) using (Window window = new Window("City Location Estimation")) { var at = result.GetGenericIndexer<double>(); for (int c = 0; c < size; c++) { double x = at[0, c]; double y = at[1, c]; x = x * 0.7 + img.Width * 0.1; y = y * 0.7 + img.Height * 0.1; img.Circle((int)x, (int)y, 5, Scalar.Red, -1); Point textPos = new Point(x + 5, y + 10); img.PutText(CityNames[c], textPos, HersheyFonts.HersheySimplex, 0.5, Scalar.White); } window.Image = img; Cv2.WaitKey(); } }