123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- using OpenCvSharp.Extensions;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace PaintDotNet.Adjust
- {
- public class StitchingController
- {
- public int MathSelect = 3;
- /// <summary>
- /// 一次:0/连续:1
- /// </summary>
- public int Mode;
- public int State;
- /// <summary>
- /// 列数
- /// </summary>
- public readonly int RowN;
- /// <summary>
- /// 列数
- /// </summary>
- public readonly int ColumnN;
- /// <summary>
- /// 拼接率
- /// </summary>
- public readonly double StitchRate;
- Queue<Bitmap> _matBuffer = new Queue<Bitmap>();
- public List<Point> _offsetList;
- int _counterSum;
- int _counterDone;
- public Bitmap _img0;
- public Bitmap _img1;
- public int ImageWidth;
- public int ImageHeight;
- public OpenCvSharp.Mat _matResult;
- public System.Drawing.Bitmap Result
- {
- get { lock (lockobj) { return _matResult == null ? null : BitmapConverter.ToBitmap(_matResult); } }
- }
- public OpenCvSharp.Mat ResultMat
- {
- get { lock (lockobj) { return _matResult == null ? null : _matResult.Clone(); } }
- }
- public bool IsDone { get; private set; } = false;
- public Task StitchingTask;
- public StitchingController(int columnN, int rowN, double stitchRate)
- {
- ColumnN = columnN;
- RowN = rowN;
- StitchRate = stitchRate;
- Mode = 1;
- }
- public StitchingController(int columnN, double stitichRate, Bitmap[] mats)
- {
- ColumnN = columnN;
- RowN = mats.Length / ColumnN;
- foreach (var mat in mats) Add(mat);
- Mode = 0;
- }
- public void Add(Bitmap mat)
- {
- if (_counterDone == 0)//第一张
- {
- _img1 = mat;
- ImageWidth = mat.Width;
- ImageHeight = mat.Height;
- _matResult = BitmapConverter.ToMat(mat);
- _counterDone++;
- }
- else
- {
- _matBuffer.Enqueue(mat);
- }
- _counterSum++;
- }
- public void Start()
- {
- StitchingTask = new Task(Runtime);
- StitchingTask.Start();
- }
- public void Stop()
- {
- IsDone = true;
- }
- public void Runtime()
- {
- while (!IsDone)
- {
- if (Mode == 1 && _counterDone == ColumnN * RowN)
- {
- Stop();
- return;
- }
- if (_matBuffer.Count == 0)
- {
- if (Mode == 0)
- {
- Stop();
- return;
- }
- Thread.Sleep(50);
- }
- else
- {
- _img0 = _matBuffer.Dequeue();
- Stitch();
- _img1 = _img0;
- _counterDone++;
- }
- }
- }
- public void SynRun()
- {
- if (_matBuffer.Count == 0)
- {
- if (Mode == 0)
- {
- Stop();
- return;
- }
- }
- else
- {
- _img0 = _matBuffer.Dequeue();
- Stitch();
- _img1 = _img0;
- _counterDone++;
- }
- if (_counterDone == ColumnN * RowN)
- {
- Stop();
- }
- }
- public void Stitch()
- {
- bool error = true;
- Point movep = new Point(0, 0);
- int dir = Dir();
- Bitmap img0;
- Bitmap img1;
- //切图
- {
- switch (dir)
- {
- case 1:
- LastX += (int)(ImageWidth * (1 - StitchRate));
- img0 = AdjustIntent.Cut(_img0, StitchRate, AdjustIntent.Side.Left);
- img1 = AdjustIntent.Cut(_img1, StitchRate, AdjustIntent.Side.Right);
- break;
- case 2:
- LastY += (int)(ImageHeight * (1 - StitchRate));
- img0 = AdjustIntent.Cut(_img0, StitchRate, AdjustIntent.Side.Top);
- img1 = AdjustIntent.Cut(_img1, StitchRate, AdjustIntent.Side.Buttom);
- break;
- case 3:
- LastX -= (int)(ImageWidth * (1 - StitchRate));
- img0 = AdjustIntent.Cut(_img0, StitchRate, AdjustIntent.Side.Right);
- img1 = AdjustIntent.Cut(_img1, StitchRate, AdjustIntent.Side.Left);
- break;
- default:
- img0 = _img0;
- img1 = _img1;
- break;
- }
- }
- //拼接算法 1
- if (error && (MathSelect & 1) > 0)
- {
- int orbCount = img0.Width * img0.Height / 40000;
- movep = AdjustIntent.MatchOneBySift(
- BitmapConverter.ToMat(img0), BitmapConverter.ToMat(img1), out error, orbCount, 0.1, dir);
- }
- ////拼接算法 2
- if (error && (MathSelect & 2) > 0)
- {
- movep = VisualMath.Tools.MatchByAccordDotNet(img0, img1, out error);
- }
- //按位置偏移
- if (error)
- {
- #region 计算偏移
- movep = new Point(0, 0);
- }
- #endregion
- #region 拼接图片
- lock (lockobj)
- _matResult = MatMerge(BitmapConverter.ToMat(_img0), _matResult, movep);
- #endregion
- }
- private int LastX;
- private int LastY;
- private object lockobj = new object();
- /// <summary>
- /// 计算拼接方向
- /// </summary>
- /// <returns>[1]右;[2]下;[3]左</returns>
- private int Dir()
- {
- var rowIndex = _counterDone / ColumnN;
- var colIndex = _counterDone % ColumnN;
- var directionRect = 1;
- if (colIndex == 0)
- {
- directionRect = 2;
- }
- else if (rowIndex % 2 == 1)
- {
- directionRect = 3;
- }
- return directionRect;
- }
- private Point DefaultOffset()
- {
- int x = (int)(ImageWidth * StitchRate);
- int y = (int)(ImageHeight * StitchRate);
- int dir = Dir();
- switch (dir)
- {
- case 1:
- return new Point(x, 0);
- case 2:
- return new Point(0, y);
- case 3:
- return new Point(-x, 0);
- default:
- return new Point(0, 0);
- }
- }
- /// <summary>
- /// 等待拼图全部完成
- /// </summary>
- public void Wait()
- {
- while (!IsDone)
- {
- Thread.Sleep(50);
- }
- }
- public void Dispose()
- {
- IsDone = true;
- Wait();
- _matResult.Dispose();
- GC.Collect();
- }
- /// <summary>
- /// 利用Opencv 将新图贴到大图上
- /// </summary>
- /// <param name="matNew"></param>
- /// <param name="matBig"></param>
- /// <param name="point"></param>
- /// <returns></returns>
- public OpenCvSharp.Mat MatMerge(OpenCvSharp.Mat matNew, OpenCvSharp.Mat matBig, System.Drawing.Point point)
- {
- //LastX -= point.X;
- //LastY -= point.Y;
- var result = new OpenCvSharp.Mat();
- int srcOriX = 0;
- int srcOriY = 0;
- int newOriX = 0;
- int newOriY = 0;
- //得到变换矩阵后拼接图像
- int viewWidth = matBig.Width;// 2448;
- int viewHeight = matBig.Height;// 2040;
- if (LastX <= 0)
- {
- viewWidth = (int)(viewWidth - LastX);
- srcOriX = (int)(-LastX);
- newOriX = 0;
- LastX = 0;
- }
- else
- {
- viewWidth = (int)Math.Max(LastX + matNew.Width, matBig.Width);
- newOriX = (int)LastX;
- }
- if (LastY <= 0)
- {
- viewHeight = (int)(viewHeight - LastY);
- srcOriY = (int)(-LastY);
- newOriY = 0;
- LastY = 0;
- }
- else
- {
- newOriY = (int)LastY;
- viewHeight = (int)Math.Max(matBig.Height, matNew.Height + LastY);
- }
- result = new OpenCvSharp.Mat(new OpenCvSharp.Size(viewWidth, viewHeight), matNew.Type());
- OpenCvSharp.Mat tempMatSrc = matNew.Clone();
- //复制原有区域part1(<--用户选中的区域)到新图像(<--原图像)
- OpenCvSharp.Mat mask = tempMatSrc.CvtColor(OpenCvSharp.ColorConversionCodes.RGBA2GRAY);
- OpenCvSharp.Mat posSrc = new OpenCvSharp.Mat(result, new OpenCvSharp.Rect(newOriX, newOriY, matNew.Width, matNew.Height));
- tempMatSrc.CopyTo(posSrc, mask);//原图像复制到新图像
- OpenCvSharp.Mat tempMat = matBig.Clone();
- //复制原有区域part2(<--用户选中的区域)到新图像(<--原图像)
- mask = tempMat.CvtColor(OpenCvSharp.ColorConversionCodes.RGBA2GRAY);
- OpenCvSharp.Mat pos = new OpenCvSharp.Mat(result, new OpenCvSharp.Rect(srcOriX, srcOriY, matBig.Width, matBig.Height));
- tempMat.CopyTo(pos, mask);//原图像复制到新图像
- return result;
- }
- }
- }
|