首页 > 编程语言 >C#+OpenCV基础(十七)_计算图片相似度

C#+OpenCV基础(十七)_计算图片相似度

时间:2024-07-11 11:10:50浏览次数:15  
标签:11 十七 Mat C# Cv2 hist OpenCV Mul new

1、SSIM算法计算相似度

/// <summary>
/// 两张图片的相似度(SSIM算法)
/// </summary>
/// <param name="mat1">图片1</param>
/// <param name="mat2">图片2</param>
/// <returns></returns>
public static Scalar CompareDetection_SSIM(Mat mat1, Mat mat2)
{
    // 将两个图片处理成同样大小,否则会有错误: The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array'
    var image2 = new Mat();
    Cv2.Resize(mat2, image2, new OpenCvSharp.Size(mat1.Width, mat1.Height));

    double C1 = 6.5025, C2 = 58.5225;
    var validImage1 = new Mat();
    var validImage2 = new Mat();
    mat1.ConvertTo(validImage1, MatType.CV_32F); //数据类型转换为 float,防止后续计算出现错误
    image2.ConvertTo(validImage2, MatType.CV_32F);

    Mat image1_1 = validImage1.Mul(validImage1); //图像乘积
    Mat image2_2 = validImage2.Mul(validImage2);
    Mat image1_2 = validImage1.Mul(validImage2);

    Mat gausBlur1 = new Mat(), gausBlur2 = new Mat(), gausBlur12 = new Mat();
    Cv2.GaussianBlur(validImage1, gausBlur1, new OpenCvSharp.Size(11, 11), 1.5); //高斯卷积核计算图像均值
    Cv2.GaussianBlur(validImage2, gausBlur2, new OpenCvSharp.Size(11, 11), 1.5);
    Cv2.GaussianBlur(image1_2, gausBlur12, new OpenCvSharp.Size(11, 11), 1.5);

    //Mat imageAvgProduct = gausBlur1.Mul(gausBlur2);  // 均值乘积
    Mat u1Squre = gausBlur1.Mul(gausBlur1);          // 计算图1的均值的平方
    Mat u2Squre = gausBlur2.Mul(gausBlur2);          // 计算图2的均值的平方

    Mat squreAvg1 = new Mat(), squreAvg2 = new Mat();
    Cv2.GaussianBlur(image1_1, squreAvg1, new OpenCvSharp.Size(11, 11), 1.5);  // 图像1的平方的均值
    Cv2.GaussianBlur(image2_2, squreAvg2, new OpenCvSharp.Size(11, 11), 1.5);  // 图像2的平方的均值

    Mat imageConvariance = gausBlur12 - gausBlur1.Mul(gausBlur2);  // 计算协方差
    Mat imageVariance1 = squreAvg1 - gausBlur1.Mul(gausBlur1);     // 计算图1的方差
    Mat imageVariance2 = squreAvg2 - gausBlur2.Mul(gausBlur2);     // 计算图2的方差

    var member = ((2 * gausBlur1.Mul(gausBlur2) + C1).Mul(2 * imageConvariance + C2));
    var denominator = ((u1Squre + u2Squre + C1).Mul(imageVariance1 + imageVariance2 + C2));

    Mat ssim = new Mat();
    Cv2.Divide(member, denominator, ssim);

    var sclar = Cv2.Mean(ssim);

    return sclar;  // 变化率,即差异
}

2、颜色直方图计算相似度

/// <summary>
/// 两张图片的相似度(颜色直方图)
/// 图片相似度识别(精度不高,速度较快,可用于以图搜图)
/// </summary>
/// <param name="imgFile1"></param>
/// <param name="imgFile2"></param>
/// <returns></returns>
public static double Compare_Hist(Mat matA, Mat matB)
{
    // 拆分通道
    Cv2.Split(matA, out Mat[] matA_S);
    Cv2.Split(matB, out Mat[] matB_S);

    //直方图的像素范围   
    Rangef[] histRange = { new Rangef(0, 256) };

    //直方图数组大小
    int[] histSize = { 256 };

    //直方图输出数组
    Mat hist_A = new Mat();
    Mat hist_B = new Mat();

    bool uniform = true, accumulate = false;
    Cv2.CalcHist(matA_S, new int[] { 0, 1, 2 }, null, hist_A, 1, histSize, histRange, uniform, accumulate);
    Cv2.CalcHist(matB_S, new int[] { 0, 1, 2 }, null, hist_B, 1, histSize, histRange, uniform, accumulate);

    //归一化,排除图像分辨率不一致的影响
    Cv2.Normalize(hist_A, hist_A, 0, 1, NormTypes.MinMax, -1, null);
    Cv2.Normalize(hist_B, hist_B, 0, 1, NormTypes.MinMax, -1, null);

    //相关性比较
    var res = Cv2.CompareHist(hist_A, hist_B, HistCompMethods.Correl);
    return res;
}

 

