SSIM 您所在的位置:网站首页 opencv相似度计算 SSIM

SSIM

2024-06-16 18:07| 来源: 网络整理| 查看: 265

SSIM---结构相似性算法 一.SSIM算法原理二.skimage.metrics包下的SSIM算法

一.SSIM算法原理

SSIM(structural similarity),结构相似性,是一种衡量两幅图像相似度的指标。SSIM算法主要用于检测两张相同尺寸的图像的相似度、或者检测图像的失真程度。原论文中,SSIM算法主要通过分别比较两个图像的亮度,对比度,结构,然后对这三个要素加权并用乘积表示。

在这里插入图片描述 常数𝑪𝟏, 𝑪𝟐, 𝑪𝟑是为了避免当分母为 0 时造成的不稳定问题。 𝝁𝒙为均值, 𝝈𝒙 为方差, 𝝈𝒙𝒚 表示协方差。 在这里插入图片描述 在这里插入图片描述

二.skimage.metrics包下的SSIM算法 函数原型: def structural_similarity(*, im1, im2, win_size=None, gradient=False, data_range=None, multichannel=False, gaussian_weights=False, full=False, **kwargs) 参数: :Ndarray,输入图像 : 参数含义im1,im2Ndarray,输入图像win_sizeint or none,optional,滑动窗口的边长,必为奇数,默认值为7, 当gaussian_weights=True时,滑动窗口的大小取决于sigmagradientbool, optional,若为True,返回相对于im2的梯度data_rangefloat,optional,图像灰度级数,图像灰度的最小值和最大可能值,默认情况----根据图像的数据类型进行估计multichannelbool, optional,值为True时将 img.shape[-1] 视为图像通道数,对每个通道单独计算,取平均值作为相似度gaussian_weightsbool, optional,高斯权重,值为True时,平均值和方差在空间上的权重为归一化高斯核 宽度sigma=1.5fullbool, optional,值为true时,返回完整的结构相似性图像

其他参数: use_sample_covariance:若为True,则通过N-1归一化协方差,N是滑动窗口内的像素数 K1,K2: float, 算法参数,默认值K1=0.01,K2=0.03 sigma: float,当gaussian_weights=True时,决定滑动窗口大小

返回值: mssim—平均结构相似度 grad—结构相似性梯度 (gradient=True) S—结构相似性图像(full=True)

下面是通过调用skimage.metrics包下的SSIM算法,结合OpenCV中的阈值分割及轮廓提取算法,找出两幅图像的差异。

import cv2 import imutils from skimage.metrics import structural_similarity import time from skimage import filters, img_as_ubyte import numpy as np start = time.time() # 读入图像,转为灰度图像 src = cv2.imread('C:/Users/Hedgehog/Desktop/right.jpg') img = cv2.imread('C:/Users/Hedgehog/Desktop/left.jpg') grayA = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) grayB = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 计算两个灰度图像之间的结构相似度 (score, diff) = structural_similarity(grayA, grayB, win_size=101, full=True) diff = (diff * 255).astype("uint8") cv2.namedWindow("diff", cv2.WINDOW_NORMAL) cv2.imshow("diff", diff) print("SSIM:{}".format(score)) # 找到不同的轮廓以致于可以在表示为 '不同'的区域放置矩形 # 全局自适应阈值分割(二值化),返回值有两个,第一个是阈值,第二个是二值图像 dst = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] cv2.namedWindow("threshold", cv2.WINDOW_NORMAL) cv2.imshow('threshold', dst) # findContours找轮廓,返回值有两个,第一个是轮廓信息,第二个是轮廓的层次信息(“树”状拓扑结构) # cv2.RETR_EXTERNAL:只检测最外层轮廓 # cv2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向和对角线方向的元素,保留该方向的终点坐标,如矩形的轮廓可用4个角点表示 contours, hierarchy = cv2.findContours(dst.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) print(contours) newimg = np.zeros(dst.shape, np.uint8) # 定义一个和图像分割处理后相同大小的黑色图 # drawContours画轮廓,将找到的轮廓信息画出来 cv2.drawContours(newimg, contours, -1, (255, 255, 255), 1) cv2.namedWindow("contours", cv2.WINDOW_NORMAL) cv2.imshow('contours', newimg) # cnts = cnts[0] if imutils.is_cv3() else cnts[0] 取findContours函数的第一个返回值,即取轮廓信息 # 找到一系列区域,在区域周围放置矩形 for c in contours: (x, y, w, h) = cv2.boundingRect(c) # boundingRect函数:计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的 cv2.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2) # rectangle函数:使用对角线的两点pt1,pt2画一个矩形轮廓 cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 画矩形的图, pt1, pt2,(对角线两点的坐标), 矩形边框的颜色,矩形边框的粗细 end = time.time() print(end - start) # 用cv2.imshow 展现最终对比之后的图片 cv2.namedWindow("right", cv2.WINDOW_NORMAL) cv2.imshow('right', src) cv2.namedWindow("left", cv2.WINDOW_NORMAL) cv2.imshow('left', img) cv2.waitKey(0) cv2.destroyAllWindows()

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有