├── IW_SSIM_PyTorch.py ├── LICENSE ├── README.txt ├── config.py ├── demo.py ├── images ├── Dist.jpg ├── Dist2.jpg ├── Ref.bmp └── Ref2.bmp ├── result ├── LIVE2 │ ├── Error_Analysis_LIVE2.png │ ├── matlab_iw-ssim_mapped.png │ ├── matlab_iw-ssim_raw.png │ ├── python_iw-ssim_mapped.png │ └── python_iw-ssim_raw.png ├── LIVEMD │ ├── Error_Analysis_LIVEMD.png │ ├── matlab_iw-ssim_mapped.png │ ├── matlab_iw-ssim_raw.png │ ├── python_iw-ssim_mapped.png │ └── python_iw-ssim_raw.png └── TID2013 │ ├── Error_Analysis_TID2013.png │ ├── matlab_iw-ssim_mapped.png │ ├── matlab_iw-ssim_raw.png │ ├── python_iw-ssim_mapped.png │ └── python_iw-ssim_raw.png └── utils.py /IW_SSIM_PyTorch.py: -------------------------------------------------------------------------------- 1 | import torch.nn.functional as F 2 | import pyrtools as pt 3 | import numpy as np 4 | import torch 5 | 6 | 7 | class IW_SSIM(): 8 | def __init__(self, iw_flag=True, Nsc=5, blSzX=3, blSzY=3, parent=True, 9 | sigma_nsq=0.4, use_cuda=False, use_double=False): 10 | # MS-SSIM parameters 11 | self.K = [0.01, 0.03] 12 | self.L = 255 13 | self.weight = [0.0448, 0.2856, 0.3001, 0.2363, 0.1333] 14 | self.winsize = 11 15 | self.sigma = 1.5 16 | 17 | # IW-SSIM parameters 18 | self.iw_flag = iw_flag 19 | self.Nsc = Nsc # scales 20 | self.blSzX = blSzX # Neighbor size 21 | self.blSzY = blSzY 22 | self.parent = parent 23 | self.sigma_nsq = sigma_nsq 24 | 25 | self.bound = np.ceil((self.winsize-1)/2) 26 | self.bound1 = self.bound - np.floor((self.blSzX-1)/2) 27 | self.use_cuda = use_cuda 28 | self.use_double = use_double 29 | 30 | self.samplet = torch.tensor([1.0]) 31 | if self.use_cuda: 32 | self.samplet = self.samplet.cuda() 33 | if self.use_double: 34 | self.samplet = self.samplet.double() 35 | self.samplen = np.array([1.0]) 36 | if not self.use_double: 37 | self.samplen = self.samplen.astype('float32') 38 | 39 | def fspecial(self, fltr, ws, **kwargs): 40 | if fltr == 'uniform': 41 | return np.ones((ws, ws)) / ws**2 42 | 43 | elif fltr == 'gaussian': 44 | x, y = np.mgrid[-ws//2 + 1:ws//2 + 1, -ws//2 + 1:ws//2 + 1] 45 | g = np.exp(-((x**2 + y**2)/(2.0*kwargs['sigma']**2))) 46 | g[g < np.finfo(g.dtype).eps*g.max()] = 0 47 | assert g.shape == (ws, ws) 48 | den = g.sum() 49 | if den != 0: 50 | g /= den 51 | return g 52 | 53 | return None 54 | 55 | def get_pyrd(self, imgo, imgd): 56 | imgopr = {} 57 | imgdpr = {} 58 | lpo = pt.pyramids.LaplacianPyramid(imgo, height=5) 59 | lpd = pt.pyramids.LaplacianPyramid(imgd, height=5) 60 | for scale in range(1, self.Nsc + 1): 61 | imgopr[scale] = torch.from_numpy(lpo.pyr_coeffs[(scale-1, 0)]).unsqueeze(0).unsqueeze(0).type(self.samplet.type()) 62 | imgdpr[scale] = torch.from_numpy(lpd.pyr_coeffs[(scale-1, 0)]).unsqueeze(0).unsqueeze(0).type(self.samplet.type()) 63 | 64 | return imgopr, imgdpr 65 | 66 | def scale_qualty_maps(self, imgopr, imgdpr): 67 | 68 | ms_win = self.fspecial('gaussian', ws=self.winsize, sigma=self.sigma) 69 | ms_win = torch.from_numpy(ms_win).unsqueeze(0).unsqueeze(0).type(self.samplet.type()) 70 | C1 = (self.K[0]*self.L)**2 71 | C2 = (self.K[1]*self.L)**2 72 | cs_map = {} 73 | for i in range(1, self.Nsc+1): 74 | imgo = imgopr[i] 75 | imgd = imgdpr[i] 76 | mu1 = F.conv2d(imgo, ms_win) 77 | mu2 = F.conv2d(imgd, ms_win) 78 | sigma12 = F.conv2d(imgo*imgd, ms_win) - mu1*mu2 79 | sigma1_sq = F.conv2d(imgo**2, ms_win) - mu1*mu1 80 | sigma2_sq = F.conv2d(imgd**2, ms_win) - mu2*mu2 81 | sigma1_sq = torch.max(torch.zeros(sigma1_sq.shape).type(self.samplet.type()), sigma1_sq) 82 | sigma2_sq = torch.max(torch.zeros(sigma2_sq.shape).type(self.samplet.type()), sigma2_sq) 83 | cs_map[i] = (2*sigma12+C2) / (sigma1_sq + sigma2_sq + C2) 84 | if i == self.Nsc: 85 | l_map = (2*mu1*mu2+C1) / (mu1**2+mu2**2+C1) 86 | 87 | return l_map, cs_map 88 | 89 | def roll(self, x, shift, dim): 90 | if dim == 0: 91 | return torch.cat((x[-shift:, :], x[:-shift, :]), dim) 92 | else: 93 | return torch.cat((x[:, -shift:], x[:, :-shift]), dim) 94 | 95 | def imenlarge2(self, im): 96 | _, _, M, N = im.shape 97 | t1 = F.upsample(im, size=(int(4*M-3), int(4*N-3)), mode='bilinear') 98 | t2 = torch.zeros([1, 1, 4*M-1, 4*N-1]).type(self.samplet.type()) 99 | t2[:, :, 1: -1, 1:-1] = t1 100 | t2[:, :, 0, :] = 2*t2[:, :, 1, :] - t2[:, :, 2, :] 101 | t2[:, :, -1, :] = 2*t2[:, :, -2, :] - t2[:, :, -3, :] 102 | t2[:, :, :, 0] = 2*t2[:, :, :, 1] - t2[:, :, :, 2] 103 | t2[:, :, :, -1] = 2*t2[:, :, :, -2] - t2[:, :, :, -3] 104 | imu = t2[:, :, ::2, ::2] 105 | 106 | return imu 107 | 108 | def info_content_weight_map(self, imgopr, imgdpr): 109 | 110 | tol = 1e-15 111 | iw_map = {} 112 | for scale in range(1, self.Nsc): 113 | 114 | imgo = imgopr[scale] 115 | imgd = imgdpr[scale] 116 | win = np.ones([self.blSzX, self.blSzY]) 117 | win = win / np.sum(win) 118 | win = torch.from_numpy(win).unsqueeze(0).unsqueeze(0).type(self.samplet.type()) 119 | padding = int((self.blSzX-1)/2) 120 | 121 | # Prepare for estimating IW-SSIM parameters 122 | mean_x = F.conv2d(imgo, win, padding=padding) 123 | mean_y = F.conv2d(imgd, win, padding=padding) 124 | cov_xy = F.conv2d(imgo*imgd, win, padding=padding) - mean_x*mean_y 125 | ss_x = F.conv2d(imgo**2, win, padding=padding) - mean_x**2 126 | ss_y = F.conv2d(imgd**2, win, padding=padding) - mean_y**2 127 | 128 | ss_x[ss_x < 0] = 0 129 | ss_y[ss_y < 0] = 0 130 | 131 | # Estimate gain factor and error 132 | g = cov_xy / (ss_x + tol) 133 | vv = (ss_y - g*cov_xy) 134 | g[ss_x < tol] = 0 135 | vv[ss_x < tol] = ss_y[ss_x < tol] 136 | ss_x[ss_x < tol] = 0 137 | g[ss_y < tol] = 0 138 | vv[ss_y < tol] = 0 139 | 140 | # Prepare parent band 141 | aux = imgo 142 | _, _, Nsy, Nsx = aux.shape 143 | prnt = (self.parent and scale < self.Nsc-1) 144 | BL = torch.zeros([1, 1, aux.shape[2], aux.shape[3], 1+prnt]) 145 | if self.use_cuda: 146 | BL = BL.cuda() 147 | if self.use_double: 148 | BL = BL.double() 149 | 150 | BL[:, :, :, :, 0] = aux 151 | if prnt: 152 | auxp = imgopr[scale+1] 153 | auxp = self.imenlarge2(auxp) 154 | BL[:, :, :, :, 1] = auxp[:, :, 0:Nsy, 0:Nsx] 155 | imgo = BL 156 | _, _, nv, nh, nb = imgo.shape 157 | 158 | block = torch.tensor([win.shape[2], win.shape[3]]) 159 | if self.use_cuda: 160 | block = block.cuda() 161 | 162 | # Group neighboring pixels 163 | nblv = nv-block[0]+1 164 | nblh = nh-block[1]+1 165 | nexp = nblv*nblh 166 | N = torch.prod(block) + prnt 167 | Ly = int((block[0]-1)/2) 168 | Lx = int((block[1]-1)/2) 169 | Y = torch.zeros([nexp, N]).type(self.samplet.type()) 170 | 171 | n = -1 172 | for ny in range(-Ly, Ly+1): 173 | for nx in range(-Lx, Lx+1): 174 | n = n + 1 175 | temp = imgo[0, 0, :, :, 0] 176 | foo1 = self.roll(temp, ny, 0) 177 | foo = self.roll(foo1, nx, 1) 178 | foo = foo[Ly: Ly+nblv, Lx: Lx+nblh] 179 | Y[:, n] = foo.flatten() 180 | if prnt: 181 | n = n + 1 182 | temp = imgo[0, 0, :, :, 1] 183 | foo = temp 184 | foo = foo[Ly: Ly+nblv, Lx: Lx+nblh] 185 | Y[:, n] = foo.flatten() 186 | 187 | C_u = torch.mm(torch.transpose(Y, 0, 1), Y) / nexp.type(self.samplet.type()) 188 | eig_values, H = torch.eig(C_u, eigenvectors=True) 189 | eig_values = eig_values.type(self.samplet.type()) 190 | H = H.type(self.samplet.type()) 191 | if self.use_double: 192 | L = torch.diag(eig_values[:, 0] * (eig_values[:, 0] > 0).double()) * torch.sum(eig_values) / ((torch.sum(eig_values[:,0] * (eig_values[:, 0] > 0).double())) + (torch.sum(eig_values[:, 0] * (eig_values[:, 0] > 0).double())==0)) 193 | else: 194 | L = torch.diag(eig_values[:, 0] * (eig_values[:, 0] > 0).float()) * torch.sum(eig_values) / ((torch.sum(eig_values[:,0] * (eig_values[:, 0] > 0).float())) + (torch.sum(eig_values[:, 0] * (eig_values[:, 0] > 0).float())==0)) 195 | C_u = torch.mm(torch.mm(H, L), torch.transpose(H, 0, 1)) 196 | C_u_inv = torch.inverse(C_u) 197 | ss = (torch.mm(Y, C_u_inv))*Y / N.type(self.samplet.type()) 198 | ss = torch.sum(ss, 1) 199 | ss = ss.view(nblv, nblh) 200 | ss = ss.unsqueeze(0).unsqueeze(0) 201 | g = g[:, :, Ly: Ly+nblv, Lx: Lx+nblh] 202 | vv = vv[:, :, Ly: Ly+nblv, Lx: Lx+nblh] 203 | 204 | # Calculate mutual information 205 | infow = torch.zeros(g.shape).type(self.samplet.type()) 206 | for j in range(len(eig_values)): 207 | infow = infow + torch.log2(1 + ((vv + (1 + g*g)*self.sigma_nsq)*ss*eig_values[j, 0]+self.sigma_nsq*vv) / (self.sigma_nsq*self.sigma_nsq)) 208 | infow[infow < tol] = 0 209 | iw_map[scale] = infow 210 | 211 | return iw_map 212 | 213 | def test(self, imgo, imgd): 214 | 215 | imgo = imgo.astype(self.samplen.dtype) 216 | imgd = imgd.astype(self.samplen.dtype) 217 | imgopr, imgdpr = self.get_pyrd(imgo, imgd) 218 | l_map, cs_map = self.scale_qualty_maps(imgopr, imgdpr) 219 | if self.iw_flag: 220 | iw_map = self.info_content_weight_map(imgopr, imgdpr) 221 | 222 | wmcs = [] 223 | for s in range(1, self.Nsc+1): 224 | cs = cs_map[s] 225 | if s == self.Nsc: 226 | cs = cs_map[s]*l_map 227 | 228 | if self.iw_flag: 229 | if s < self.Nsc: 230 | iw = iw_map[s] 231 | if self.bound1 != 0: 232 | iw = iw[:, :, int(self.bound1): -int(self.bound1), int(self.bound1): -int(self.bound1)] 233 | else: 234 | iw = iw[:, :, int(self.bound1):, int(self.bound1):] 235 | else: 236 | iw = torch.ones(cs.shape).type(self.samplet.type()) 237 | wmcs.append(torch.sum(cs*iw) / torch.sum(iw)) 238 | else: 239 | wmcs.append(torch.mean(cs)) 240 | 241 | wmcs = torch.tensor(wmcs).type(self.samplet.type()) 242 | self.weight = torch.tensor(self.weight).type(self.samplet.type()) 243 | score = torch.prod((torch.abs(wmcs))**(self.weight)) 244 | 245 | return score 246 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | Copyright (c) 2019, Xinyu Guo 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | The procedure to install and run PyTorch IW-SSIM is provided below. 2 | 3 | Note: This implementation is based on the Matlab version IW-SSIM. The Matlab 4 | version IW-SSIM can be found here: https://ece.uwaterloo.ca/~z70wang/research/iwssim/ 5 | 6 | ********************************** 7 | INSTALLATION 8 | ********************************** 9 | You may follow the installation guide (May. 2020) that we provide below for installing the dependencies: 10 | 11 | 1. Install Anaconda3 (A distribution of Python3, please see https://www.anaconda.com/distribution/) 12 | 2. Create a new virtual environment: 13 | 2.1. Open terminal (Ubuntu) 14 | 2.2. Run "conda create -n envname python=3.6" 15 | 2.3. Install packages: 16 | 2.3.1 numpy "conda install -c anaconda numpy" 17 | 2.3.2 pillow "conda install -c anaconda pillow" 18 | 2.3.3 scipy "conda install -c anaconda scipy" 19 | 2.3.4 pyrtools "pip install pyrtools" 20 | 2.3.5 easydict "conda install -c conda-forge easydict" 21 | 2.3.6 PyTorch "conda install pytorch==1.2.0 torchvision==0.4.0 cudatoolkit=10.0 -c pytorch" 22 | 23 | We have tested the code on Ubuntu 18.04 with both CPU and GPU mode. 24 | 25 | ********************************** 26 | PyTorch IW-SSIM USAGE 27 | ********************************** 28 | 1. Open terminal (Ubuntu) 29 | 2. Activate the virtual environment: "conda activate envname" 30 | 3. Run PyTorch IW-SSIM, run "python test.py" 31 | 3.1. If you are using GPU, add "--use_cuda" to your command above. 32 | 3.2. If you want a more precise result add "use_double" to your command above. 33 | 34 | Note: PyTorch IW-SSIM requires RGB Color images as input and will convert it to grayscale itself. 35 | 36 | ********************************** 37 | PyTorch IW-SSIM Time Analysis 38 | ********************************** 39 | We compare PyTorch version IW-SSIM with Matlab version IW-SSIM with regard to time. The results are 40 | provided below. We run the test on Ref.bmp and Ref2.bmp, and we use a machine with 3.6GHz Intel Core 41 | i9-9900K processor, 32GB RAM, GeForce GTX 1660 GPU and Ubuntu 18.04 operating system. For one test we 42 | run 100 times. The same test is run 10 times and we take the average to get the following results. 43 | 44 | Method Execution Time Execution time(Relative to Python GPU version) 45 | 46 | Python(GPU) 0.1912s/image 1.00 47 | Matlab 0.3148s/image 1.65 48 | Python(CPU) 0.3572s/image 1.87 49 | 50 | Note: The provided results are given when using single data type. 51 | 52 | ********************************** 53 | PyTorch IW-SSIM Performance Analysis 54 | ********************************** 55 | We compare PyTorch version IW-SSIM with Matlab version IW-SSIM with regard to performance. 56 | The results are provided below. We use three database (LIVE2, TID2013, LIVEMD) to test the 57 | PyTorch IW-SSIM. 58 | 59 | Database Python version Matlab version 60 | PLCC SRCC PLCC SRCC 61 | 62 | LIVE2 0.9522, 0.9567 0.9522, 0.9567 63 | TID2013 0.8319, 0.7779 0.8319, 0.7779 64 | LIVEMD 0.9109, 0.8836 0.9109, 0.8836 65 | 66 | The scatter plots are put in the result folder. 67 | 68 | Note: The provided results are given when using single data type. 69 | 70 | ********************************** 71 | Citation 72 | ********************************** 73 | ### references 74 | We are making the PyTorch IW-SSIM model available to the research community free of charge. 75 | If you use this model in your research, we kindly ask that you reference our papers listed below: 76 | 77 | Zhou Wang and Qiang Li, "Information Content Weighting for Perceptual Image Quality Assessment," 78 | IEEE Transactions on Image Processing, vol. 20, no. 5, pp. 1185-1198, May 2011. 79 | 80 | @article{wang2010information, 81 | title={Information content weighting for perceptual image quality assessment}, 82 | author={Wang, Zhou and Li, Qiang}, 83 | journal={IEEE Transactions on image processing}, 84 | volume={20}, 85 | number={5}, 86 | pages={1185--1198}, 87 | year={2010}, 88 | publisher={IEEE} 89 | } 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | from easydict import EasyDict as edict 2 | 3 | __C = edict() 4 | 5 | # cfg is treated as a global variable. 6 | # Need add "from config import cfg" for each file to use cfg. 7 | cfg = __C 8 | 9 | # Include IW pooling 10 | __C.iw_flag = True 11 | # number of scales 12 | __C.Nsc = 5 13 | # neigborhood size 14 | __C.blSzX = 3 15 | __C.blSzY = 3 16 | # use parent scale 17 | __C.parent = True 18 | # noise level 19 | __C.sigma_nsq = 0.4 20 | # CUDA config 21 | __C.use_cuda = False 22 | # Data type (True: more similar to Matlab version but will be slower) 23 | __C.use_double = False 24 | 25 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | from PIL import Image 3 | import time 4 | 5 | from IW_SSIM_PyTorch import IW_SSIM 6 | from utils import * 7 | from config import * 8 | 9 | 10 | def main(): 11 | 12 | iw_ssim = IW_SSIM(iw_flag=args.iw_flag, Nsc=args.Nsc, blSzX=args.blSzX, 13 | blSzY=args.blSzY, parent=args.parent, sigma_nsq=args.sigma_nsq, 14 | use_cuda=args.use_cuda, use_double=args.use_double) 15 | 16 | iw_raw_scores = [] 17 | for k in range(num_run): 18 | if k == 1: 19 | start = time.time() 20 | for i in range(num_imgs): 21 | iw_score = iw_ssim.test(rgb2gray(imgos[i]), rgb2gray(imgds[i])) # test one image 22 | end = time.time() 23 | print('Avg time for one image', (end-start)/((num_run-1)*num_imgs), 's') 24 | print('Total time:', end-start, 's') 25 | 26 | 27 | if __name__ == "__main__": 28 | 29 | parser = ArgumentParser(description='PyTorch IW-SSIM') 30 | parser.add_argument("--iw_flag", type=bool, default=cfg.iw_flag) 31 | parser.add_argument('--Nsc', type=int, default=cfg.Nsc, 32 | help='iw-ssim scales (default: 5)') 33 | parser.add_argument('--blSzX', type=int, default=cfg.blSzX, 34 | help='iw-ssim neighborhood size (default: 3)') 35 | parser.add_argument('--blSzY', type=int, default=cfg.blSzY, 36 | help='iw-ssim neighborhood size (default: 3)') 37 | parser.add_argument('--parent', type=bool, default=cfg.parent, 38 | help='incluse parent scale in neighborhood (default: True)') 39 | parser.add_argument('--sigma_nsq', type=float, default=cfg.sigma_nsq, 40 | help='HVS noise (default: 0.4)') 41 | parser.add_argument('--use_cuda', type=bool, default=cfg.use_cuda, 42 | help='use cuda (default: True)') 43 | parser.add_argument('--use_double', type=bool, default=cfg.use_double, 44 | help='use_double (default: False)') 45 | 46 | args = parser.parse_args() 47 | 48 | # Time test 49 | img1 = np.asarray(Image.open('./images/Ref.bmp')) 50 | img2 = np.asarray(Image.open('./images/Ref2.bmp')) 51 | img3 = np.asarray(Image.open('./images/Dist.jpg')) 52 | img4 = np.asarray(Image.open('./images/Dist2.jpg')) 53 | imgos = [img2, img1] 54 | imgds = [img4, img3] 55 | mos = [1, 1] 56 | num_imgs = 2 57 | num_run = 100 58 | 59 | main() 60 | 61 | 62 | -------------------------------------------------------------------------------- /images/Dist.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/images/Dist.jpg -------------------------------------------------------------------------------- /images/Dist2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/images/Dist2.jpg -------------------------------------------------------------------------------- /images/Ref.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/images/Ref.bmp -------------------------------------------------------------------------------- /images/Ref2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/images/Ref2.bmp -------------------------------------------------------------------------------- /result/LIVE2/Error_Analysis_LIVE2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVE2/Error_Analysis_LIVE2.png -------------------------------------------------------------------------------- /result/LIVE2/matlab_iw-ssim_mapped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVE2/matlab_iw-ssim_mapped.png -------------------------------------------------------------------------------- /result/LIVE2/matlab_iw-ssim_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVE2/matlab_iw-ssim_raw.png -------------------------------------------------------------------------------- /result/LIVE2/python_iw-ssim_mapped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVE2/python_iw-ssim_mapped.png -------------------------------------------------------------------------------- /result/LIVE2/python_iw-ssim_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVE2/python_iw-ssim_raw.png -------------------------------------------------------------------------------- /result/LIVEMD/Error_Analysis_LIVEMD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVEMD/Error_Analysis_LIVEMD.png -------------------------------------------------------------------------------- /result/LIVEMD/matlab_iw-ssim_mapped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVEMD/matlab_iw-ssim_mapped.png -------------------------------------------------------------------------------- /result/LIVEMD/matlab_iw-ssim_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVEMD/matlab_iw-ssim_raw.png -------------------------------------------------------------------------------- /result/LIVEMD/python_iw-ssim_mapped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVEMD/python_iw-ssim_mapped.png -------------------------------------------------------------------------------- /result/LIVEMD/python_iw-ssim_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/LIVEMD/python_iw-ssim_raw.png -------------------------------------------------------------------------------- /result/TID2013/Error_Analysis_TID2013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/TID2013/Error_Analysis_TID2013.png -------------------------------------------------------------------------------- /result/TID2013/matlab_iw-ssim_mapped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/TID2013/matlab_iw-ssim_mapped.png -------------------------------------------------------------------------------- /result/TID2013/matlab_iw-ssim_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/TID2013/matlab_iw-ssim_raw.png -------------------------------------------------------------------------------- /result/TID2013/python_iw-ssim_mapped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/TID2013/python_iw-ssim_mapped.png -------------------------------------------------------------------------------- /result/TID2013/python_iw-ssim_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack-guo-xy/Python-IW-SSIM/f9de37cdb4c459fd188c611e377a87a54516d3cd/result/TID2013/python_iw-ssim_raw.png -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def rgb2gray(rgb): 5 | r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] 6 | gray = 0.2989 * r + 0.5870 * g + 0.1140 * b 7 | 8 | return np.round(gray) 9 | --------------------------------------------------------------------------------