简介
最近接到了一个需求,需要对比图片并自动生成对比报表,核心功能就是获取图片相似度,生成表格。
这里仅介绍如何实现的图片相似度获取;
思路
相似度计算的算法选择的是SSIM算法,具体算法原理参考的是SSIM 的原理和代码实现,算法中涉及了卷积运算,还有图片的矩阵运算,决定选用OpenCV库来实现。因为后台使用的是C#写的,OpenCV使用的是C++,所以决定用C++封装图像相似度处理的函数,通过dll导出接口到C#中使用;(C#中有已经封装的OpenCV库,OpencvSharp和Emgu都是很好的,但是这次功能简单,没有必要使用)
实现
VS2019下的OpenCV环境搭建
OpenCV源代码编译
- 从https://opencv.org/releases/下载源代码,如果不介意官方打包的dll和lib体积太大的话,也可以下载exe版本,双击即可,可以省去后面的编译步骤
- 从https://cmake.org/download/下载cmake,用于源码编译
- 下载完cmake后解压,运行 解压目录/bin/cmake-gui.exe ,通过Browse Source找到第一步下载解压的OpenCV源码目录,然后选择一个结果输出路径比如我这里分别是:E:/Program Zip/opencv-4.4.0/opencv-4.4.0和 E:/Program Zip/opencv-4.4.0/opencv-4.4.0/build

- 点击左下角的Configure按钮,选择编译选项如下,然后点finish;这里我只配置了64位的,其他平台可以自行选择
-
- 待配置完成后,点击generate,等待生成完成,点击project按钮打开解决方案
- 选择Debug或Releas编译选项,在
INSTALL项目上右键,Build - 漫长的Build之后,你会在输出目录下(比如我的是
E:\Program Zip\opencv-4.4.0\opencv-4.4.0\build\install)看到, 如果中间报了python相关的错误,可以忽略

- 到这里,opencv的编译就成功完成了
项目配置
-
把上一步编译好的opencv库中的
include,x64目录拷贝到合适的地方,最好是release合debug版本的分目录存放,下面是我的目录结构,因为暂时不考虑多个vs版本的,所以x64下面的vc目录去掉了

-
新建一个空的C++项目
-
在项目上右键,跳转到:
属性页->Configuration Properties->General->Configuration Type,修改为Dynamic Library (.dll) -
跳转到:
属性页 ->C/C++->General->Additional Include Directories,填入存放opencv库的include目录的路径

-
跳转到:
属性页->Linker->General->Additional Library Directories,填入存放opencv库的 路径中对应版本的lib路径,我这里使用了相应的编译选项宏以及编译平台宏,可以视情况选择

-
跳转到:
属性页->Linker->Input->Additioinal Dependencies;release编译选项下填入opencv_core440.lib opencv_imgcodecs440.lib opencv_imgproc440.lib opencv_gapi440.lib opencv_calib3d440.lib,debug选项下记得名字后面要加d,因为我的代码中只用到了这些lib,所以只填了这些lib,如果不介意大小的话,可以把opencv所有的lib都加上,这样可以避免出现 找不到定义的报错 -
到此,项目配置就完成了,dll我们就直接拷贝到项目的输出路径去即可,可以按需拷贝,运行若报错说某个dll找不到就拷贝过去即可
SSIM的算法实现
算法的原理可以参考SSIM 的原理和代码实现,讲的非常清晰,同时也建议阅读下python下的实现
下面是计算图片差异的核心函数,返回的Mat中 包含了两幅图片各个像素点的相似度,如果需要整张图的,求一下均值即可;完整代码放在末尾
static const double C1 = 6.5025, C2 = 58.5225;
Mat Compare_SSIM(Mat image1, Mat image2)
{
Mat validImage1, validImage2;
image1.convertTo(validImage1, CV_32F); //数据类型转换为 float,防止后续计算出现错误
image2.convertTo(validImage2, CV_32F);
Mat image1_1 = validImage1.mul(validImage1); //图像乘积
Mat image2_2 = validImage2.mul(validImage2);
Mat image1_2 = validImage1.mul(validImage2);
Mat gausBlur1, gausBlur2, gausBlur12;
GaussianBlur(validImage1, gausBlur1, Size(11, 11), 1.5); //高斯卷积核计算图像均值
GaussianBlur(validImage2, gausBlur2, Size(11, 11), 1.5);
GaussianBlur(image1_2, gausBlur12, Size(11, 11), 1.5);
Mat imageAvgProduct = gausBlur1.mul(gausBlur2); //均值乘积
Mat u1Squre = gausBlur1.mul(gausBlur1); //各自均值的平方
Mat u2Squre = gausBlur2.mul(gausBlur2

本文详细介绍了使用SSIM算法在C++中实现图片相似度计算,并通过DLL导出接口供C#调用的过程。涵盖OpenCV环境搭建、SSIM算法原理及实现、参数传递技巧等内容。
最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



