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