两个Bitmap图形比较相似度(.net)

在网上找了一圈资料之后:比较两个图片相似度方法主要有2种

1.遍历图片每个像素,计算方差进行比较。这个没有去试,直接遍历Bitmap所有获取像素点,性能上不会好到哪去的。

2.也是使用方差,但是是使用两个图片的总方差进行比较(因为项目中主要是用来自动裁剪图片中相似度高的部分,经测试,比较出来的结果还是可以接受的)

variance是计算方差的方法,cutBitmapByVariance方法是具体使用,会涉及到了其它很多的业务代码,那些就不贴出来了

        /// <summary>
        /// 计算方差
        /// datas为Bitmap中的byte
        /// </summary>
        private static double variance(byte[] datas)
        {
            double variance = 0;
            int avg = datas.Sum(x => x) / datas.Length;
            foreach (byte data in datas)
            {
                variance += (double)((double)(data - avg)) * (data - avg) / datas.Length;
            }
            return variance;
        }

        /// <summary>
        /// 根据方差计算相似度
        /// </summary>
        public static List<JudgeInfoModel> cutBitmapByVariance(FileStream fs,List<JudgeInfoModel> lstTimes,bool isMirror=false)
        {
            List<JudgeInfoModel> lstTempTimes = new List<JudgeInfoModel>(lstTimes);      
            long totalImage = fs.Length / GlobalData.imageSize;
            int forCount = (int)totalImage / GlobalData.perCount;
            fs.Seek(0, SeekOrigin.Begin);
            byte[] startBytes = new byte[GlobalData.perCount*GlobalData.imageSize];
            fs.Read(startBytes, 0, startBytes.Length);

            double startVariance = variance(startBytes);
            double xx = 10;
            for (int i = 1; i < forCount; i++)
            {
                
                fs.Seek(i*GlobalData.perCount*GlobalData.imageSize, SeekOrigin.Begin);    
                byte[] tempBytes = new byte[GlobalData.perCount * GlobalData.imageSize];
                fs.Read(tempBytes, 0, tempBytes.Length);
                double tempVariance = variance(tempBytes);
                if (Math.Abs(startVariance - tempVariance) <= xx) //如果相似
                {
                    int index = lstTempTimes.FindIndex(x => x.X == i * GlobalData.perCount);
                    int cutCount =  lstTempTimes.Count - index < GlobalData.perCount ? lstTempTimes.Count - index : GlobalData.perCount;
                    lstTempTimes.RemoveRange(index, cutCount);
                }
                startVariance = tempVariance;
            }
            return lstTempTimes;
        }

3.使用直方图比较(应用了算法计算。这个方法比较出来的结果会比较准确)

使用了OpenCv,首先需要添加依赖包OpenCvSharp4.Extensions和OpenCvSharp4.Windows

以下是主要代码

 public static double compareHist(Bitmap bBitmap, Bitmap cBitmap)
        {
            Mat bMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bBitmap);
            Mat cMat = OpenCvSharp.Extensions.BitmapConverter.ToMat(cBitmap);

            Cv2.CvtColor(bMat, bMat, ColorConversionCodes.BGR2HSV);
            Cv2.CvtColor(cMat, cMat, ColorConversionCodes.BGR2HSV);

            int h_bins = 50;
            int s_bins = 60;
            int[] histSize = { h_bins, s_bins };

            Rangef h_ranges = new Rangef(0, 256);
            Rangef s_ranges = new Rangef(0, 180);
            Rangef[] ranges = { h_ranges, s_ranges };

            int[] channels = { 0, 1 };

            Mat hist_bMat = new Mat();
            Mat hist_cMat = new Mat();

            Cv2.CalcHist(new Mat[] { bMat }, channels, new Mat(), hist_bMat, 2, histSize, ranges, true, false);
            Cv2.Normalize(hist_bMat, hist_bMat, 0, 1, NormTypes.MinMax, -1, new Mat());


            Cv2.CalcHist(new Mat[] { cMat }, channels, new Mat(), hist_cMat, 2, histSize, ranges, true, false);
            Cv2.Normalize(hist_cMat, hist_cMat, 0, 1, NormTypes.MinMax, -1, new Mat());

            double result = Cv2.CompareHist(hist_bMat, hist_cMat, HistCompMethods.Bhattacharyya);
            return result;
        }

猜你喜欢

转载自blog.csdn.net/liyayou/article/details/127049283
今日推荐