using OpenCvSharp;
using Sunny.UI.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;
using Point = OpenCvSharp.Point;
using Size = OpenCvSharp.Size;



namespace HisenceYoloDetection
{
    public static class CheckDiffSciHelper
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="path1">标准图像</param>
        /// <param name="path2">要对比的图像</param>
        /// <param name="IfWhiteWord"> 白板黑字为true </param>
        /// <param name="saveDir">存储路径</param>
        public static bool CheckDiffSci(string path1, Mat MatDet, Rect sqlrect, Rect detrect, bool IfWhiteWord, string saveDir)
        {
            // 读取和处理第一张图片。。
            Mat img1 = Cv2.ImRead(path1, ImreadModes.Color);
            if (img1.Empty())
            {
                Console.WriteLine($"Error loading image {path1}");
                return false;
            }
            //  Cv2.Resize(img1, img1, new Size(550, 270));
            Mat gimg1 = new Mat();
            Cv2.CvtColor(img1, gimg1, ColorConversionCodes.BGR2GRAY);
            Mat thr1 = new Mat();

            if (IfWhiteWord)
            {
                Cv2.Threshold(gimg1, thr1, 0, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);
            }
            else
            {
                Cv2.Threshold(gimg1, thr1, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
            }




            // 读取和处理第二张图片
            Mat img2 = MatDet.Clone();
            if (img2.Empty())
            {
                // Console.WriteLine($"Error loading image {path2}");
                return false;
            }
            // Cv2.Resize(img2, img2, new Size(550, 270));
            Mat gimg2 = new Mat();
            Cv2.CvtColor(img2, gimg2, ColorConversionCodes.BGR2GRAY);
            Mat thr2 = new Mat();
            //Cv2.Threshold(gimg2, thr2, 0, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);
            if (IfWhiteWord)
            {
                Cv2.Threshold(gimg2, thr2, 0, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);
            }
            else
            {
                Cv2.Threshold(gimg2, thr2, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
            }


            //Rect  area2 = new Rect(148,30,229,222);
            sqlrect.Width += 20;
            sqlrect.Height += 60;
            detrect.Width += 20;
            detrect.Height += 60;
            Mat matCutblack1 = new Mat(thr1, sqlrect);
            if (IfWhiteWord)
            {
                matCutblack1.SetTo(Scalar.Black);
            }
            else
            {
                matCutblack1.SetTo(Scalar.Black);
            }
            Mat matCutblack2 = new Mat(thr2, detrect);
            if (IfWhiteWord)
            {
                matCutblack2.SetTo(Scalar.Black);
            }
            else
            {
                matCutblack2.SetTo(Scalar.Black);
            }
            Cv2.Resize(thr1, thr1, new Size(550, 270));
            Cv2.Resize(thr2, thr2, new Size(550, 270));
            DateTime dt = DateTime.Now;
            string filename = dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Millisecond.ToString();

            //string savePath4 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "_thr1.png");
            //// 保存结果

            //Cv2.ImWrite(savePath4, thr1);
            //string savePath3 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "_thr2.png");
            //// 保存结果

            //Cv2.ImWrite(savePath3, thr2);

            // 创建卷积核
            Mat filter1 = new Mat(15, 15, MatType.CV_32F, new Scalar(0));
            filter1.Row(7).SetTo(new Scalar(0.025));
            filter1.Col(7).SetTo(new Scalar(0.025));

            // 应用卷积
            Mat final_result1 = new Mat();
            Cv2.Filter2D(thr1, final_result1, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
            Cv2.Filter2D(final_result1, final_result1, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
            Cv2.Filter2D(final_result1, final_result1, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);

            Mat final_result2 = new Mat();
            Cv2.Filter2D(thr2, final_result2, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
            Cv2.Filter2D(final_result2, final_result2, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
            Cv2.Filter2D(final_result2, final_result2, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
            //裁剪才行


            //string savePath2 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + "_final_result1.png");
            //// 保存结果
            ////string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
            //Cv2.ImWrite(savePath2, final_result1);
            //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + "_final_result2.png");
            //// 保存结果
            ////string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
            //Cv2.ImWrite(savePath, final_result2);







            // 计算图像差异
            Mat devIMG = new Mat();
            Mat devIMG_ = new Mat();
            Cv2.Subtract(final_result1, final_result2, devIMG);
            Cv2.Subtract(final_result2, final_result1, devIMG_);
            //string savePathd = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "devIMG.png");
            //// 保存结果

            //Cv2.ImWrite(savePathd, devIMG);
            //string savePathd1 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "devIMG_.png");
            //// 保存结果

            //Cv2.ImWrite(savePathd1, devIMG_);
            // 对差异图像应用阈值
            Cv2.Threshold(devIMG, devIMG, 20, 255, ThresholdTypes.Binary);
            Cv2.Threshold(devIMG_, devIMG_, 20, 255, ThresholdTypes.Binary);

            // 结合差异
            Mat sumIMG = new Mat();
            Cv2.Add(devIMG, devIMG_, sumIMG);

            // 应用形态学操作
            Mat kernelCL = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
            Mat blackhatImg = new Mat();
            Cv2.Dilate(sumIMG, blackhatImg, kernelCL);

            // 处理轮廓和保存结果
            Point[][] contours = new Point[10000][];
            Cv2.FindContours(blackhatImg, out contours, out _, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
            bool isMatch = true;
            foreach (var contour in contours)
            {
                if (Cv2.ContourArea(contour) <= 500)
                {
                    Cv2.DrawContours(blackhatImg, new Point[][] { contour }, -1, Scalar.Black, thickness: Cv2.FILLED);
                    // 框选轮廓
                    string savePath2 = Path.Combine("D:\\Hisence\\Test\\2\\ng", Path.GetFileNameWithoutExtension(path1) + filename + "_Rect.png");
                    // 保存结果
                    //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                    Cv2.ImWrite(savePath2, img2);
                    string savePath = Path.Combine("D:\\Hisence\\Test\\2\\ng", Path.GetFileNameWithoutExtension(path1) + filename + "_diff.png");
                    // 保存结果
                    //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                    Cv2.ImWrite(savePath, blackhatImg);
                }
                else
                {
                    Rect boundingRect = Cv2.BoundingRect(contour);
                    Cv2.Rectangle(img2, boundingRect, Scalar.Red, thickness: 2);
                    isMatch = false;
                    string savePath2 = Path.Combine("D:\\Hisence\\Test\\2\\ok", Path.GetFileNameWithoutExtension(path1) + filename + "_Rect.png");
                    // 保存结果
                    //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                    Cv2.ImWrite(savePath2, img2);
                    string savePath = Path.Combine("D:\\Hisence\\Test\\2\\ok", Path.GetFileNameWithoutExtension(path1) + filename + "_diff.png");
                    // 保存结果
                    //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                    Cv2.ImWrite(savePath, blackhatImg);
                }
            }

           
            return isMatch;
        }



        public static Rect strChangeRect(string strrect)
        {
            if (!string.IsNullOrEmpty(strrect))
            {
                string[] rectstr = strrect.Split(",");
                int areaX = int.Parse(rectstr[0]);
                int areaY = int.Parse(rectstr[1]);
                int areaWidth = int.Parse(rectstr[2]);
                int areaHeight = int.Parse(rectstr[3]);

                Rect rect = new Rect(areaX, areaY, areaWidth, areaHeight);
                return rect;
            }
            else
            {
                return new Rect(0, 0, 0, 0);
            }

        }

        public static string rectChangeStr(Rect area)
        {
            string[] rectsql = new string[4];
            rectsql[0] = Convert.ToString(area.X);
            rectsql[1] = Convert.ToString(area.Y);
            rectsql[2] = Convert.ToString(area.Width);
            rectsql[3] = Convert.ToString(area.Height);

            string strrect = rectsql.Join(",");
            return strrect;
        }
        public static class CheckDiffSciHelper1
        {
            /// <summary>
            /// 
            /// </summary>
            /// <param name="path1">标准图像</param>
            /// <param name="path2">要对比的图像</param>
            /// <param name="IfWhiteWord"> 白板黑字为true </param>
            /// <param name="saveDir">存储路径</param>
            public static bool CheckDiffSci(string path1, Mat MatDet, Rect sqlrect, Rect detrect, bool IfWhiteWord, string saveDir)
            {
                // 读取和处理第一张图片
                Mat img1 = Cv2.ImRead(path1, ImreadModes.Color);
                if (img1.Empty())
                {
                    Console.WriteLine($"Error loading image {path1}");
                    return false;
                }
                //  Cv2.Resize(img1, img1, new Size(550, 270));
                Mat gimg1 = new Mat();
                Cv2.CvtColor(img1, gimg1, ColorConversionCodes.BGR2GRAY);
                Mat thr1 = new Mat();

                if (IfWhiteWord)
                {
                    Cv2.Threshold(gimg1, thr1, 0, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);
                }
                else
                {
                    Cv2.Threshold(gimg1, thr1, 100, 255, ThresholdTypes.Binary );//| ThresholdTypes.Otsu
                }




                // 读取和处理第二张图片
                Mat img2 = MatDet.Clone();
                if (img2.Empty())
                {
                    // Console.WriteLine($"Error loading image {path2}");
                    return false;
                }
                // Cv2.Resize(img2, img2, new Size(550, 270));
                Mat gimg2 = new Mat();
                Cv2.CvtColor(img2, gimg2, ColorConversionCodes.BGR2GRAY);
                Mat thr2 = new Mat();
                //Cv2.Threshold(gimg2, thr2, 0, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);
                if (IfWhiteWord)
                {
                    Cv2.Threshold(gimg2, thr2, 0, 255, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);
                }
                else
                {
                    Cv2.Threshold(gimg2, thr2, 100, 255, ThresholdTypes.Binary );//| ThresholdTypes.Otsu
                }


                //Rect  area2 = new Rect(148,30,229,222);
                sqlrect.Width += 20;
                sqlrect.Height += 20;
                detrect.Width += 20;
                detrect.Height += 20;
                Mat matCutblack1 = new Mat(thr1, sqlrect);
                if (IfWhiteWord)
                {
                    matCutblack1.SetTo(Scalar.Black);
                }
                else
                {
                    matCutblack1.SetTo(Scalar.Black);
                }
                Mat matCutblack2 = new Mat(thr2, detrect);
                if (IfWhiteWord)
                {
                    matCutblack2.SetTo(Scalar.Black);
                }
                else
                {
                    matCutblack2.SetTo(Scalar.Black);
                }
                Cv2.Resize(thr1, thr1, new Size(845, 498));
                Cv2.Resize(thr2, thr2, new Size(845, 498));
                DateTime dt = DateTime.Now;
                string filename = dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Millisecond.ToString();

                //string savePath4 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "_thr1.png");
                //// 保存结果

                //Cv2.ImWrite(savePath4, thr1);
                //string savePath3 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "_thr2.png");
                //// 保存结果

                //Cv2.ImWrite(savePath3, thr2);

                // 创建卷积核
                
                Mat filter1 = new Mat(15,15, MatType.CV_32F, new Scalar(0));
                filter1.Row(7).SetTo(new Scalar(0.025));
                filter1.Col(7).SetTo(new Scalar(0.025));

             
                // 应用卷积
                Mat final_result1 = new Mat();
                Cv2.Filter2D(thr1, final_result1, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
                Cv2.Filter2D(final_result1, final_result1, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
                Cv2.Filter2D(final_result1, final_result1, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
              
                //Cv2.Filter2D(final_result1, final_result1, -1, filter2, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);

                Mat final_result2 = new Mat();
                Cv2.Filter2D(thr2, final_result2, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
                Cv2.Filter2D(final_result2, final_result2, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
                Cv2.Filter2D(final_result2, final_result2, -1, filter1, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
               
                //Cv2.Filter2D(final_result2, final_result2, -1, filter2, anchor: new Point(-1, -1), 0, BorderTypes.Reflect);
                //裁剪才行


                //string savePath2 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + "_final_result1.png");
                //// 保存结果
                ////string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                //Cv2.ImWrite(savePath2, final_result1);
                //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + "_final_result2.png");
                //// 保存结果
                ////string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                //Cv2.ImWrite(savePath, final_result2);







                // 计算图像差异
                Mat devIMG = new Mat();
                Mat devIMG_ = new Mat();
                Cv2.Subtract(final_result1, final_result2, devIMG);
                Cv2.Subtract(final_result2, final_result1, devIMG_);
                //string savePathd = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "devIMG.png");
                //// 保存结果
             
                //Cv2.ImWrite(savePathd, devIMG);
                //string savePathd1 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "devIMG_.png");
                //// 保存结果
                
                //Cv2.ImWrite(savePathd1, devIMG_);
                // 对差异图像应用阈值
                Cv2.Threshold(devIMG, devIMG, 45, 255, ThresholdTypes.Binary);
                Cv2.Threshold(devIMG_, devIMG_, 45, 255, ThresholdTypes.Binary);

                // 结合差异
                Mat sumIMG = new Mat();
                Cv2.Add(devIMG, devIMG_, sumIMG);
                //string savePaths = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "sumIMG.png");
                //// 保存结果

                //Cv2.ImWrite(savePaths, sumIMG);
                // 应用形态学操作
                Mat kernelCL = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
                Mat blackhatImg = new Mat();
                Cv2.Dilate(sumIMG, blackhatImg, kernelCL);

                // 处理轮廓和保存结果
                Point[][] contours = new Point[10000][];
                Cv2.FindContours(blackhatImg, out contours, out _, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
                bool isMatch = true;
                foreach (var contour in contours)
                {
                    if (Cv2.ContourArea(contour) <= 100)
                    {
                        Cv2.DrawContours(blackhatImg, new Point[][] { contour }, -1, Scalar.Black, thickness: Cv2.FILLED);
                        // 框选轮廓

                    }
                    else
                    {
                        Rect boundingRect = Cv2.BoundingRect(contour);
                        Cv2.Rectangle(img2, boundingRect, Scalar.Red, thickness: 2);
                        isMatch = false;
                    }
                }

                string savePath2 = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "_Rect.png");
                // 保存结果
                //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                Cv2.ImWrite(savePath2, img2);
                string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path1) + filename + "_diff.png");
                // 保存结果
                //string savePath = Path.Combine(saveDir, Path.GetFileNameWithoutExtension(path2) + "_diff.png");
                Cv2.ImWrite(savePath, blackhatImg);
                return isMatch;
            }
        }
    }
}