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;
///
/// 一次:0/连续:1
///
public int Mode;
public int State;
///
/// 列数
///
public readonly int RowN;
///
/// 列数
///
public readonly int ColumnN;
///
/// 拼接率
///
public readonly double StitchRate;
Queue _matBuffer = new Queue();
public List _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();
///
/// 计算拼接方向
///
/// [1]右;[2]下;[3]左
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);
}
}
///
/// 等待拼图全部完成
///
public void Wait()
{
while (!IsDone)
{
Thread.Sleep(50);
}
}
public void Dispose()
{
IsDone = true;
Wait();
_matResult.Dispose();
GC.Collect();
}
///
/// 利用Opencv 将新图贴到大图上
///
///
///
///
///
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;
}
}
}