using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SixLabors.ImageSharp.Processing; namespace VideoAnalysisCore.Common { /// /// ssim计算器 /// public class SSIMCalculator { // SSIM计算常量 (基于8-bit图像范围0-255) private const double C1 = (0.01 * 255) * (0.01 * 255); private const double C2 = (0.03 * 255) * (0.03 * 255); /// /// 计算连续帧的SSIM 值 /// /// /// /// 返回阈值 0-1 越小变化越大清晰视频:阈值 0.90-0.95 低质量视频:阈值 0.85-0.90 public static double CalculateFrameSSIM(Image img1, Image img2) { // 转换为灰度图 var gray1 = CreateResizedGrayImage(img1); var gray2 = CreateResizedGrayImage(img2); // 计算全局统计量 CalculateStats(gray1, gray2, out double mean1, out double mean2, out double var1, out double var2, out double covar); // 计算SSIM分量 double luminance = (2 * mean1 * mean2 + C1) / (mean1 * mean1 + mean2 * mean2 + C1); double contrast = (2 * Math.Sqrt(var1) * Math.Sqrt(var2) + C2) / (var1 + var2 + C2); double structure = (covar + C2 / 2) / (Math.Sqrt(var1) * Math.Sqrt(var2) + C2 / 2); // 返回SSIM值 (值越接近1表示越相似) return luminance * contrast * structure; } private static Image CreateResizedGrayImage(Image image) { return image .Clone(x => x.Grayscale()) .CloneAs(); // 转换为8位灰度格式 } private static void CalculateStats( Image img1, Image img2, out double mean1, out double mean2, out double var1, out double var2, out double covar) { int width = img1.Width; int height = img1.Height; int totalPixels = width * height; double sum1 = 0, sum2 = 0; double sum1Sq = 0, sum2Sq = 0, sumProduct = 0; // 单次遍历计算所有统计量 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { double val1 = img1[x, y].PackedValue; double val2 = img2[x, y].PackedValue; sum1 += val1; sum2 += val2; sum1Sq += val1 * val1; sum2Sq += val2 * val2; sumProduct += val1 * val2; } } // 计算均值 mean1 = sum1 / totalPixels; mean2 = sum2 / totalPixels; // 计算方差: Var(X) = E[X²] - E[X]² var1 = (sum1Sq / totalPixels) - (mean1 * mean1); var2 = (sum2Sq / totalPixels) - (mean2 * mean2); // 计算协方差: Cov(X,Y) = E[XY] - E[X]E[Y] covar = (sumProduct / totalPixels) - (mean1 * mean2); } } }