1
+ function [similarity ,similarityMaps ,weightMaps ] = HaarPSIExt(imgRef ,imgDist ,preprocessWithSubsampling ,wavelet ,boundaryTreatment )
2
+ % HaarPSIExt Computes the Haar wavelet-based perceptual similarity index of two
3
+ % images.
4
+ %
5
+ % Please make sure that grayscale and color values are given in the [0,255]
6
+ % interval! If this is not the case, the HaarPSI cannot be computed
7
+ % correctly.
8
+ %
9
+ % Usage (optional parameters in <>-brackets):
10
+ %
11
+ % [similarity,<similarityMaps>,<weightMaps>] = HaarPSI(imgRef, imgDist, <preprocessWithSubsampling>, <wavelet>, <boundaryTreatment>);
12
+ %
13
+ %
14
+ %
15
+ % Input:
16
+ %
17
+ % imgRef: RGB or grayscale image with values ranging from 0
18
+ % to 255.
19
+ % imgDist: RGB or grayscale image with values ranging from 0
20
+ % to 255.
21
+ % preprocessWithSubsampling: <optional> If 0, the preprocssing step to acommodate for the
22
+ % viewing distance in psychophysical experimentes is omitted.
23
+ % wavelet: <optional> A string specifying the wavelet
24
+ % used in the definition of the perceptual
25
+ % simlarity measure. For a list of possible
26
+ % choices, see the documentation of wfilters.
27
+ % boundaryTreatment: <optional> A string or number specifying
28
+ % boundary treatment. For possible choices,
29
+ % see the documentation of imfilter.
30
+ %
31
+ %
32
+ %
33
+ % Output:
34
+ %
35
+ % similarity: The Haar wavelet-based perceptual similarity index, measured
36
+ % in the interval [0,1].
37
+ % similarityMaps: <optional> Maps of horizontal and vertical local similarities.
38
+ % For RGB images, this variable also includes
39
+ % a similarity map with respect to the two
40
+ % color channesl in the YIQ space.
41
+ % weightMaps: <optional> Weight maps measuring the importance of
42
+ % the local similarities in similarityMaps.
43
+ %
44
+ %
45
+ % Example:
46
+ %
47
+ % imgRef = double(imread('peppers.png'));
48
+ % imgDist = imgRef + randi([-20,20],size(imgRef));
49
+ % imgDist = min(max(imgDist,0),255);
50
+ % similarity = HaarPSI(imgRef,imgDist);
51
+ %
52
+ % Reference:
53
+ %
54
+ % R. Reisenhofer, S. Bosse, G. Kutyniok & T. Wiegand: 'A Haar Wavelet-Based Perceptual Similarity Index for Image Quality Assessment', 2017.
55
+ if nargin < 3
56
+ preprocessWithSubsampling = 1 ;
57
+ end
58
+ if nargin < 4
59
+ wavelet = ' haar' ;
60
+ end
61
+ if nargin < 5
62
+ boundaryTreatment = 0 ;
63
+ end
64
+ colorImage = size(imgRef ,3 ) == 3 ;
65
+
66
+ imgRef = double(imgRef );
67
+ imgDist = double(imgDist );
68
+
69
+ %% initialization and preprocessing
70
+ % constants
71
+ C = 30 ;
72
+ alpha = 4.2 ;
73
+ % transform to YIQ colorspace
74
+ if colorImage
75
+ imgRefY = 0.299 * (imgRef(: ,: ,1 )) + 0.587 * (imgRef(: ,: ,2 )) + 0.114 * (imgRef(: ,: ,3 ));
76
+ imgDistY = 0.299 * (imgDist(: ,: ,1 )) + 0.587 * (imgDist(: ,: ,2 )) + 0.114 * (imgDist(: ,: ,3 ));
77
+ imgRefI = 0.596 * (imgRef(: ,: ,1 )) - 0.274 * (imgRef(: ,: ,2 )) - 0.322 * (imgRef(: ,: ,3 ));
78
+ imgDistI = 0.596 * (imgDist(: ,: ,1 )) - 0.274 * (imgDist(: ,: ,2 )) - 0.322 * (imgDist(: ,: ,3 ));
79
+ imgRefQ = 0.211 * (imgRef(: ,: ,1 )) - 0.523 * (imgRef(: ,: ,2 )) + 0.312 * (imgRef(: ,: ,3 ));
80
+ imgDistQ = 0.211 * (imgDist(: ,: ,1 )) - 0.523 * (imgDist(: ,: ,2 )) + 0.312 * (imgDist(: ,: ,3 ));
81
+ else
82
+ imgRefY = double(imgRef );
83
+ imgDistY = double(imgDist );
84
+ end
85
+
86
+ %% subsampling
87
+ if preprocessWithSubsampling
88
+ imgRefY = HaarPSISubsample(imgRefY ,boundaryTreatment );
89
+ imgDistY = HaarPSISubsample(imgDistY ,boundaryTreatment );
90
+ if colorImage
91
+ imgRefQ = HaarPSISubsample(imgRefQ ,boundaryTreatment );
92
+ imgDistQ = HaarPSISubsample(imgDistQ ,boundaryTreatment );
93
+ imgRefI = HaarPSISubsample(imgRefI ,boundaryTreatment );
94
+ imgDistI = HaarPSISubsample(imgDistI ,boundaryTreatment );
95
+ end
96
+ end
97
+
98
+ %% pre-allocate variables
99
+ if colorImage
100
+ localSimilarities = zeros([size(imgRefY ),3 ]);
101
+ weights = zeros([size(imgRefY ),3 ]);
102
+ else
103
+ localSimilarities = zeros([size(imgRefY ),2 ]);
104
+ weights = zeros([size(imgRefY ),2 ]);
105
+ end
106
+
107
+ %% Haar wavelet decomposition
108
+ nScales = 3 ;
109
+ coeffsRefY = HaarPSIDec(imgRefY ,wavelet ,boundaryTreatment ,nScales );
110
+ coeffsDistY = HaarPSIDec(imgDistY ,wavelet ,boundaryTreatment ,nScales );
111
+ if colorImage
112
+ coeffsRefQ = abs(imfilter(imgRefQ ,ones(2 ,2 )/4 ,' same' ,' conv' ,boundaryTreatment ));
113
+ coeffsDistQ = abs(imfilter(imgDistQ ,ones(2 ,2 )/4 ,' same' ,' conv' ,boundaryTreatment ));
114
+ coeffsRefI = abs(imfilter(imgRefI ,ones(2 ,2 )/4 ,' same' ,' conv' ,boundaryTreatment ));
115
+ coeffsDistI = abs(imfilter(imgDistI ,ones(2 ,2 )/4 ,' same' ,' conv' ,boundaryTreatment ));
116
+ end
117
+
118
+ %% compute weights and similarity for each orientation
119
+ for ori = 1 : 2
120
+ weights(: ,: ,ori ) = max(abs(coeffsRefY(: ,: ,3 + (ori - 1 )*nScales )), abs(coeffsDistY(: ,: ,3 + (ori - 1 )*nScales )));
121
+ coeffsRefYMag = abs(coeffsRefY(: ,: ,(1 : 2 ) + (ori - 1 )*nScales ));
122
+ coeffsDistYMag = abs(coeffsDistY(: ,: ,(1 : 2 ) + (ori - 1 )*nScales ));
123
+ localSimilarities(: ,: ,ori ) = sum(((2 * coeffsRefYMag .* coeffsDistYMag + C )./(coeffsRefYMag .^ 2 + coeffsDistYMag .^ 2 + C )),3 )/2 ;
124
+ end
125
+
126
+ %% compute similarities for color channels
127
+ if colorImage
128
+ similarityI = ((2 * coeffsRefI .* coeffsDistI + C ) ./(coeffsRefI .^ 2 + coeffsDistI .^ 2 + C ));
129
+ similarityQ = ((2 * coeffsRefQ .* coeffsDistQ + C ) ./(coeffsRefQ .^ 2 + coeffsDistQ .^ 2 + C ));
130
+ localSimilarities(: ,: ,3 ) = ((similarityI )+(similarityQ ))/2 ;
131
+ weights(: ,: ,3 ) = (weights(: ,: ,1 ) + weights(: ,: ,2 ))/2 ;
132
+ end
133
+
134
+ %% compute final score
135
+ similarity = HaarPSILogInv(sum((HaarPSILog(localSimilarities(: ),alpha )).*weights(: ))/sum(weights(: )),alpha )^2 ;
136
+
137
+ %% output maps
138
+ if nargout > 1
139
+ similarityMaps = localSimilarities ;
140
+ end
141
+ if nargout > 2
142
+ weightMaps = weights ;
143
+ end
144
+ end
145
+
146
+ function coeffs = HaarPSIDec(X ,wavelet ,boundaryTreatment ,nScales )
147
+ [h ,g ] = wfilters(wavelet );
148
+ coeffs = zeros([size(X ),2 * nScales ]);
149
+ hnew = h ;
150
+ hnew2 = hnew ;
151
+ g2 = g ;
152
+ for k = 1 : nScales
153
+ waveletFilter = hnew2 ' *g2 ;
154
+ coeffs(: ,: ,k ) = imfilter(X ,waveletFilter ,' same' ,' conv' ,boundaryTreatment );
155
+ coeffs(: ,: ,k + nScales ) = imfilter(X ,waveletFilter ' ,' same' ,' conv' ,boundaryTreatment );
156
+ g = conv(h ,dyadup(g ));
157
+ hnew = conv(h ,dyadup(hnew ));
158
+ g2 = g((find(abs(g )>0,1 ,' first' )): (find(abs(g )>0,1 ,' last' )));
159
+ hnew2 = hnew((find(abs(hnew )>0,1 ,' first' )): (find(abs(hnew )>0,1 ,' last' )));
160
+ end
161
+ end
162
+
163
+ function imgSubsampled = HaarPSISubsample(img ,boundaryTreatment )
164
+ imgSubsampled = imfilter(img , ones(2 ,2 )/4 ,' same' ,' conv' ,boundaryTreatment );
165
+ imgSubsampled = imgSubsampled(1 : 2 : end ,1 : 2 : end );
166
+ end
167
+
168
+ function val = HaarPSILog(x ,alpha )
169
+ val = 1 ./(1 + exp(-alpha .*(x )));
170
+ end
171
+
172
+ function val = HaarPSILogInv(x ,alpha )
173
+ val = log(x ./(1 - x ))./alpha ;
174
+ end
175
+
176
+ % Written by Rafael Reisenhofer
177
+ % Built on 08/05/2017
0 commit comments