| | |
| | | /// <summary> |
| | | /// 读写锁 |
| | | /// </summary> |
| | | public readonly object lockObj = new object(); |
| | | public static readonly object lockObj = new object(); |
| | | |
| | | /// <summary> |
| | | /// 裁切图片为hoDomainImage(保留原坐标系,其余填充为空) |
| | |
| | | { |
| | | if (InputImage is Bitmap) |
| | | { |
| | | Bitmap2Mat((Bitmap)InputImage, out Mat src); |
| | | TAlgorithm.Bitmap2Mat((Bitmap)InputImage, out Mat src); |
| | | |
| | | if (Params.Fixture == null) |
| | | Params.Fixture = new Fixture(); |
| | |
| | | |
| | | // 4. 创建与原图大小相同的Mat,并初始化无效值 |
| | | image = new Mat(src.Size(), src.Type()); |
| | | ((Mat)image).SetTo(GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | |
| | | // 5. 创建遮罩:在result上绘制旋转矩形(白色填充) |
| | | using (Mat cropped = new Mat(src, boundingRect)) |
| | |
| | | |
| | | // 2. 创建与原图大小相同的Mat,并初始化无效值 |
| | | image = new Mat(src.Size(), src.Type()); |
| | | ((Mat)image).SetTo(GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | |
| | | // 3. 创建圆形遮罩 |
| | | using (Mat mask = Mat.Zeros(src.Rows, src.Cols, MatType.CV_8UC1)) |
| | |
| | | image = ((Bitmap)InputImage)?.Clone(); |
| | | return true; |
| | | } |
| | | Mat2Bitmap((Mat)image, out Bitmap bmp); |
| | | TAlgorithm.Mat2Bitmap((Mat)image, out Bitmap bmp); |
| | | image = bmp; |
| | | return true; |
| | | } |
| | | else if (InputImage is HObject ho_image) |
| | | { |
| | | if (!ho_image.IsInitialized()) |
| | | return false; |
| | | |
| | | if (Params.Fixture == null) |
| | | Params.Fixture = new Fixture(); |
| | | |
| | | HObject hoDomainImage = null; |
| | | |
| | | switch (Params.ROI?.GetType().Name) |
| | | { |
| | | case "HRectangle2": |
| | | HOperatorSet.GenRectangle2(out HObject hRectangle2, (HTuple)(Params.ROI.Row + Params.Fixture.Row), (HTuple)(Params.ROI.Column + Params.Fixture.Column) |
| | | , (HTuple)(Params.ROI.Phi + Params.Fixture.Phi), (HTuple)((HRectangle2)Params.ROI).SemiLength1, (HTuple)((HRectangle2)Params.ROI).SemiLength2); |
| | | HOperatorSet.ReduceDomain(ho_image, hRectangle2, out hoDomainImage); |
| | | break; |
| | | case "HCircle": |
| | | HOperatorSet.GenCircle(out HObject hCircle, (HTuple)(Params.ROI.Row + Params.Fixture.Row), (HTuple)(Params.ROI.Column + Params.Fixture.Column) |
| | | , (HTuple)((HCircle)Params.ROI).Radius); |
| | | HOperatorSet.ReduceDomain(ho_image, hCircle, out hoDomainImage); |
| | | break; |
| | | case "ROI": |
| | | default: |
| | | image = ho_image.CopyObj(1, -1); |
| | | return true; |
| | | } |
| | | |
| | | image = hoDomainImage; |
| | | return true; |
| | | } |
| | | else if (InputImage is Mat) |
| | |
| | | |
| | | // 4. 创建与原图大小相同的Mat,并初始化无效值 |
| | | image = new Mat(src.Size(), src.Type()); |
| | | ((Mat)image).SetTo(GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | |
| | | // 5. 创建遮罩:在result上绘制旋转矩形(白色填充) |
| | | using (Mat cropped = new Mat(src, boundingRect)) |
| | |
| | | |
| | | // 2. 创建与原图大小相同的Mat,并初始化无效值 |
| | | image = new Mat(src.Size(), src.Type()); |
| | | ((Mat)image).SetTo(GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | ((Mat)image).SetTo(TAlgorithm.GetInvalidValueForMat(src)); // 全部初始化为无效值 |
| | | |
| | | // 3. 创建圆形遮罩 |
| | | using (Mat mask = Mat.Zeros(src.Rows, src.Cols, MatType.CV_8UC1)) |
| | |
| | | } |
| | | } |
| | | |
| | | public virtual bool ReduceDomainImage(object InputImage, ref HImage image) |
| | | { |
| | | image = null; |
| | | if (InputImage == null) |
| | | { |
| | | image = null; |
| | | Msg = "输入图片为空"; |
| | | Result = false; |
| | | return false; |
| | | } |
| | | |
| | | lock (InputImage) |
| | | { |
| | | try |
| | | { |
| | | if (InputImage is HImage ho_image) |
| | | { |
| | | if (!ho_image.IsInitialized()) |
| | | return false; |
| | | |
| | | if (Params.Fixture == null) |
| | | Params.Fixture = new Fixture(); |
| | | |
| | | HImage hoDomainImage = null; |
| | | |
| | | switch (Params.ROI?.GetType().Name) |
| | | { |
| | | case "HRectangle2": |
| | | using (HRegion hRectangle2 = new HRegion()) |
| | | { |
| | | hRectangle2.GenRectangle2((HTuple)(Params.ROI.Row + Params.Fixture.Row), (HTuple)(Params.ROI.Column + Params.Fixture.Column) |
| | | , (HTuple)(Params.ROI.Phi + Params.Fixture.Phi), (HTuple)((HRectangle2)Params.ROI).SemiLength1, (HTuple)((HRectangle2)Params.ROI).SemiLength2); |
| | | hoDomainImage = ho_image.ReduceDomain(hRectangle2); |
| | | } |
| | | break; |
| | | case "HCircle": |
| | | using (HRegion hCircle = new HRegion()) |
| | | { |
| | | hCircle.GenCircle((HTuple)(Params.ROI.Row + Params.Fixture.Row), (HTuple)(Params.ROI.Column + Params.Fixture.Column) |
| | | , (HTuple)((HCircle)Params.ROI).Radius); |
| | | hoDomainImage = ho_image.ReduceDomain(hCircle); |
| | | } |
| | | break; |
| | | case "ROI": |
| | | default: |
| | | image = ho_image.CopyObj(1, -1); |
| | | return true; |
| | | } |
| | | |
| | | image = hoDomainImage; |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | image = null; |
| | | Msg = $"输入格式不正确{InputImage.GetType()}"; |
| | | Result = false; |
| | | return false; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | image = null; |
| | | Msg = $"裁剪区域失败,原因是:{ex.ToString()}"; |
| | | Result = false; |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | public override void Dispose() |
| | | { |
| | | if (InputImage != null) |
| | | { |
| | | if (InputImage is HObject) |
| | | { |
| | | ((HObject)InputImage).Dispose(); |
| | | } |
| | | else if (InputImage is Mat) |
| | | { |
| | | ((Mat)InputImage).Dispose(); |
| | | } |
| | | else if (InputImage is Bitmap) |
| | | { |
| | | ((Bitmap)InputImage).Dispose(); |
| | | } |
| | | |
| | | InputImage = null; |
| | | } |
| | | |
| | | if (OutputImage != null) |
| | | { |
| | | if (OutputImage is HObject) |
| | | { |
| | | ((HObject)OutputImage).Dispose(); |
| | | } |
| | | else if (OutputImage is Mat) |
| | | { |
| | | ((Mat)OutputImage).Dispose(); |
| | | } |
| | | else if (OutputImage is Bitmap) |
| | | { |
| | | ((Bitmap)OutputImage).Dispose(); |
| | | } |
| | | |
| | | OutputImage = null; |
| | | } |
| | | |
| | | if (Record != null) |
| | | { |
| | | Record.Dispose(); |
| | |
| | | if (InputImage != null) |
| | | { |
| | | if (InputImage is HObject ho_image && ho_image.IsInitialized()) |
| | | { |
| | | obj.InputImage = ho_image.CopyObj(1, -1); |
| | | } |
| | | else if (InputImage is Mat mat && !mat.Empty()) |
| | | { |
| | | obj.InputImage = mat.Clone(); |
| | | } |
| | | else if (InputImage is Bitmap bitmap) |
| | | { |
| | | obj.InputImage = bitmap.Clone(); |
| | | } |
| | | } |
| | | |
| | | return obj; |
| | | } |
| | | catch { return (TAlgorithm)MemberwiseClone(); } |
| | |
| | | { |
| | | Result = true; |
| | | bCompleted = false; |
| | | Msg = string.Empty; |
| | | //if (InputImage != null) |
| | | //{ |
| | | // if (InputImage is HObject) |
| | | // { |
| | | // ((HObject)InputImage).Dispose(); |
| | | // } |
| | | // else if (InputImage is Mat) |
| | | // { |
| | | // ((Mat)InputImage).Dispose(); |
| | | // } |
| | | // else if (InputImage is Bitmap) |
| | | // { |
| | | // ((Bitmap)InputImage).Dispose(); |
| | | // } |
| | | // InputImage = null; |
| | | //} |
| | | if (Record != null) |
| | | Msg = ""; |
| | | if (OutputImage != null) |
| | | { |
| | | Record.Dispose(); |
| | | if (OutputImage is HObject) |
| | | ((HObject)OutputImage).Dispose(); |
| | | else if (OutputImage is Mat) |
| | | ((Mat)OutputImage).Dispose(); |
| | | else if (OutputImage is Bitmap) |
| | | ((Bitmap)OutputImage).Dispose(); |
| | | OutputImage = null; |
| | | } |
| | | |
| | | if (Record != null) |
| | | Record.Dispose(); |
| | | } |
| | | |
| | | public override bool Run() |
| | | { |
| | | DateTime StartTime = DateTime.Now; |
| | | |
| | | InitRunParams(); |
| | | HOperatorSet.GenEmptyObj(out HObject EmptyObj); |
| | | OutputImage = EmptyObj; |
| | |
| | | |
| | | Thread.Sleep(30); |
| | | } |
| | | |
| | | Msg = "运行超时"; |
| | | Result = false; |
| | | RunTime = (DateTime.Now - StartTime).TotalMilliseconds; |
| | |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(fullPath)) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | if (!fullPath.Contains(".json")) |
| | | { |
| | | Debug.WriteLine("文件路径不完整"); |
| | |
| | | Debug.WriteLine("文件路径不完整"); |
| | | return false; |
| | | } |
| | | |
| | | // 获取不带文件名的目录路径 |
| | | string directoryPath = Path.GetDirectoryName(fullPath); |
| | | strProcessName = Path.GetFileNameWithoutExtension(fullPath); |
| | |
| | | Save(directoryPath); |
| | | return true; |
| | | } |
| | | |
| | | string strJson = string.Empty; |
| | | using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8)) |
| | | { |
| | |
| | | } |
| | | Params = JsonConvert.DeserializeObject<ProcessParams>(strJson); |
| | | if (Params == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | Params.FixDeserializedData(); |
| | | return true; |
| | | } |
| | |
| | | return value; |
| | | } |
| | | |
| | | public static HImage Bitmap2HImage(Bitmap bmp) |
| | | public static void Bitmap2HObject(Bitmap bmp, out HObject image) |
| | | { |
| | | BitmapData srcBmpData; |
| | | HImage image = null; |
| | | |
| | | try |
| | | { |
| | | if (bmp.Tag == null || bmp == null || bmp.Width == 0 || bmp.Height == 0) |
| | | if (bmp == null || bmp.Width == 0 || bmp.Height == 0) |
| | | { |
| | | image = null; |
| | | return image; |
| | | return; |
| | | } |
| | | |
| | | lock (bmp) |
| | | { |
| | | image = new HImage(); |
| | | switch (bmp.PixelFormat) |
| | | { |
| | | case PixelFormat.Format24bppRgb: |
| | |
| | | int width = bmp.Width; |
| | | int height = bmp.Height; |
| | | int stride = srcBmpData.Stride; |
| | | |
| | | if (stride == width * 3) |
| | | { |
| | | image.GenImageInterleaved(srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0); |
| | | } |
| | | HOperatorSet.GenImageInterleaved(out image, srcBmpData.Scan0, "bgr", bmp.Width, bmp.Height, 0, "byte", 0, 0, 0, 0, -1, 0); |
| | | else |
| | | { |
| | | image = HandleStrideAlignmentBest(srcBmpData.Scan0, width, height, stride); |
| | | } |
| | | |
| | | bmp.UnlockBits(srcBmpData); |
| | | break; |
| | | default: |
| | | srcBmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); |
| | | image.GenImage1("byte", bmp.Width, bmp.Height, srcBmpData.Scan0); |
| | | HOperatorSet.GenImage1(out image, "byte", bmp.Width, bmp.Height, srcBmpData.Scan0); |
| | | bmp.UnlockBits(srcBmpData); |
| | | break; |
| | | } |
| | | } |
| | | return image; |
| | | return; |
| | | } |
| | | catch |
| | | { |
| | | if (image != null) |
| | | { |
| | | image.Dispose(); |
| | | } |
| | | image = null; |
| | | return image; |
| | | return; |
| | | } |
| | | } |
| | | |
| | | private static HImage HandleStrideAlignmentBest(IntPtr scan0, int width, int height, int stride) |
| | | private static HObject HandleStrideAlignmentBest(IntPtr scan0, int width, int height, int stride) |
| | | { |
| | | int expectedStride = width * 3; |
| | | byte[] alignedData = new byte[width * height * 3]; |
| | | HImage image = new HImage(); |
| | | |
| | | unsafe |
| | | { |
| | | byte* srcPtr = (byte*)scan0; |
| | |
| | | expectedStride |
| | | ); |
| | | } |
| | | image.GenImageInterleaved(new IntPtr(dstPtr), "bgr", width, height, 0, "byte", width, height, 0, 0, -1, 0); |
| | | return image; |
| | | HOperatorSet.GenImageInterleaved(out HObject ho_img, new IntPtr(dstPtr), "bgr", width, height, 0, "byte", width, height, 0, 0, -1, 0); |
| | | return ho_img; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static unsafe void HImage2Bitmap(HImage hImage, out Bitmap bmp) |
| | | public static unsafe void HObject2Bitmap(HObject hObject, out Bitmap bmp) |
| | | { |
| | | try |
| | | { |
| | | if (hImage == null || !hImage.IsInitialized()) |
| | | if (hObject == null || !hObject.IsInitialized()) |
| | | { |
| | | bmp = null; |
| | | return; |
| | | } |
| | | |
| | | // 获取图像信息 |
| | | hImage.GetImageSize(out HTuple width, out HTuple height); |
| | | HTuple channels = hImage.CountChannels(); |
| | | HOperatorSet.GetImageSize(hObject, out HTuple width, out HTuple height); |
| | | HOperatorSet.CountChannels(hObject, out HTuple channels); |
| | | |
| | | if (channels.I == 1) |
| | | { |
| | | // 灰度图处理 |
| | | HTuple ptr, type; |
| | | ptr = hImage.GetImagePointer1(out type, out width, out height); |
| | | HOperatorSet.GetImagePointer1(hObject, out ptr, out type, out width, out height); |
| | | |
| | | bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed); |
| | | |
| | |
| | | { |
| | | // 彩色图处理(BGR顺序) |
| | | HTuple ptrR, ptrG, ptrB, type; |
| | | hImage.GetImagePointer3(out ptrR, out ptrG, out ptrB, out type, out width, out height); |
| | | HOperatorSet.GetImagePointer3(hObject, out ptrR, out ptrG, out ptrB, out type, out width, out height); |
| | | |
| | | bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); |
| | | BitmapData bmpData = bmp.LockBits( |
| | |
| | | } |
| | | } |
| | | |
| | | public static HImage Mat2HImage(Mat mat) |
| | | public static void Mat2HObject(Mat mat, out HObject image) |
| | | { |
| | | HImage image = null; |
| | | try |
| | | { |
| | | if (mat == null || mat.Empty()) |
| | | { |
| | | return image; |
| | | image = null; |
| | | return; |
| | | } |
| | | |
| | | if (mat.Type() == MatType.CV_8UC3) // 彩色图像 (BGR) |
| | | { |
| | | image = new HImage(); |
| | | image.GenImageInterleaved( |
| | | HOperatorSet.GenImageInterleaved( |
| | | out image, |
| | | mat.Data, |
| | | "bgr", |
| | | mat.Width, |
| | |
| | | } |
| | | else if (mat.Type() == MatType.CV_8UC1) // 灰度图像 |
| | | { |
| | | image = new HImage(); |
| | | image.GenImage1( |
| | | HOperatorSet.GenImage1( |
| | | out image, |
| | | "byte", |
| | | mat.Width, |
| | | mat.Height, |
| | |
| | | else |
| | | { |
| | | throw new ArgumentException($"Mat2HObject不支持的图像格式:{mat.Type()}"); |
| | | return; |
| | | } |
| | | return image; |
| | | return; |
| | | } |
| | | catch |
| | | { |
| | | image = null; |
| | | return image; |
| | | return; |
| | | } |
| | | } |
| | | |
| | |
| | | HOperatorSet.GenImageConst(out image, "real", hv_xMax + 1, hv_yMax + 1); |
| | | HOperatorSet.SetGrayval(image, hv_y, hv_x, hv_z); |
| | | |
| | | //hoperatorset.getimagesize(ho_image, out htuple hv_width, out htuple hv_height); |
| | | //hoperatorset.genrectangle1(out hobject ho_rectangle, 0, 0, hv_height - 1, hv_width - 1); |
| | | //hoperatorset.getregionpoints(ho_rectangle, out htuple hv_rows, out htuple hv_columns); |
| | | //hoperatorset.getgrayval(ho_image, hv_rows, hv_columns, out htuple hv_z); |
| | | //HOperatorSet.GetImageSize(ho_Image, out HTuple hv_Width, out HTuple hv_Height); |
| | | //HOperatorSet.GenRectangle1(out HObject ho_Rectangle, 0, 0, hv_Height - 1, hv_Width - 1); |
| | | //HOperatorSet.GetRegionPoints(ho_Rectangle, out HTuple hv_Rows, out HTuple hv_Columns); |
| | | //HOperatorSet.GetGrayval(ho_Image, hv_Rows, hv_Columns, out HTuple hv_Z); |
| | | } |
| | | catch { image = null; } |
| | | } |
| | |
| | | /// <param name="startPoint"></param> |
| | | /// <param name="endPoint"></param> |
| | | /// <returns></returns> |
| | | public double GetDistanceP2P(HPoint startPoint, HPoint endPoint) |
| | | public static double GetDistanceP2P(HPoint startPoint, HPoint endPoint) |
| | | { |
| | | try |
| | | { |
| | |
| | | catch { return 9994; } |
| | | } |
| | | |
| | | public double GetDistanceP2P(Point startPoint, Point endPoint) |
| | | public static double GetDistanceP2P(Point startPoint, Point endPoint) |
| | | { |
| | | return GetDistanceP2P(new HPoint(startPoint), new HPoint(endPoint)); |
| | | } |
| | | |
| | | public double DistanceP2P(double startX, double startY, double endX, double endY) |
| | | public static double DistanceP2P(double startX, double startY, double endX, double endY) |
| | | { |
| | | return GetDistanceP2P(new HPoint(startX, startY), new HPoint(endX, endY)); |
| | | } |
| | |
| | | /// <param name="startPoint"></param> |
| | | /// <param name="endPoint"></param> |
| | | /// <returns></returns> |
| | | public HPoint GetMidPoint(HPoint startPoint, HPoint endPoint) |
| | | public static HPoint GetMidPoint(HPoint startPoint, HPoint endPoint) |
| | | { |
| | | return new HPoint((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2); |
| | | } |
| | | |
| | | public Point GetMidPoint(Point startPoint, Point endPoint) |
| | | public static Point GetMidPoint(Point startPoint, Point endPoint) |
| | | { |
| | | return new Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2); |
| | | } |
| | | |
| | | public System.Drawing.Point GetMidPoint(System.Drawing.Point startPoint, System.Drawing.Point endPoint) |
| | | public static System.Drawing.Point GetMidPoint(System.Drawing.Point startPoint, System.Drawing.Point endPoint) |
| | | { |
| | | return new System.Drawing.Point((startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2); |
| | | } |
| | |
| | | /// <param name="point"></param> |
| | | /// <param name="segment"></param> |
| | | /// <returns></returns> |
| | | public bool IsPointOnSegment(HPoint pt, HSegment segment, double tolerance = 1e-3) |
| | | public static bool IsPointOnSegment(HPoint pt, HSegment segment, double tolerance = 1e-3) |
| | | { |
| | | // 计算直线方程的系数 |
| | | double A = segment.EndY - segment.StartX; |
| | |
| | | return false; |
| | | } |
| | | |
| | | public bool IsPointOnSegment(double px, double py, double x1, double y1, double x2, double y2) |
| | | public static bool IsPointOnSegment(double px, double py, double x1, double y1, double x2, double y2) |
| | | { |
| | | return IsPointOnSegment(new HPoint(px, py), new HSegment(x1, y1, x2, y2)); |
| | | } |
| | |
| | | catch { return false; } |
| | | } |
| | | |
| | | public bool IsPointNearRectangleSilde(HPoint pt, HRectangle2 rect, double tolerance = 100) |
| | | public static bool IsPointNearRectangleSilde(HPoint pt, HRectangle2 rect, double tolerance = 100) |
| | | { |
| | | return IsPointNearRectangleSilde(new System.Drawing.Point((int)pt.X, (int)pt.Y), new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height), tolerance); |
| | | } |
| | |
| | | /// <param name="pt2"></param> |
| | | /// <param name="tolerance"></param> |
| | | /// <returns></returns> |
| | | public bool IsPointNearPoint(HPoint pt1, HPoint pt2, double tolerance = 100) |
| | | public static bool IsPointNearPoint(HPoint pt1, HPoint pt2, double tolerance = 100) |
| | | { |
| | | if (GetDistanceP2P(pt1, pt2) <= tolerance) |
| | | return true; |
| | | return false; |
| | | } |
| | | |
| | | public bool IsPointNearPoint(Point pt1, Point pt2, double tolerance = 100) |
| | | public static bool IsPointNearPoint(Point pt1, Point pt2, double tolerance = 100) |
| | | { |
| | | if (GetDistanceP2P(pt1, pt2) <= tolerance) |
| | | return true; |
| | | return false; |
| | | } |
| | | |
| | | public bool IsPointNearPoint(double x1, double y1, double x2, double y2, int tolerance = 100) |
| | | public static bool IsPointNearPoint(double x1, double y1, double x2, double y2, int tolerance = 100) |
| | | { |
| | | return IsPointNearPoint(new HPoint(x1, y1), new HPoint(x2, y2), tolerance); |
| | | } |
| | |
| | | /// <param name="corner"></param> |
| | | /// <param name="tolerance"></param> |
| | | /// <returns></returns> |
| | | public bool IsPointNearRectangleCorner(Point pt, Rectangle rect, out string corner, double tolerance = 10) |
| | | public static bool IsPointNearRectangleCorner(Point pt, Rectangle rect, out string corner, double tolerance = 10) |
| | | { |
| | | try |
| | | { |
| | |
| | | catch { corner = ""; return false; } |
| | | } |
| | | |
| | | public bool IsPointNearRectangleCorner(HPoint pt, HRectangle2 rect, out string corner, double tolerance = 10) |
| | | public static bool IsPointNearRectangleCorner(HPoint pt, HRectangle2 rect, out string corner, double tolerance = 10) |
| | | { |
| | | try |
| | | { |
| | |
| | | /// <param name="p3">线2起始点</param> |
| | | /// <param name="p4"></param> |
| | | /// <returns></returns> |
| | | public Point2d? GetLineIntersection(Point2d p1, Point2d p2, Point2d p3, Point2d p4, bool bOnSegment = false) |
| | | public static Point2d? GetLineIntersection(Point2d p1, Point2d p2, Point2d p3, Point2d p4, bool bOnSegment = false) |
| | | { |
| | | // 直线1的向量 |
| | | double x1 = p1.X, y1 = p1.Y; |
| | |
| | | #region Halcon |
| | | // Chapter: Graphics / Output |
| | | // Short Description: Display 3D object models |
| | | public void visualize_object_model_3d(HTuple hv_WindowHandle, HTuple hv_ObjectModel3D, |
| | | public static void visualize_object_model_3d(HTuple hv_WindowHandle, HTuple hv_ObjectModel3D, |
| | | HTuple hv_CamParam, HTuple hv_PoseIn, HTuple hv_GenParamName, HTuple hv_GenParamValue, |
| | | HTuple hv_Title, HTuple hv_Label, HTuple hv_Information, out HTuple hv_PoseOut) |
| | | { |
| | |
| | | |
| | | // Chapter: Calibration / Camera Parameters |
| | | // Short Description: Set the value of a specified camera parameter in the camera parameter tuple. |
| | | public void set_cam_par_data(HTuple hv_CameraParamIn, HTuple hv_ParamName, HTuple hv_ParamValue, |
| | | public static void set_cam_par_data(HTuple hv_CameraParamIn, HTuple hv_ParamName, HTuple hv_ParamValue, |
| | | out HTuple hv_CameraParamOut) |
| | | { |
| | | // Local iconic variables |
| | |
| | | } |
| | | } |
| | | |
| | | public void gen_arrow_contour_xld(out HObject ho_Arrow, HTuple hv_Row1, HTuple hv_Column1, |
| | | public static void gen_arrow_contour_xld(out HObject ho_Arrow, HTuple hv_Row1, HTuple hv_Column1, |
| | | HTuple hv_Row2, HTuple hv_Column2, HTuple hv_HeadLength, HTuple hv_HeadWidth) |
| | | { |
| | | // Stack for temporary objects |
| | |
| | | } |
| | | } |
| | | |
| | | public void get_rect2_vertex(HTuple hv_Row, HTuple hv_Column, HTuple hv_Phi, HTuple hv_Length1, |
| | | public static void get_rect2_vertex(HTuple hv_Row, HTuple hv_Column, HTuple hv_Phi, HTuple hv_Length1, |
| | | HTuple hv_Length2, out HTuple hv_TopLeft_Row, out HTuple hv_TopLeft_Col, out HTuple hv_TopRight_Row, |
| | | out HTuple hv_TopRight_Col, out HTuple hv_LowLeft_Row, out HTuple hv_LowLeft_Col, |
| | | out HTuple hv_LowRight_Row, out HTuple hv_LowRight_Col) |
| | |
| | | } |
| | | } |
| | | |
| | | public void pts_to_best_line(out HObject ho_LineXld, HTuple hv_Rows, HTuple hv_Columns, |
| | | public static void pts_to_best_line(out HObject ho_LineXld, HTuple hv_Rows, HTuple hv_Columns, |
| | | HTuple hv_IgnoreNum, out HTuple hv_Row1, out HTuple hv_Column1, out HTuple hv_Row2, |
| | | out HTuple hv_Column2) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | public (double, double) CalculateTailValues(HTuple minValue, HTuple maxValue, HTuple mean, HTuple deviation, double tailPercentage = 0.3) |
| | | public static (double, double) CalculateTailValues(HTuple minValue, HTuple maxValue, HTuple mean, HTuple deviation, double tailPercentage = 0.3) |
| | | { |
| | | // 计算低尾灰度值 |
| | | double lowTailValue = minValue.TupleReal() + (mean.TupleReal() - minValue.TupleReal()) * tailPercentage; |
| | |
| | | return (highTailValue, lowTailValue); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 图像增强算法-边缘增强 |
| | | /// </summary> |
| | | /// <param name="ho_Image">待测图片</param> |
| | | /// <param name="hv_Wid">掩膜宽</param> |
| | | /// <param name="hv_High">掩膜高</param> |
| | | /// <param name="hv_Fac">增强因子</param> |
| | | /// <param name="hv_Row1">起始纵坐标</param> |
| | | /// <param name="hv_Column1">起始横坐标</param> |
| | | /// <param name="hv_Row2">结束纵坐标</param> |
| | | /// <param name="hv_Column2">结束横坐标</param> |
| | | public static void ImageEnhancement(HObject ho_Image, out HObject ho_OutImage, HTuple hv_ImageEnhancementType, HTuple hv_Wid, HTuple hv_High, HTuple hv_Fac) |
| | | { |
| | | HOperatorSet.GenEmptyObj(out ho_OutImage); |
| | | try |
| | | { |
| | | HTuple hv_ImageEnhancementTypeOut = new HTuple(); |
| | | hv_ImageEnhancementTypeOut.Dispose(); |
| | | hv_ImageEnhancementTypeOut = new HTuple(hv_ImageEnhancementType); |
| | | |
| | | hv_Wid.Dispose(); |
| | | hv_High.Dispose(); |
| | | ho_OutImage.Dispose(); |
| | | |
| | | //设置图像增强算法 |
| | | if ((int)(new HTuple(hv_ImageEnhancementTypeOut.TupleEqual("emphasize"))) != 0) |
| | | { |
| | | hv_ImageEnhancementTypeOut.Dispose(); |
| | | hv_ImageEnhancementTypeOut = "emphasize"; |
| | | HOperatorSet.Emphasize(ho_Image, out ho_OutImage, hv_Wid, hv_High, hv_Fac); |
| | | } |
| | | else if ((int)(new HTuple(hv_ImageEnhancementTypeOut.TupleEqual("equHisto"))) != 0) |
| | | { |
| | | hv_ImageEnhancementTypeOut.Dispose(); |
| | | hv_ImageEnhancementTypeOut = "equHisto"; |
| | | HOperatorSet.ScaleImageMax(ho_Image, out ho_OutImage); |
| | | } |
| | | else |
| | | { |
| | | hv_ImageEnhancementTypeOut.Dispose(); |
| | | hv_ImageEnhancementTypeOut = "scaleMax"; |
| | | HOperatorSet.EquHistoImage(ho_Image, out ho_OutImage); |
| | | } |
| | | return; |
| | | } |
| | | catch (HalconException HDevExpDefaultException) |
| | | { |
| | | |
| | | hv_Wid.Dispose(); |
| | | hv_High.Dispose(); |
| | | |
| | | throw HDevExpDefaultException; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 卡尺算法 |
| | | /// </summary> |
| | |
| | | /// <param name="hv_Column2">结束横坐标</param> |
| | | /// <param name="hv_ResultRow">结果点集合纵坐标</param> |
| | | /// <param name="hv_ResultColumn">结果点集合横坐标</param> |
| | | public void Rake(HObject ho_Image, out HObject ho_Regions, HTuple hv_Elements, |
| | | public static void Rake(HObject ho_Image, out HObject ho_Regions, HTuple hv_Elements, |
| | | HTuple hv_DetectHeight, HTuple hv_DetectWidth, HTuple hv_Sigma, HTuple hv_Threshold, |
| | | HTuple hv_Transition, HTuple hv_Select, HTuple hv_Row1, HTuple hv_Column1, HTuple hv_Row2, |
| | | HTuple hv_Column2, out HTuple hv_ResultRow, out HTuple hv_ResultColumn) |
| | |
| | | catch { } |
| | | } |
| | | |
| | | public void scale_gray_map(HObject ho_Image, out HObject ho_Image1, HTuple hv_Min, HTuple hv_Max) |
| | | public static void scale_gray_map(HObject ho_Image, out HObject ho_Image1, HTuple hv_Min, HTuple hv_Max) |
| | | { |
| | | HTuple hv_Mult = new HTuple(), hv_Add = new HTuple(); |
| | | HOperatorSet.GenEmptyObj(out ho_Image1); |
| | |
| | | |
| | | #region OpenCVSharp |
| | | // 根据Mat类型返回对应的无效值 |
| | | public Scalar GetInvalidValueForMat(Mat mat) |
| | | public static Scalar GetInvalidValueForMat(Mat mat) |
| | | { |
| | | MatType type = mat.Type(); |
| | | if (type == MatType.CV_8UC1 || type == MatType.CV_8UC3) |
| | |
| | | return new Scalar(0); // 对于8位无符号类型,0是安全的无效值 |
| | | } |
| | | |
| | | public void RGB2XYZ(double sR, double sG, double sB, out double X, out double Y, out double Z) |
| | | public static void RGB2XYZ(double sR, double sG, double sB, out double X, out double Y, out double Z) |
| | | { |
| | | // 输入的颜色值 (sR, sG, sB) 应为 0 到 255 之间的值 |
| | | |
| | |
| | | Z = Math.Round(var_Z / (var_X + var_Y + var_Z), 3); |
| | | } |
| | | |
| | | public void ExtractFrames(string videoPath, string outputDir) |
| | | public static void ExtractFrames(string videoPath, string outputDir) |
| | | { |
| | | // 检查视频文件是否存在 |
| | | if (!File.Exists(videoPath)) |