public async Task <List <Mat> > GenerateTiles(Quilter quilter, int size, float overlapQuotient, int nIter) { int qSize = (int)(Math.Sqrt(2) * size); if (qSize % 2 == 0) { qSize++; } int overlap = (int)(qSize / (2 - overlapQuotient) * overlapQuotient); if (overlap % 2 == 0) { overlap++; } int bs = (qSize + overlap) / 2; int sSize = bs + overlap / 2; quilter.BlockSize = bs; quilter.Overlap = overlap; quilter.WangMode = true; //DEBUG quilter.RngSeed(42); float minCutErr = float.MaxValue; List <Mat> bestTiles = null; for (int k = 0; k < nIter; k++) { float cutErr = 0; List <Mat> currTiles = new List <Mat>(); List <Mat> vert = new List <Mat>(), horiz = new List <Mat>(); for (int i = 0; i < vertColors; i++) { vert.Add(quilter.GetRandomBlock(sSize)); } for (int i = 0; i < horizColors; i++) { horiz.Add(quilter.GetRandomBlock(sSize)); } for (int i = 0; i < tiles.Count; i++) { var tile = tiles[i]; quilter.Start(2, 2); Mat l = new Mat(horiz[tile.L], new CvRect(overlap / 2, overlap / 2, bs, bs)); Mat t = new Mat(vert[tile.T], new CvRect(0, overlap / 2, bs, bs)); Mat b = new Mat(vert[tile.B], new CvRect(overlap / 2, 0, bs, bs)); Mat r = new Mat(horiz[tile.R], new CvRect(0, 0, bs, bs)); quilter.Step(l); l.Dispose(); quilter.Step(t); t.Dispose(); quilter.Step(b); b.Dispose(); quilter.Step(r); r.Dispose(); cutErr += quilter.CutError; currTiles.Add(quilter.Quilt); if (cutErr >= minCutErr) { break; } //if (float.IsInfinity(cutErr) || cutErr > 5000) //{ //} } if (cutErr < minCutErr) { minCutErr = cutErr; if (bestTiles != null) { foreach (var m in bestTiles) { m.Dispose(); } } bestTiles = currTiles; } else { foreach (var m in currTiles) { m.Dispose(); } } if (k % 100 == 0) { System.Diagnostics.Debug.WriteLine($"{minCutErr} {cutErr}"); } foreach (var m in vert) { m.Dispose(); } foreach (var m in horiz) { m.Dispose(); } await Task.Delay(1); } List <Mat> turned = new List <Mat>(); //Remapping float[,] mapx = new float[size, size]; float[,] mapy = new float[size, size]; //float dxy = (0.5f * qSize - 0.5f * overlap) / size; //TODO: why not size + 1? //float x0 = 0.5f * qSize; //float y0 = 0.5f * overlap; float dxy = (0.5f * qSize - 0.5f) / size; //TODO: why not size + 1? float x0 = 0.5f * qSize; float y0 = 0.5f; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { mapx[i, j] = x0 + j * dxy; mapy[i, j] = y0 + j * dxy; } x0 -= dxy; y0 += dxy; } Mat mMapx = new Mat(size, size, MatType.CV_32FC1, mapx); Mat mMapy = new Mat(size, size, MatType.CV_32FC1, mapy); foreach (var m in bestTiles) { Mat tm = new Mat(size, size, MatType.CV_32FC3); Cv2.Remap(m, tm, mMapx, mMapy, OpenCvSharp.Interpolation.Cubic, OpenCvSharp.BorderType.Wrap); turned.Add(tm); m.Dispose(); } mMapx.Dispose(); mMapy.Dispose(); return(turned); }
async void Quilt() { //for (;;) //{ // Mat b1 = new Mat(16, 16, MatType.CV_32FC3, new Scalar(1, 1, 1)); // Mat b2 = new Mat(16, 16, MatType.CV_32FC3, new Scalar(1, 1, 1)); // Mat b = new Mat(16, 16, MatType.CV_32FC3, new Scalar(1, 1, 1)); // Cv2.Subtract(b1, b2, b); // b1.Dispose(); // b2.Dispose(); // b.Dispose(); // //GC.Collect(); //} //int size = 64; //int qSize = (int)Math.Round(Math.Sqrt(2) * size); //Mat m = new Mat(qSize, qSize, MatType.CV_32FC3, new Scalar(255,0,0)); //Cv2.FillPoly(m, new[] { new[] { new CvPoint(0.5f * qSize, 0), new CvPoint(qSize, 0.5f * qSize), new CvPoint(0.5f * qSize, qSize), new CvPoint(0, 0.5f * qSize) } }, new Scalar(0, 0, 255)); //Mat trans = Cv2.GetRotationMatrix2D(new Point2f(0.5f * qSize, 0.5f * qSize), -45, 1); //trans.Set<double>(0, 2, trans.At<double>(0, 2) - 0.5 * (qSize - size)); //trans.Set<double>(1, 2, trans.At<double>(1, 2) - 0.5 * (qSize - size)); //Mat tm = new Mat(); //Cv2.WarpAffine(m, tm, trans, new CvSize(size, size), OpenCvSharp.Interpolation.Linear); //Cv2.ImShow("Test", tm); //DEBUG //int size = 64; //int qSize = (int)Math.Round(Math.Sqrt(2) * size); //Mat m = new Mat(qSize, qSize, MatType.CV_32FC3, new Scalar(255,0,0)); //Cv2.FillPoly(m, new[] { new[] { new CvPoint(0.5f * qSize, 10), new CvPoint(qSize - 10, 0.5f * qSize), new CvPoint(0.5f * qSize, qSize - 10), new CvPoint(10, 0.5f * qSize) } }, new Scalar(0, 0, 255)); //float[,] mapx = new float[size, size]; //float[,] mapy = new float[size, size]; //float dxy = (0.5f * qSize - 0.5f) / (size + 1); //float x0 = 0.5f * (qSize - 1); //float y0 = 0; //for (int i = 0; i < size; i++) //{ // for (int j = 0; j < size; j++) // { // mapx[i, j] = x0 + j * dxy; // mapy[i, j] = y0 + j * dxy; // } // x0 -= dxy; // y0 += dxy; //} //Mat mMapx = new Mat(size, size, MatType.CV_32FC1, mapx); //Mat mMapy = new Mat(size, size, MatType.CV_32FC1, mapy); //Mat tm = new Mat(size, size, MatType.CV_32FC3); //Cv2.Remap(m, tm, mMapx, mMapy, OpenCvSharp.Interpolation.Cubic, OpenCvSharp.BorderType.Wrap); //Cv2.ImShow("Src", m); //Cv2.ImShow("Dst", tm); //return; //DEBUG var wangTiler = new WangTiler(3, 3, 31337); var q = new Quilter(); q.Sources = sources; //System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ThreadStart(() => //{ List <Mat> tiles = await wangTiler.GenerateTiles(q, BlockSize, 1f / 6, 1000); //} //)); //th.Start(); Mat result = wangTiler.FitTiles(16, 16, BlockSize, tiles); //Cv2.ImShow("Test", result); Mat quilted8U = new Mat(); result.ConvertTo(quilted8U, MatType.CV_8UC3, 255.0); WriteableBitmap quiltedBmp = quilted8U.ToWriteableBitmap(); Result = quiltedBmp; return; //foreach (var src in sources) //{ // if (BlockSize > src.Cols || BlockSize > src.Rows) // { // MessageBox.Show("Block Size exceeds one of the source's size, please reduce Block Size or reload the sources.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); // return; // } //} //Quilter q = new Quilter(); ////q.MatchTolerance = 100; //q.BlockSize = BlockSize; //q.Overlap = BlockSize / 6; //q.Sources = sources; //int step = q.BlockSize - q.Overlap; //int qw = (Width - q.Overlap - 1) / step + 1; //int qh = (Height - q.Overlap - 1) / step + 1; //q.Start(qw, qh); //for (;;) //{ // bool more = q.Step(); // Mat quilted8U = new Mat(); // q.Quilt.ConvertTo(quilted8U, MatType.CV_8UC3, 255.0); // WriteableBitmap quiltedBmp = quilted8U.ToWriteableBitmap(); // Result = quiltedBmp; // quilted8U.Dispose(); // await Task.Delay(1); // if (!more) break; //} //System.Diagnostics.Debug.WriteLine(q.CutError); }