标签:11,十七,Mat,C#,Cv2,hist,OpenCV,Mul,new
From: https://www.cnblogs.com/qq2806933146xiaobai/p/18295636

相关文章

  • C#+OpenCV基础(十八)_模版匹配
    1、MatchTemplate匹配图片///<summary>///匹配图片(Cv2.MatchTemplate)///</summary>///<paramname="matSrc">图片</param>///<paramname="matTo">特征图片</param>///<paramname="outMat">结果图片<......
  • C. Count Triangles
    原题链接题解我们知道,三角形成立的条件是任意两边之和都要大于第三边,因为这里已经明确了三条边的大小关系,即\(x\leqy\leqz\)所以,该三角形成立的条件是\(x+y>z\)看到\(5e5\)我们不难想到遍历其中某条边的长度这里我遍历的是\(y\)遍历\(y\),找到最小的\(x\)使得至少......
  • Docker 因端口映射不一致出现的问题
    问题描述因为服务器原先已经安装了nginx(非容器安装),并且占用80端口;而我方习惯使用容器进行安装应用,故用安装了一个容器ngixn;docker-compose.ymlversion:'3'services:nginx:restart:alwayscontainer_name:nginximage:nginxports:-81:80......
  • WPF/C#:在WPF中如何实现依赖注入
    前言本文通过WPFGallery这个项目学习依赖注入的相关概念与如何在WPF中进行依赖注入。什么是依赖注入依赖注入(DependencyInjection,简称DI)是一种设计模式,用于实现控制反转(InversionofControl,简称IoC)原则。依赖注入的主要目的是将对象的创建和对象之间的依赖关系的管......
  • StarRocks跨集群迁移最佳实践|得物技术
    一、引言2024年之前,DBA维护的StarRocks集群存在在用低版本多、稳定性受组件bug影响大的问题,给日常运维带来一定压力,版本升级迫在眉睫。于是,我们在今年年初安排了针对2.5以下版本升级2.5.13的专项。这里和大家分享下,针对因版本兼容问题而不能原地升级的场景下,进行跨集群升级......
  • TCP协议三次握手和四次挥手原理图文解析
    前言TCP协议(TransmissionControlProtocol)是计算机网络中最常用的传输层协议之一,负责提供可靠、面向连接的数据传输服务。它存在的目的就是为了让传输更可靠,也更稳定,但同样也会对端口与端口之间的传输速率造成影响。它一般采用两种方式来使传输更加可靠。一种是面向连接,而另......
  • Kubernetes高可用集群二进制离线部署(Runtime Docker)
    Kubernetes高可用集群二进制部署(RuntimeDocker)Kubernetes(简称为:k8s)是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了资源调度、部署管理、服务......
  • Qt开发 | Qt创建线程 | Qt并发-QtConcurrent
    文章目录一、Qt创建线程的三种方法二、Qt并发:QtConcurrent介绍三、QtConcurrentrun参数说明四、获取QtConcurrent的返回值五、C++其他线程技术介绍一、Qt创建线程的三种方法  以下是Qt创建线程的三种方法:方法一:派生于QThread派生于QThread,这是Qt创建线程最常用......
  • ES6 Reflect 详解(三)
    Reflect对象与Proxy对象一样,也是ES6为了操作对象而提供的新API。Reflect对象的设计目的有4个。将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只......
  • Android 应用、驱动开发(五十九)Calendar应用(DatePicker、TimePicker )
    一、运行效果:二、主函数MainActivity.java:packagecom.example.a074_calendarapp;importstaticjava.lang.String.format;importandroidx.appcompat.app.AppCompatActivity;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;im......