using OpenCvSharp;
using PaintDotNet.Adjust.BaseImage;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace PaintDotNet.Adjust
{
///
/// 预处理 - 交互操作功能
///
public unsafe class PreActionIntent
{
///
/// 默认红色
///
private static Vec4b vec4B;
///
/// 全局的mat,用来做中间变量,但是需要注意销毁
///
private static Mat phaseTemp, phaseTemp1;
///
/// 目前用于删除时的中间变量颜色
///
private static int colorTemp;
///
/// 用于矩形删除的时候的中间变量
///
private static RectangleF rectangle;
///
/// 用于多边形删除的时候的中间变量
///
private static List pointsTemp;
private static Vec4b oldVec4B, newVec4B;
#region 提取
///
/// 单个提取
///
/// 源图像Mat
/// 选中的相的Mat,没有相或没有选中相为null
/// 双击的坐标点
///
public static Mat SingleExtract(Mat source, Mat phase, System.Drawing.PointF point, Vec4b vec4b)
{
try
{
vec4B = vec4b;
phaseTemp1 = new Mat();
if(phase==null)
{
phase = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
}
phaseTemp = new Mat(source.Rows + 2, source.Cols + 2, MatType.CV_8U, Scalar.All(0));
Mat sourceTemp = new Mat();
source.CopyTo(sourceTemp);
sourceTemp = sourceTemp.CvtColor(ColorConversionCodes.BGRA2BGR);
phase.CopyTo(phaseTemp1);
Rect rect = new Rect();
Cv2.FloodFill(sourceTemp, phaseTemp, new OpenCvSharp.Point(point.X, point.Y), new Scalar(255), out rect, null, null, FloodFillFlags.Link8 | FloodFillFlags.MaskOnly);
phaseTemp.ForEachAsByte(ForeachFunctionByteForChoise);
phaseTemp1.CopyTo(phase);
}
catch (Exception)
{
}
finally
{
if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
if (phaseTemp1 != null && !phaseTemp1.IsDisposed) phaseTemp1.Dispose();
}
return phase;
}
///
/// 单个提取的循环
///
///
///
public unsafe static void ForeachFunctionByteForChoise(byte* value, int* position)
{
int y = position[0];
int x = position[1];
byte intencity = *value;
if (intencity == 1 && x > 0 && y > 0 && x < phaseTemp.Width - 1 && y < phaseTemp.Height - 1)
{
phaseTemp1.Set(y - 1, x - 1, vec4B);
}
}
#endregion
#region 选择
///
/// 应用
///
///
///
///
public static Mat BinaryActionAntiConfirm(Mat phase, int color)
{
phaseTemp = new Mat();
phase.CopyTo(phaseTemp);
Color color1 = Color.FromArgb(color);
Color color2 = Color.FromArgb(255-color1.R, 255 - color1.G, 255 - color1.B);
oldVec4B = new Vec4b(color1.B, color1.G, color1.R, 255);
newVec4B = new Vec4b(color2.B, color2.G, color2.R, 255);
phase.ForEachAsVec4b(ForeachFunctionByteForConfirm);
phaseTemp.CopyTo(phase);
return phase;
}
private static void ForeachFunctionByteForConfirm(Vec4b* value, int* position)
{
int y = position[0];
int x = position[1];
if (value->Item0== oldVec4B.Item0 && value->Item1 == oldVec4B.Item1
&& value->Item2 == oldVec4B.Item2 && value->Item3 == oldVec4B.Item3)
{
phaseTemp.Set(y, x, new Vec4b(0,0,0,0));
}
else if(value->Item0 == newVec4B.Item0 && value->Item1 == newVec4B.Item1
&& value->Item2 == newVec4B.Item2 && value->Item3 == newVec4B.Item3)
{
phaseTemp.Set(y, x, oldVec4B);
}
}
///
/// 单个选择
///
///
///
///
///
public static Mat SingleChoise(Mat phase, int color, System.Drawing.Point point)
{
Color color1 = Color.FromArgb(color);
Mat[] arr = phase.Split();
Mat phase_temp = phase.CvtColor(ColorConversionCodes.BGRA2BGR);
Cv2.FloodFill(phase_temp, new OpenCvSharp.Point(point.X, point.Y), new Scalar(255-color1.B, 255-color1.G, 255-color1.R));
Mat[] arr1 = phase_temp.Split();
arr[0] = arr1[0];
arr[1] = arr1[1];
arr[2] = arr1[2];
Cv2.Merge(arr, phase);
return phase;
}
///
/// 矩形选择
///
///
///
///
public static Mat SingleChoiseRectangle(Mat phase, int color, System.Drawing.RectangleF rectangle)
{
Color color1 = Color.FromArgb(color);
Mat ImageROI = null, labels = null, stats = null, centroids = null;
try
{
float ax = rectangle.X, ay = rectangle.Y;
//处理矩形数据
if (rectangle.Width <= 0 || rectangle.Height <= 0)
{
System.Drawing.PointF p1 = new System.Drawing.PointF(rectangle.X, rectangle.Y);
System.Drawing.PointF p2 = new System.Drawing.PointF(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height);
if (rectangle.Width <= 0 && rectangle.Height > 0)
{
ax = p2.X;
ay = p1.Y;
}
else if (rectangle.Width > 0 && rectangle.Height <= 0)
{
ax = p1.X;
ay = p2.Y;
}
else if (rectangle.Width <= 0 && rectangle.Height <= 0)
{
ax = p2.X;
ay = p2.Y;
}
}
Mat[] arr = phase.Split();
//Cv2.Circle(phase, new OpenCvSharp.Point(ax, ay), 2, new Scalar(255), 3);
ImageROI = new Mat(phase, new Rect((int)ax, (int)ay, (int)Math.Abs(rectangle.Width), (int)Math.Abs(rectangle.Height)));
ImageROI = ImageROI.CvtColor(ColorConversionCodes.BGRA2GRAY);
labels = new Mat();
stats = new Mat();
centroids = new Mat();
phase = phase.CvtColor(ColorConversionCodes.BGRA2BGR);
//获取矩形内的连通分量,图像传矩形内的图片
int num = Cv2.ConnectedComponentsWithStats(ImageROI, labels, stats, centroids, PixelConnectivity.Connectivity8);
if (centroids != null)
{
for (int y = 1; y < centroids.Height; y++)
{
OpenCvSharp.Point p = new OpenCvSharp.Point();
p.X = Convert.ToInt32(centroids.At(y, 0)) + (int)ax;
p.Y = Convert.ToInt32(centroids.At(y, 1)) + (int)ay;
//Cv2.Circle(phase, p, 2, new Scalar(255), 3);
if (arr[3].At(p.Y, p.X) == 255)
{
Rect rect = new Rect();
Cv2.FloodFill(phase, p, new Scalar(255-color1.B, 255 - color1.G, 255 - color1.R), out rect, null, null, FloodFillFlags.Link8);
}
}
}
Mat[] arr1 = phase.Split();
arr[0] = arr1[0];
arr[1] = arr1[1];
arr[2] = arr1[2];
Cv2.Merge(arr, phase);
}
catch(Exception)
{
if (ImageROI != null && !ImageROI.IsDisposed) ImageROI.Dispose();
if (labels != null && !labels.IsDisposed) labels.Dispose();
if (stats != null && !stats.IsDisposed) stats.Dispose();
if (centroids != null && !centroids.IsDisposed) centroids.Dispose();
}
finally
{
}
return phase;
}
///
/// 椭圆选择
///
///
///
///
public static Mat SingleChoiseOval(Mat phase, int color, System.Drawing.RectangleF rect)
{
Color color1 = Color.FromArgb(color);
//提取椭圆的数据
Mat labels = null, stats = null, centroids = null;
try
{
float ax = rectangle.X, ay = rectangle.Y;
//处理矩形数据
if (rectangle.Width <= 0 || rectangle.Height <= 0)
{
System.Drawing.PointF p1 = new System.Drawing.PointF(rectangle.X, rectangle.Y);
System.Drawing.PointF p2 = new System.Drawing.PointF(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height);
if (rectangle.Width <= 0 && rectangle.Height > 0)
{
ax = p2.X;
ay = p1.Y;
}
else if (rectangle.Width > 0 && rectangle.Height <= 0)
{
ax = p1.X;
ay = p2.Y;
}
else if (rectangle.Width <= 0 && rectangle.Height <= 0)
{
ax = p2.X;
ay = p2.Y;
}
}
rectangle = rect;
vec4B = new Vec4b(255, 0, 0, 255);
Mat[] arr = phase.Split();
phaseTemp = new Mat(phase.Size(), phase.Type());
phase.ForEachAsVec4b(ForeachFunctionByteForOvalChoise);
labels = new Mat();
stats = new Mat();
centroids = new Mat();
phaseTemp = phaseTemp.CvtColor(ColorConversionCodes.BGRA2GRAY);
phase = phase.CvtColor(ColorConversionCodes.BGRA2BGR);
//获取矩形内的连通分量,图像传矩形内的图片
int num = Cv2.ConnectedComponentsWithStats(phaseTemp, labels, stats, centroids, PixelConnectivity.Connectivity8);
if (centroids != null)
{
for (int y = 1; y < centroids.Height; y++)
{
OpenCvSharp.Point p = new OpenCvSharp.Point();
p.X = Convert.ToInt32(centroids.At(y, 0));// + ax;
p.Y = Convert.ToInt32(centroids.At(y, 1));// + ay;
//Cv2.Circle(phase, p, 2, new Scalar(255,255,255), 3);
if (arr[3].At(p.Y, p.X) == 255)
{
Rect rect1 = new Rect();
Cv2.FloodFill(phase, p, new Scalar(255- color1.B, 255- color1.G, 255- color1.R), out rect1, null, null, FloodFillFlags.Link8);
}
}
}
Mat[] arr1 = phase.Split();
arr[0] = arr1[0];
arr[1] = arr1[1];
arr[2] = arr1[2];
Cv2.Merge(arr, phase);
}
catch (Exception)
{
if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
if (labels != null && !labels.IsDisposed) labels.Dispose();
if (stats != null && !stats.IsDisposed) stats.Dispose();
if (centroids != null && !centroids.IsDisposed) centroids.Dispose();
}
finally
{
}
return phase;
}
private static void ForeachFunctionByteForOvalChoise(Vec4b* value, int* position)
{
int y = position[0];
int x = position[1];
if (BaseTools.isPointInOval(new System.Drawing.Point(x, y),
new System.Drawing.PointF(rectangle.X + rectangle.Width / 2, rectangle.Y + rectangle.Height / 2),
rectangle.Width / 2,
rectangle.Height / 2
))
{
if (value->Item3 > 0)
{
phaseTemp.Set(y, x, new Vec4b(value->Item0, value->Item1, value->Item2, value->Item3));
}
}
}
//多边形选择
//https://blog.csdn.net/qq_31839479/article/details/53025067
public static Mat SingleChoisePolygon(Mat phase, int color, List points)
{
Color color1 = Color.FromArgb(color);
//提取椭圆的数据
Mat labels = null, stats = null, centroids = null;
try
{
float ax = rectangle.X, ay = rectangle.Y;
//处理矩形数据
if (rectangle.Width <= 0 || rectangle.Height <= 0)
{
System.Drawing.PointF p1 = new System.Drawing.PointF(rectangle.X, rectangle.Y);
System.Drawing.PointF p2 = new System.Drawing.PointF(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height);
if (rectangle.Width <= 0 && rectangle.Height > 0)
{
ax = p2.X;
ay = p1.Y;
}
else if (rectangle.Width > 0 && rectangle.Height <= 0)
{
ax = p1.X;
ay = p2.Y;
}
else if (rectangle.Width <= 0 && rectangle.Height <= 0)
{
ax = p2.X;
ay = p2.Y;
}
}
pointsTemp = points;
vec4B = new Vec4b(255, 0, 0, 255);
Mat[] arr = phase.Split();
phaseTemp = new Mat(phase.Size(), phase.Type());
phase.ForEachAsVec4b(ForeachFunctionByteForPolygonChoise);
labels = new Mat();
stats = new Mat();
centroids = new Mat();
phaseTemp = phaseTemp.CvtColor(ColorConversionCodes.BGRA2GRAY);
phase = phase.CvtColor(ColorConversionCodes.BGRA2BGR);
//获取矩形内的连通分量,图像传矩形内的图片
int num = Cv2.ConnectedComponentsWithStats(phaseTemp, labels, stats, centroids, PixelConnectivity.Connectivity8);
if (centroids != null)
{
for (int y = 1; y < centroids.Height; y++)
{
OpenCvSharp.Point p = new OpenCvSharp.Point();
p.X = Convert.ToInt32(centroids.At(y, 0));// + ax;
p.Y = Convert.ToInt32(centroids.At(y, 1));// + ay;
//Cv2.Circle(phase, p, 2, new Scalar(255,255,255), 3);
if (arr[3].At(p.Y, p.X) == 255)
{
Rect rect1 = new Rect();
Cv2.FloodFill(phase, p, new Scalar(255- color1.B, 255 - color1.G, 255 - color1.R), out rect1, null, null, FloodFillFlags.Link8);
}
}
}
Mat[] arr1 = phase.Split();
arr[0] = arr1[0];
arr[1] = arr1[1];
arr[2] = arr1[2];
Cv2.Merge(arr, phase);
}
catch (Exception)
{
if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
if (labels != null && !labels.IsDisposed) labels.Dispose();
if (stats != null && !stats.IsDisposed) stats.Dispose();
if (centroids != null && !centroids.IsDisposed) centroids.Dispose();
}
finally
{
}
return phase;
}
private static void ForeachFunctionByteForPolygonChoise(Vec4b* value, int* position)
{
int y = position[0];
int x = position[1];
//lock (obj)
//原来用region判断,但是多线程崩溃,只能加锁,所以改成射线法判断点是否在
//if (region.IsVisible(x, y))
if (BaseTools.isPointInPolygon(new System.Drawing.Point(x, y), pointsTemp))
{
if (value->Item3 > 0)
phaseTemp.Set(y, x, vec4B);
}
}
#endregion
#region 删除
///
/// 单个删除
///
///
public static Mat SingleDelete(Mat phase, System.Drawing.Point point, int color)
{
try
{
phaseTemp1 = new Mat();
vec4B = new Vec4b(0, 0, 0, 0);
Rect rect = new Rect();
Mat[] arr = phase.Split();
phaseTemp = phase.CvtColor(ColorConversionCodes.BGRA2BGR);
if (color == 0) { colorTemp = 1; }
else if (color == 255) { colorTemp = 254; }
else { colorTemp = color + 1; }
Cv2.FloodFill(phaseTemp, new OpenCvSharp.Point(point.X, point.Y), new Scalar(colorTemp, colorTemp, colorTemp), out rect, null, null, FloodFillFlags.Link8);
Mat[] arr1 = phaseTemp.Split();
arr[0] = arr1[0];
arr[1] = arr1[1];
arr[2] = arr1[2];
Cv2.Merge(arr, phaseTemp);
phaseTemp.CopyTo(phaseTemp1);
phaseTemp.ForEachAsVec4b(ForeachFunctionByteForDelete);
phaseTemp1.CopyTo(phase);
}
catch(Exception)
{
}
finally
{
if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
if (phaseTemp1 != null && !phaseTemp1.IsDisposed) phaseTemp1.Dispose();
}
return phase;
}
///
/// 矩形删除
///
///
///
///
public static Mat RectangleDelete(Mat phase, System.Drawing.RectangleF rect)
{
try
{
vec4B = new Vec4b(0, 0, 0, 0);
rectangle = rect;
phaseTemp = new Mat();
phase.CopyTo(phaseTemp);
phase.ForEachAsVec4b(ForeachFunctionByteForRectangleDelete);
phaseTemp.CopyTo(phase);
}
catch(Exception)
{
}
finally
{
if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
}
return phase;
}
///
/// 多边形删除
///
///
///
///
public static Mat PolygonDelete(Mat phase, List points)
{
try
{
pointsTemp = points;
vec4B = new Vec4b(0, 0, 0, 0);
phaseTemp = new Mat();
phase.CopyTo(phaseTemp);
phase.ForEachAsVec4b(ForeachFunctionByteForPolygonDelete);
phaseTemp.CopyTo(phase);
}
catch(Exception)
{
}
finally
{
if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
pointsTemp = null;
}
return phase;
}
///
/// 椭圆删除
///
///
///
///
public static Mat OvalDelete(Mat phase, System.Drawing.RectangleF rect)
{
try
{
vec4B = new Vec4b(0, 0, 0, 0);
rectangle = rect;
phaseTemp = new Mat();
phase.CopyTo(phaseTemp);
phase.ForEachAsVec4b(ForeachFunctionByteForOvalDelete);
phaseTemp.CopyTo(phase);
}
catch(Exception)
{
}
finally
{
if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
}
return phase;
}
///
/// 椭圆删除
///
///
///
private static void ForeachFunctionByteForOvalDelete(Vec4b* value, int* position)
{
int y = position[0];
int x = position[1];
if (BaseTools.isPointInOval(new System.Drawing.Point(x, y),
new System.Drawing.PointF(rectangle.X + rectangle.Width/2, rectangle.Y + rectangle.Height / 2),
rectangle.Width / 2,
rectangle.Height / 2
))
{
phaseTemp.Set(y, x, vec4B);
}
}
///
/// 多边形删除
///
///
///
private static void ForeachFunctionByteForPolygonDelete(Vec4b* value, int* position)
{
int y = position[0];
int x = position[1];
//lock (obj)
//原来用region判断,但是多线程崩溃,只能加锁,所以改成射线法判断点是否在
//if (region.IsVisible(x, y))
if (BaseTools.isPointInPolygon(new System.Drawing.Point(x, y), pointsTemp))
{
phaseTemp.Set(y, x, vec4B);
}
}
///
/// 矩形删除
///
///
///
private static void ForeachFunctionByteForRectangleDelete(Vec4b* value, int* position)
{
int y = position[0];
int x = position[1];
if(rectangle.Contains(x,y))
{
phaseTemp.Set(y, x, vec4B);
}
}
///
/// 单个删除的循环
///
///
///
private static void ForeachFunctionByteForDelete(Vec4b* value, int* position)
{
int y = position[0];
int x = position[1];
if (value->Item0 == colorTemp)
{
phaseTemp1.Set(y, x, vec4B);
}
}
#endregion
#region 分割
///
/// 直线分割
///
/// 相
/// 点
/// 颜色
///
public static Mat LineSplit(Mat phase, System.Drawing.PointF start, System.Drawing.PointF end, int width)
{
Cv2.Line(phase,
new OpenCvSharp.Point(start.X, start.Y),
new OpenCvSharp.Point(end.X, end.Y), new Scalar(0, 0, 0, 0), width, LineTypes.Link8);
return phase;
}
///
/// 椭圆分割
///
///
public static Mat EllipseSplit(Mat phase, System.Drawing.RectangleF rectangle, int width)
{
Point2f point2F = new Point2f(rectangle.X+ rectangle.Width/2, rectangle.Y + rectangle.Height/2);
Size2f size2F = new Size2f(Math.Abs(rectangle.Width), Math.Abs(rectangle.Height));
Cv2.Ellipse(phase, new RotatedRect(point2F, size2F, 0), new Scalar(0, 0, 0, 0), width, LineTypes.Link8);
return phase;
}
#endregion
#region 连接
///
/// 直线连接
///
///
///
///
///
///
public static Mat LineConnection(Mat phase, int color, System.Drawing.PointF start, System.Drawing.PointF end, int width)
{
Color color1 = Color.FromArgb(color);
Cv2.Line(phase,
new OpenCvSharp.Point(start.X, start.Y),
new OpenCvSharp.Point(end.X, end.Y), new Scalar(color1.B, color1.G, color1.R, 255), width, LineTypes.Link8);
return phase;
}
///
/// 椭圆连接
///
///
public static Mat EllipseConnection(Mat phase, int color, System.Drawing.RectangleF rectangle, int width)
{
Color color1 = Color.FromArgb(color);
Point2f point2F = new Point2f(rectangle.X + rectangle.Width / 2, rectangle.Y + rectangle.Height / 2);
Size2f size2F = new Size2f(Math.Abs(rectangle.Width), Math.Abs(rectangle.Height));
Cv2.Ellipse(phase, new RotatedRect(point2F, size2F, 0), new Scalar(color1.B, color1.G, color1.R, 255), width, LineTypes.Link8);
return phase;
}
#endregion
#region 添加
///
/// 椭圆添加
///
///
public static Mat EllipseAdd(Mat phase, int color, System.Drawing.RectangleF rectangle)
{
Color color1 = Color.FromArgb(color);
Point2f point2F = new Point2f(rectangle.X + rectangle.Width / 2, rectangle.Y + rectangle.Height / 2);
Size2f size2F = new Size2f(Math.Abs(rectangle.Width), Math.Abs(rectangle.Height));
Cv2.Ellipse(phase, new RotatedRect(point2F, size2F, 0), new Scalar(color1.B, color1.G, color1.R, 255), -1, LineTypes.Link8);
return phase;
}
///
/// 矩形添加
///
///
///
///
///
public static Mat RectangleAdd(Mat phase, int color, System.Drawing.RectangleF rectangle)
{
Color color1 = Color.FromArgb(color);
Cv2.Rectangle(phase, new Rect((int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height), new Scalar(color1.B, color1.G, color1.R, 255), -1, LineTypes.Link8);
return phase;
}
///
/// 多边形添加
///
/// 相
/// 相颜色
/// 多边形顶点集合
///
public static Mat PolygonAdd(Mat phase, int color, List points)
{
Color color1 = Color.FromArgb(color);
OpenCvSharp.Point[][] arr = new OpenCvSharp.Point[1][];
arr[0] = BaseTools.pointToPoint(points).ToArray();
Cv2.FillPoly(phase, arr, new Scalar(color1.B, color1.G, color1.R, 255), LineTypes.Link8);
return phase;
}
#endregion
}
}