首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

OpenCV进行图像相似度对比的几种办法

OpenCV进行图像相似度对比的几种办法

转载请注明出处:http://blog.csdn.net/wangyaninglm/article/details/43853435
来自:shiter编写程序的艺术

对计算图像相似度的方法,本文做了如下总结,主要有三种办法:
1.PSNR峰值信噪比PSNR(Peak Signal to Noise Ratio),一种全参考的图像质量评价指标。
简介:https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
PSNR是最普遍和使用最为广泛的一种图像客观评价指标,然而它是基于对应像素点间的误差,即基于误差敏感的图像质量评价。由于并未考虑到人眼的视觉特性(人眼对空间频率较低的对比差异敏感度较高,人眼对亮度对比差异的敏感度较色度高,人眼对一个区域的感知结果会受到其周围邻近区域的影响等),因而经常出现评价结果与人的主观感觉不一致的情况。
SSIM(structural similarity)结构相似性,也是一种全参考的图像质量评价指标,它分别从亮度、对比度、结构三方面度量图像相似性。

SSIM取值范围[0,1],值越大,表示图像失真越小.
在实际应用中,可以利用滑动窗将图像分块,令分块总数为N,考虑到窗口形状对分块的影响,采用高斯加权计算每一窗口的均值、方差以及协方差,然后计算对应块的结构相似度SSIM,最后将平均值作为两图像的结构相似性度量,即平均结构相似性MSSIM:
参考资料[1] 峰值信噪比-维基百科
[2] 王宇庆,刘维亚,王勇. 一种基于局部方差和结构相似度的图像质量评价方法[J]. 光电子激光,2008。
[3]http://www.cnblogs.com/vincent2012/archive/2012/10/13/2723152.html
官方文档的说明,不过是GPU版本的,我们可以修改不用gpu不然还得重新编译
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/highgui/video-input-psnr-ssim/video-input-psnr-ssim.html#videoinputpsnrmssim
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.html?highlight=psnr
// PSNR.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>                   // Console I/O#include <sstream>                    // String to number conversion#include <opencv2/core/core.hpp>      // Basic OpenCV structures#include <opencv2/imgproc/imgproc.hpp>// Image processing methods for the CPU#include <opencv2/highgui/highgui.hpp>// Read images#include <opencv2/gpu/gpu.hpp>        // GPU structures and methodsusing namespace std;using namespace cv;double getPSNR(const Mat& I1, const Mat& I2);      // CPU versionsScalar getMSSIM( const Mat& I1, const Mat& I2);double getPSNR_GPU(const Mat& I1, const Mat& I2);  // Basic GPU versionsScalar getMSSIM_GPU( const Mat& I1, const Mat& I2);struct BufferPSNR                                     // Optimized GPU versions{   // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later.    gpu::GpuMat gI1, gI2, gs, t1,t2;    gpu::GpuMat buf;};double getPSNR_GPU_optimized(const Mat& I1, const Mat& I2, BufferPSNR& b);struct BufferMSSIM                                     // Optimized GPU versions{   // Data allocations are very expensive on GPU. Use a buffer to solve: allocate once reuse later.    gpu::GpuMat gI1, gI2, gs, t1,t2;    gpu::GpuMat I1_2, I2_2, I1_I2;    vector<gpu::GpuMat> vI1, vI2;    gpu::GpuMat mu1, mu2;     gpu::GpuMat mu1_2, mu2_2, mu1_mu2;     gpu::GpuMat sigma1_2, sigma2_2, sigma12;     gpu::GpuMat t3;     gpu::GpuMat ssim_map;    gpu::GpuMat buf;};Scalar getMSSIM_GPU_optimized( const Mat& i1, const Mat& i2, BufferMSSIM& b);void help(){    cout        << "\n--------------------------------------------------------------------------" << endl        << "This program shows how to port your CPU code to GPU or write that from scratch." << endl        << "You can see the performance improvement for the similarity check methods (PSNR and SSIM)."  << endl        << "Usage:"                                                               << endl        << "./gpu-basics-similarity referenceImage comparedImage numberOfTimesToRunTest(like 10)." << endl        << "--------------------------------------------------------------------------"   << endl        << endl;}int main(int argc, char *argv[]){    help();     Mat I1 = imread("swan1.jpg",1);           // Read the two images    Mat I2 = imread("swan2.jpg",1);    if (!I1.data || !I2.data)           // Check for success    {        cout << "Couldn't read the image";        return 0;    }    BufferPSNR bufferPSNR;    BufferMSSIM bufferMSSIM;    int TIMES;     stringstream sstr("500");     sstr >> TIMES;    double time, result;    //------------------------------- PSNR CPU ----------------------------------------------------    time = (double)getTickCount();        for (int i = 0; i < TIMES; ++i)        result = getPSNR(I1,I2);    time = 1000*((double)getTickCount() - time)/getTickFrequency();    time /= TIMES;    cout << "Time of PSNR CPU (averaged for " << TIMES << " runs): " << time << " milliseconds."        << " With result of: " <<  result << endl;     ////------------------------------- PSNR GPU ----------------------------------------------------    //time = (double)getTickCount();        //for (int i = 0; i < TIMES; ++i)    //  result = getPSNR_GPU(I1,I2);    //time = 1000*((double)getTickCount() - time)/getTickFrequency();    //time /= TIMES;    //cout << "Time of PSNR GPU (averaged for " << TIMES << " runs): " << time << " milliseconds."    //  << " With result of: " <<  result << endl; /*    //------------------------------- PSNR GPU Optimized--------------------------------------------    time = (double)getTickCount();                                  // Initial call    result = getPSNR_GPU_optimized(I1, I2, bufferPSNR);    time = 1000*((double)getTickCount() - time)/getTickFrequency();    cout << "Initial call GPU optimized:              " << time  <<" milliseconds."        << " With result of: " << result << endl;    time = (double)getTickCount();        for (int i = 0; i < TIMES; ++i)        result = getPSNR_GPU_optimized(I1, I2, bufferPSNR);    time = 1000*((double)getTickCount() - time)/getTickFrequency();    time /= TIMES;    cout << "Time of PSNR GPU OPTIMIZED ( / " << TIMES << " runs): " << time         << " milliseconds." << " With result of: " <<  result << endl << endl;     //------------------------------- SSIM CPU -----------------------------------------------------    Scalar x;    time = (double)getTickCount();        for (int i = 0; i < TIMES; ++i)        x = getMSSIM(I1,I2);    time = 1000*((double)getTickCount() - time)/getTickFrequency();    time /= TIMES;    cout << "Time of MSSIM CPU (averaged for " << TIMES << " runs): " << time << " milliseconds."        << " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl;     //------------------------------- SSIM GPU -----------------------------------------------------    time = (double)getTickCount();        for (int i = 0; i < TIMES; ++i)        x = getMSSIM_GPU(I1,I2);    time = 1000*((double)getTickCount() - time)/getTickFrequency();    time /= TIMES;    cout << "Time of MSSIM GPU (averaged for " << TIMES << " runs): " << time << " milliseconds."        << " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl;     //------------------------------- SSIM GPU Optimized--------------------------------------------    time = (double)getTickCount();        x = getMSSIM_GPU_optimized(I1,I2, bufferMSSIM);    time = 1000*((double)getTickCount() - time)/getTickFrequency();    cout << "Time of MSSIM GPU Initial Call            " << time << " milliseconds."        << " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl;     time = (double)getTickCount();        for (int i = 0; i < TIMES; ++i)        x = getMSSIM_GPU_optimized(I1,I2, bufferMSSIM);    time = 1000*((double)getTickCount() - time)/getTickFrequency();    time /= TIMES;    cout << "Time of MSSIM GPU OPTIMIZED ( / " << TIMES << " runs): " << time << " milliseconds."        << " With result of B" << x.val[0] << " G" << x.val[1] << " R" << x.val[2] << endl << endl;     return 0;    */    getchar();}
继承事业,薪火相传
返回列表