using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace OTSMeasureApp.ServiceCenter { using OpenCvSharp; public class ImageStitchUsingOpenCvSharp { #region 合并天宇颗粒融合新增函数 public Mat CombinImageX(Mat[] list_mats, int OverlapParam, int type) { List matStitch = new List();//拼接 List matCombin = new List();//合并 for (int i = 0; i < list_mats.Count(); i++) { if (i == 0)//首张 { matCombin.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, 0, list_mats[i].Width - OverlapParam - 100, list_mats[i].Height))); matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(list_mats[i].Width - OverlapParam - 100, 0, OverlapParam + 100, list_mats[i].Height))); } else if (i == list_mats.Count() - 1)//末张 { matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, 0, OverlapParam + 100, list_mats[i].Height))); matCombin.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(OverlapParam + 100, 0, list_mats[i].Width - OverlapParam - 100, list_mats[i].Height))); } else { matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, 0, OverlapParam + 100, list_mats[i].Height))); matCombin.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(OverlapParam + 100, 0, list_mats[i].Width - (OverlapParam + 100) * 2, list_mats[i].Height))); matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(list_mats[i].Width - OverlapParam - 100, 0, OverlapParam + 100, list_mats[i].Height))); } } for (int i = 0; i < matStitch.Count; i += 2) { if (matStitch.Count == 1) { matCombin.Insert(i + 1, matStitch[i]); } else { matCombin.Insert(i + 1, StitchImageX((int)(OverlapParam / 2 * 1.2), type, matStitch[i], matStitch[i + 1])); } } Mat pano = new OpenCvSharp.Mat(); Cv2.HConcat(matCombin.ToArray(), pano); return pano; } public Mat CombinImageY(Mat[] list_mats, int OverlapParam, int type) { List matStitch = new List();//拼接 List matCombin = new List();//合并 for (int i = 0; i < list_mats.Count(); i++) { if (i == 0)//首张 { matCombin.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, 0, list_mats[i].Width, list_mats[i].Height - OverlapParam - 100))); matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, list_mats[i].Height - OverlapParam - 100, list_mats[i].Width, OverlapParam + 100))); } else if (i == list_mats.Count() - 1)//末张 { matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, 0, list_mats[i].Width, OverlapParam + 100))); matCombin.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, OverlapParam + 100, list_mats[i].Width, list_mats[i].Height - OverlapParam - 100))); } else { matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, 0, list_mats[i].Width, OverlapParam + 100))); matCombin.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, OverlapParam + 100, list_mats[i].Width, list_mats[i].Height - (OverlapParam + 100) * 2))); matStitch.Add(new Mat(list_mats[i], new OpenCvSharp.Rect(0, list_mats[i].Height - OverlapParam - 100, list_mats[i].Width, OverlapParam + 100))); } } for (int i = 0; i < matStitch.Count; i += 2) { if (matStitch.Count == 1) { matCombin.Insert(i + 1, matStitch[i]); } else { matCombin.Insert(i + 1, StitchImageY(OverlapParam, type, matStitch[i], matStitch[i + 1])); } } Mat pano = new OpenCvSharp.Mat(); Cv2.VConcat(matCombin.ToArray(), pano); return pano; } public struct MStitch { public int Pwidth;//单幅图像的宽度 public int Pheight;//单幅图像的高度 public int W_min;//最小的重叠区域宽度 public int W_max;//最大的重叠区域宽度 public int H_min;//最小的重叠区域高度 public double minval;//块过滤阈值 public Mat im;//图像信息 } public struct ImageParam { public int W_box;//宽度信息 public int H_box;//高度信息 public int bdown;//上下信息 public MStitch mStitch; //参数结构 public Mat im;//图像信息 } /// /// 横向拼图 /// public Mat StitchImageXGrid(int min_w, int type, Mat newImg1, Mat newImg2) { MStitch mStitch = new MStitch(); mStitch.Pwidth = newImg1.Width; mStitch.Pheight = newImg1.Height; mStitch.W_min = min_w - 50; mStitch.W_max = min_w + 50; mStitch.H_min = newImg1.Height; mStitch.minval = 255; mStitch.im = newImg1; ImageParam imageParam = Fun_Match(newImg2, mStitch); imageParam.im = newImg2; if (type == 3) { return Fun_Stitch(imageParam); } else { return Fun_StitchRGB(imageParam); } } /// /// 纵向拼图 /// public Mat StitchImageYGrid(int min_w, int type, Mat newImg1, Mat newImg2) { Cv2.Transpose(newImg1, newImg1); Cv2.Flip(newImg1, newImg1, FlipMode.X); Cv2.Transpose(newImg2, newImg2); Cv2.Flip(newImg2, newImg2, FlipMode.X); MStitch mStitch = new MStitch(); mStitch.Pwidth = newImg1.Width; mStitch.Pheight = newImg1.Height; mStitch.W_min = min_w - 50; mStitch.W_max = min_w + 50; mStitch.H_min = newImg1.Height; mStitch.minval = 255; mStitch.im = newImg1; ImageParam imageParam = Fun_Match(newImg2, mStitch); imageParam.im = newImg2; Mat result = type == 3 ? Fun_Stitch(imageParam) : Fun_StitchRGB(imageParam); Cv2.Transpose(result, result); Cv2.Flip(result, result, FlipMode.Y); return result; } /// /// 横向拼图 /// public Mat StitchImageX(int min_w, int type, Mat newImg1, Mat newImg2) { MStitch mStitch = new MStitch(); mStitch.Pwidth = newImg1.Width; mStitch.Pheight = newImg1.Height; mStitch.W_min = min_w; mStitch.W_max = min_w; mStitch.H_min = newImg1.Height; mStitch.minval = 255; mStitch.im = newImg1; ImageParam imageParam = Fun_Match(newImg2, mStitch); imageParam.im = newImg2; if (type == 3) { return Fun_Stitch(imageParam); } else { return Fun_StitchRGB(imageParam); } } /// /// 纵向拼图 /// public Mat StitchImageY(int min_w, int type, Mat newImg1, Mat newImg2) { Cv2.Transpose(newImg1, newImg1); Cv2.Flip(newImg1, newImg1, FlipMode.X); Cv2.Transpose(newImg2, newImg2); Cv2.Flip(newImg2, newImg2, FlipMode.X); MStitch mStitch = new MStitch(); mStitch.Pwidth = newImg1.Width; mStitch.Pheight = newImg1.Height; mStitch.W_min = min_w - 50; mStitch.W_max = min_w - 50; mStitch.H_min = newImg1.Height - 20; mStitch.minval = 255; mStitch.im = newImg1; ImageParam imageParam = Fun_Match(newImg2, mStitch); imageParam.im = newImg2; Mat result = type == 2 ? Fun_Stitch(imageParam) : Fun_StitchRGB(imageParam); Cv2.Transpose(result, result); Cv2.Flip(result, result, FlipMode.Y); return result; } public static ImageParam Fun_Match(Mat im2, MStitch mStitch) { ImageParam imageParam = new ImageParam(); double imsum = 0; int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; int w_ind = 0; int h_ind = 0; // for (int w = mStitch.W_min; w <= mStitch.W_max; w++) { for (int h = mStitch.H_min; h <= mStitch.Pheight; h++) { imsum = 0;//块差分集初始化 x2 = 1; for (x1 = mStitch.Pwidth - w; x1 <= mStitch.Pwidth; x1 += 5) { y2 = 1; for (y1 = mStitch.Pheight - h + 1; y1 <= mStitch.Pheight; y1 += 5) { //块差分集计算 CheckRC(ref x1, ref y1, mStitch.im); CheckRC(ref x2, ref y2, im2); imsum = imsum + Math.Abs(mStitch.im.At(y1, x1).Item0 - im2.At(y2, x2).Item0); y2 = y2 + 5; } x2 = x2 + 5; } //阈值更新 if (imsum * 5 * 5 <= mStitch.minval * w * h) { mStitch.minval = imsum * 5 * 5 / (w * h); w_ind = w; h_ind = h; } } } imageParam.W_box = w_ind; imageParam.H_box = h_ind; imageParam.bdown = 1; //在下窗口所有匹配块内进行搜索 Parallel.For(mStitch.W_min, mStitch.W_max, w => { Parallel.For(mStitch.H_min, mStitch.Pheight, h => { imsum = 0;//块差分集初始化 x2 = 1; for (x1 = mStitch.Pwidth - w; x1 <= mStitch.Pwidth; x1 += 5) { y1 = 1; for (y2 = mStitch.Pheight - h + 1; y2 <= mStitch.Pheight; y2 += 5) { //块差分集计算 CheckRC(ref x1, ref y1, mStitch.im); CheckRC(ref x2, ref y2, im2); imsum = imsum + Math.Abs(mStitch.im.At(y1, x1).Item0 - im2.At(y2, x2).Item0); y1 = y1 + 5; } x2 = x2 + 5; } //阈值更新 if (imsum * 5 * 5 <= mStitch.minval * w * h) { mStitch.minval = imsum * 5 * 5 / (w * h); w_ind = w; h_ind = h; imageParam.bdown = 0; } }); }); imageParam.mStitch = mStitch; return imageParam; } public static void CheckRC(ref int x, ref int y, Mat im) { //图像矩阵访问有效性检测 // 输入参数: // x——列 // y——行 // im——图像矩阵 // 输出参数: // x——列 // y——行 y = Math.Max(y, 1); y = Math.Min(y, im.Height - 1); x = Math.Max(x, 1); x = Math.Min(x, im.Width - 1); } public Mat Fun_Stitch(ImageParam imageParam) { //图像融合 //输入参数: //im2——待融合图像 //W_box——宽度信息 //H_box——高度信息 //bdown——上下信息 //MStitch——参数结构 //输出参数: //MStitch——参数结构 //im——融合图像 Mat img = imageParam.im; int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; double w = 0.5; //融合权值 if (imageParam.bdown == 1) { //下区域重叠 x2 = 1; //融合重叠区域 for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++) { y2 = 1; for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++) { //安全性检测 CheckRC(ref x1, ref y1, imageParam.mStitch.im); CheckRC(ref x2, ref y2, imageParam.im); //融合权值 w = (double)x2 / (double)imageParam.W_box; //加权融合 double ColorRGB = imageParam.mStitch.im.At(y1, x1).Item0 * (1.0 - w) + imageParam.im.At(y2, x2).Item0 * w; imageParam.mStitch.im.Set(y1, x1, new Vec3b((byte)ColorRGB, (byte)ColorRGB, (byte)ColorRGB)); y2 = y2 + 1; } x2 = x2 + 1; } } else { //上区域重叠 x2 = 1; //融合重叠区域 for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++) { y2 = 1; for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++) { //安全性检测 CheckRC(ref x1, ref y1, imageParam.mStitch.im); CheckRC(ref x2, ref y2, imageParam.im); //融合权值 w = (double)x2 / (double)imageParam.W_box; //加权融合 double ColorRGB = imageParam.mStitch.im.At(y1, x1).Item0 * (1.0 - w) + imageParam.im.At(y2, x2).Item0 * w; imageParam.mStitch.im.Set(y1, x1, new Vec3b((byte)ColorRGB, (byte)ColorRGB, (byte)ColorRGB)); y2 = y2 + 1; } x2 = x2 + 1; } } //最终图 img = new Mat(imageParam.mStitch.Pheight, imageParam.mStitch.Pwidth + imageParam.im.Width - x2 + 1, MatType.CV_8UC3); //分离出重叠区域 OpenCvSharp.Rect m_select = new OpenCvSharp.Rect(x2 - 1, 0, imageParam.im.Width - x2 + 1, imageParam.mStitch.Pheight); Mat imgSwitch = new Mat(imageParam.im, m_select); Cv2.HConcat(imageParam.mStitch.im, imgSwitch, img); return img; } public Mat Fun_StitchRGB(ImageParam imageParam) { //图像融合 //输入参数: //im2——待融合图像 //W_box——宽度信息 //H_box——高度信息 //bdown——上下信息 //MStitch——参数结构 //输出参数: //MStitch——参数结构 //im——融合图像 Mat img = imageParam.im; int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; double w = 0.5; //融合权值 if (imageParam.bdown == 1) { //下区域重叠 x2 = 1; //融合重叠区域 for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++) { y2 = 1; for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++) { //安全性检测 CheckRC(ref x1, ref y1, imageParam.mStitch.im); CheckRC(ref x2, ref y2, imageParam.im); //融合权值 w = (double)x2 / (double)imageParam.W_box; //加权融合 double ColorR = imageParam.mStitch.im.At(y1, x1).Item0 * (1.0 - w) + imageParam.im.At(y2, x2).Item0 * w; double ColorG = imageParam.mStitch.im.At(y1, x1).Item1 * (1.0 - w) + imageParam.im.At(y2, x2).Item1 * w; double ColorB = imageParam.mStitch.im.At(y1, x1).Item2 * (1.0 - w) + imageParam.im.At(y2, x2).Item2 * w; if (imageParam.mStitch.im.At(y1, x1).Item0 == imageParam.mStitch.im.At(y1, x1).Item1 && imageParam.mStitch.im.At(y1, x1).Item1 == imageParam.mStitch.im.At(y1, x1).Item2 && imageParam.im.At(y2, x2).Item0 == imageParam.im.At(y2, x2).Item1 && imageParam.im.At(y2, x2).Item1 == imageParam.im.At(y2, x2).Item2) { imageParam.mStitch.im.Set(y1, x1, new Vec3b((byte)ColorR, (byte)ColorG, (byte)ColorB)); } else { } y2 = y2 + 1; } x2 = x2 + 1; } } else { //上区域重叠 x2 = 1; //融合重叠区域 for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++) { y2 = 1; for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++) { //安全性检测 CheckRC(ref x1, ref y1, imageParam.mStitch.im); CheckRC(ref x2, ref y2, imageParam.im); //融合权值 w = (double)x2 / (double)imageParam.W_box; //加权融合 double ColorR = imageParam.mStitch.im.At(y1, x1).Item0 * (1.0 - w) + imageParam.im.At(y2, x2).Item0 * w; double ColorG = imageParam.mStitch.im.At(y1, x1).Item1 * (1.0 - w) + imageParam.im.At(y2, x2).Item1 * w; double ColorB = imageParam.mStitch.im.At(y1, x1).Item2 * (1.0 - w) + imageParam.im.At(y2, x2).Item2 * w; if (imageParam.mStitch.im.At(y1, x1).Item0 == imageParam.mStitch.im.At(y1, x1).Item1 && imageParam.mStitch.im.At(y1, x1).Item1 == imageParam.mStitch.im.At(y1, x1).Item2 && imageParam.im.At(y2, x2).Item0 == imageParam.im.At(y2, x2).Item1 && imageParam.im.At(y2, x2).Item1 == imageParam.im.At(y2, x2).Item2) { imageParam.mStitch.im.Set(y1, x1, new Vec3b((byte)ColorR, (byte)ColorG, (byte)ColorB)); } else { } y2 = y2 + 1; } x2 = x2 + 1; } } //最终图 img = new Mat(imageParam.mStitch.Pheight, imageParam.mStitch.Pwidth + imageParam.im.Width - x2 + 1, MatType.CV_8UC3); //分离出重叠区域 OpenCvSharp.Rect m_select = new OpenCvSharp.Rect(x2 - 1, 0, imageParam.im.Width - x2 + 1, imageParam.mStitch.Pheight); Mat imgSwitch = new Mat(imageParam.im, m_select); Cv2.HConcat(imageParam.mStitch.im, imgSwitch, img); return img; } #endregion } }