| 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;        }    }}
 |