void stitch(List <string> fileList, string saveFileName) { int n_rows = 4; int n_cols = 15; double or_hl = 0.23; // lower bound for horizontal overlap ratio double or_hu = 0.24; // upper double or_vl = 0.065; // vertical double or_vu = 0.08; double dr_hu = 0.01; // upper bound for horizontal drift ratio double dr_vu = 0.01; // Mat dst = null; Rectangle roi0 = new Rectangle(); //上一行第一张的区域 // first row Rectangle roi = new Rectangle(); // 左对齐的参考的区域 // first row for (int col = 0; col < n_cols; ++col) { Mat img = new Mat(fileList[col], Emgu.CV.CvEnum.LoadImageType.AnyColor); if (col == 0) { roi0 = new Rectangle(Convert.ToInt32(img.Cols * (n_cols - 1) * dr_hu), Convert.ToInt32(img.Rows * (n_rows - 1) * dr_vu), img.Cols, img.Rows); dst = new Mat(Convert.ToInt32(img.Rows * (n_rows + (n_rows - 1) * (dr_vu * 2 - or_vl))) + 100, Convert.ToInt32(img.Cols * (n_cols + (n_cols - 1) * (dr_hu * 2 - or_hl))) + 100, img.Depth, 3); // 第一张图不要0,0 最好留一些像素 roi = roi0; } else { AoiAi.stitchv2(dst.Ptr, roi, img.Ptr, ref roi, (int)AoiAi.side.left, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu)); } AoiAi.copy_to(dst.Ptr, img.Ptr, roi); //#region 这里去掉 CvInvoke.Resize(dst, dst, new Size(Convert.ToInt32(dst.Width * 0.3), Convert.ToInt32(dst.Height * 0.3))); CvInvoke.NamedWindow("AJpg", NamedWindowType.Normal); //创建一个显示窗口 CvInvoke.Imshow("AJpg", dst); char key = (char)CvInvoke.WaitKey(1); if (key == 0x1b || key == 'q') { continue; } //#endregion 这里去掉 } // other rows for (int row = 1; row < n_rows; ++row) { for (int col = 0; col < n_cols; ++col) { Mat img = new Mat(fileList[n_cols * row + col], Emgu.CV.CvEnum.LoadImageType.AnyColor); //std::cout << n_cols * row + col << "\n"; if (col == 0) { AoiAi.stitchv2(dst.Ptr, roi0, img.Ptr, ref roi0, (int)AoiAi.side.up, Convert.ToInt32(img.Cols * or_vl), Convert.ToInt32(img.Cols * or_vu), Convert.ToInt32(img.Rows * dr_hu)); roi = roi0; } else { AoiAi.stitchv2(dst.Ptr, roi, img.Ptr, ref roi, (int)AoiAi.side.left, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu), (int)AoiAi.side.up, Convert.ToInt32(img.Rows * or_vl), Convert.ToInt32(img.Rows * or_vu), Convert.ToInt32(img.Cols * dr_hu)); } AoiAi.copy_to(dst.Ptr, img.Ptr, roi); //#region 这里去掉 //CvInvoke.NamedWindow("AJpg", NamedWindowType.Normal); //创建一个显示窗口 //CvInvoke.Imshow("AJpg", dst); //char key = (char)CvInvoke.WaitKey(1); //if (key == 0x1b || key == 'q') continue; //#endregion 这里去掉 } } dst.Save(saveFileName); }
void stitch(OneSidePcb oneSidePcb) { double or_hl = 0.23; // lower bound for horizontal overlap ratio double or_hu = 0.24; // upper double or_vl = 0.065; // vertical double or_vu = 0.08; double dr_hu = 0.01; // upper bound for horizontal drift ratio double dr_vu = 0.01; // Bitmap bitmap = oneSidePcb.bitmaps.Dequeue(); Emgu.CV.Image <Bgr, Byte> currentFrame = new Emgu.CV.Image <Bgr, Byte>(bitmap); Mat imgOld = new Mat(); CvInvoke.BitwiseAnd(currentFrame, currentFrame, imgOld); int edge = 3; Mat img = new Mat(imgOld, new Rectangle(new Point(edge, edge), new Size(imgOld.Width - edge * 2, imgOld.Height - edge * 2))); //第一行 if (oneSidePcb.currentRow == 0) { if (oneSidePcb.currentCol == 0) { #region 判断s型还是z字形 if (oneSidePcb.zTrajectory) //Z形 { oneSidePcb.trajectorySide = (int)AoiAi.side.left; int x = Convert.ToInt32(img.Cols * (oneSidePcb.allCols - 1) * dr_hu); int y = Convert.ToInt32(img.Rows * (oneSidePcb.allRows - 1) * dr_vu); int dstRows = Convert.ToInt32(img.Rows * (oneSidePcb.allRows + (oneSidePcb.allRows - 1) * (dr_vu * 2 - or_vl))); int dstCols = Convert.ToInt32(img.Cols * (oneSidePcb.allCols + (oneSidePcb.allCols - 1) * (dr_hu * 2 - or_hl))); oneSidePcb.roi = new Rectangle(x, y, img.Cols, img.Rows); oneSidePcb.dst = new Mat(dstRows, dstCols, img.Depth, 3); // 第一张图不要0,0 最好留一些像素 } else // S型 { oneSidePcb.trajectorySide = (int)AoiAi.side.right; int dstRows = Convert.ToInt32(img.Rows * (oneSidePcb.allRows + (oneSidePcb.allRows - 1) * (dr_vu * 2 - or_vl))); int dstCols = Convert.ToInt32(img.Cols * (oneSidePcb.allCols + (oneSidePcb.allCols - 1) * (dr_hu * 2 - or_hl))); int x = Convert.ToInt32((dstCols - img.Cols) * (1 - dr_hu)); int y = Convert.ToInt32(img.Rows * (oneSidePcb.allRows - 1) * dr_vu); oneSidePcb.roi = new Rectangle(x, y, img.Cols, img.Rows); oneSidePcb.dst = new Mat(dstRows, dstCols, img.Depth, 3); // 第一张图不要0,0 最好留一些像素 } #endregion } else { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu)); } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); AoiAi.copy_to(oneSidePcb.dst.Ptr, img.Ptr, oneSidePcb.roi); //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); img.Dispose(); currentFrame.Dispose(); bitmap.Dispose(); oneSidePcb.currentCol++; if (oneSidePcb.currentCol >= oneSidePcb.allCols) { oneSidePcb.currentCol = 0; oneSidePcb.currentRow++; if (oneSidePcb.trajectorySide == (int)AoiAi.side.left) { oneSidePcb.trajectorySide = (int)AoiAi.side.right; } else if (oneSidePcb.trajectorySide == (int)AoiAi.side.right) { oneSidePcb.trajectorySide = (int)AoiAi.side.left; } } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\row1.jpg"); } else // 其他行 { if (Convert.ToBoolean(oneSidePcb.currentRow % 2)) //偶行 { if (oneSidePcb.currentCol == 0) { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, (int)AoiAi.side.up, Convert.ToInt32(img.Cols * or_vl), Convert.ToInt32(img.Cols * or_vu), Convert.ToInt32(img.Rows * dr_hu)); //oneSidePcb.roi = oneSidePcb.roi0; } else { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu), (int)AoiAi.side.up, Convert.ToInt32(img.Rows * or_vl), Convert.ToInt32(img.Rows * or_vu), Convert.ToInt32(img.Cols * dr_hu)); } } else { if (oneSidePcb.currentCol == 0) { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, (int)AoiAi.side.up, Convert.ToInt32(img.Cols * or_vl), Convert.ToInt32(img.Cols * or_vu), Convert.ToInt32(img.Rows * dr_hu)); //oneSidePcb.roi = oneSidePcb.roi0; } else { AoiAi.stitchv2(oneSidePcb.dst.Ptr, oneSidePcb.roi, img.Ptr, ref oneSidePcb.roi, oneSidePcb.trajectorySide, Convert.ToInt32(img.Cols * or_hl), Convert.ToInt32(img.Cols * or_hu), Convert.ToInt32(img.Rows * dr_vu), (int)AoiAi.side.up, Convert.ToInt32(img.Rows * or_vl), Convert.ToInt32(img.Rows * or_vu), Convert.ToInt32(img.Cols * dr_hu)); } } //oneSidePcb.dst.Save(@"C:\Users\Administrator\Desktop\suomi-test-img\" + oneSidePcb.currentRow + "-" + oneSidePcb.currentCol + ".jpg"); AoiAi.copy_to(oneSidePcb.dst.Ptr, img.Ptr, oneSidePcb.roi); img.Dispose(); currentFrame.Dispose(); bitmap.Dispose(); oneSidePcb.currentCol++; if (oneSidePcb.currentRow >= oneSidePcb.allRows - 1 && oneSidePcb.currentCol >= oneSidePcb.allCols) { sw.Stop(); TimeSpan ts = sw.Elapsed; Console.WriteLine("DateTime costed for Shuffle function is: {0}ms", ts.TotalMilliseconds); this.BeginInvoke(done); if (oneSidePcb.zTrajectory) { oneSidePcb.dst.Save(Path.Combine(savePath, "Front.jpg")); } else { oneSidePcb.dst.Save(Path.Combine(savePath, "Back.jpg")); } } else if (oneSidePcb.currentCol >= oneSidePcb.allCols) { oneSidePcb.currentCol = 0; oneSidePcb.currentRow++; if (oneSidePcb.trajectorySide == (int)AoiAi.side.left) { oneSidePcb.trajectorySide = (int)AoiAi.side.right; } else if (oneSidePcb.trajectorySide == (int)AoiAi.side.right) { oneSidePcb.trajectorySide = (int)AoiAi.side.left; } } } }