Skip to content

Commit 3b9599b

Browse files
authored
Add files via upload
1 parent 093324d commit 3b9599b

File tree

3 files changed

+856
-0
lines changed

3 files changed

+856
-0
lines changed

HaarPSI.m

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
function [similarity,similarityMaps,weightMaps] = HaarPSI(imgRef,imgDist,preprocessWithSubsampling)
2+
%HaarPSI 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>);
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+
%
24+
%
25+
%Output:
26+
%
27+
% similarity: The Haar wavelet-based perceptual similarity index, measured
28+
% in the interval [0,1].
29+
% similarityMaps: <optional> Maps of horizontal and vertical local similarities.
30+
% For RGB images, this variable also includes
31+
% a similarity map with respect to the two
32+
% color channesl in the YIQ space.
33+
% weightMaps: <optional> Weight maps measuring the importance of
34+
% the local similarities in similarityMaps.
35+
%
36+
%
37+
%Example:
38+
%
39+
% imgRef = double(imread('peppers.png'));
40+
% imgDist = imgRef + randi([-20,20],size(imgRef));
41+
% imgDist = min(max(imgDist,0),255);
42+
% similarity = HaarPSI(imgRef,imgDist);
43+
%
44+
%Reference:
45+
%
46+
% R. Reisenhofer, S. Bosse, G. Kutyniok & T. Wiegand: 'A Haar Wavelet-Based Perceptual Similarity Index for Image Quality Assessment', 2017.
47+
48+
if nargin < 3
49+
preprocessWithSubsampling = 1;
50+
end
51+
colorImage = size(imgRef,3) == 3;
52+
53+
imgRef = double(imgRef);
54+
imgDist = double(imgDist);
55+
56+
%% initialization and preprocessing
57+
%constants
58+
C = 30;
59+
alpha = 4.2;
60+
%transform to YIQ colorspace
61+
if colorImage
62+
imgRefY = 0.299 * (imgRef(:,:,1)) + 0.587 * (imgRef(:,:,2)) + 0.114 * (imgRef(:,:,3));
63+
imgDistY = 0.299 * (imgDist(:,:,1)) + 0.587 * (imgDist(:,:,2)) + 0.114 * (imgDist(:,:,3));
64+
imgRefI = 0.596 * (imgRef(:,:,1)) - 0.274 * (imgRef(:,:,2)) - 0.322 * (imgRef(:,:,3));
65+
imgDistI = 0.596 * (imgDist(:,:,1)) - 0.274 * (imgDist(:,:,2)) - 0.322 * (imgDist(:,:,3));
66+
imgRefQ = 0.211 * (imgRef(:,:,1)) - 0.523 * (imgRef(:,:,2)) + 0.312 * (imgRef(:,:,3));
67+
imgDistQ = 0.211 * (imgDist(:,:,1)) - 0.523 * (imgDist(:,:,2)) + 0.312 * (imgDist(:,:,3));
68+
else
69+
imgRefY = double(imgRef);
70+
imgDistY = double(imgDist);
71+
end
72+
73+
%% subsampling
74+
if preprocessWithSubsampling
75+
imgRefY = HaarPSISubsample(imgRefY);
76+
imgDistY = HaarPSISubsample(imgDistY);
77+
if colorImage
78+
imgRefQ = HaarPSISubsample(imgRefQ);
79+
imgDistQ = HaarPSISubsample(imgDistQ);
80+
imgRefI = HaarPSISubsample(imgRefI);
81+
imgDistI = HaarPSISubsample(imgDistI);
82+
end
83+
end
84+
85+
%% pre-allocate variables
86+
if colorImage
87+
localSimilarities = zeros([size(imgRefY),3]);
88+
weights = zeros([size(imgRefY),3]);
89+
else
90+
localSimilarities = zeros([size(imgRefY),2]);
91+
weights = zeros([size(imgRefY),2]);
92+
end
93+
94+
%% Haar wavelet decomposition
95+
nScales = 3;
96+
coeffsRefY = HaarPSIDec(imgRefY,nScales);
97+
coeffsDistY = HaarPSIDec(imgDistY,nScales);
98+
if colorImage
99+
coeffsRefQ = abs(conv2(imgRefQ,ones(2,2)/4,'same'));
100+
coeffsDistQ = abs(conv2(imgDistQ,ones(2,2)/4,'same'));
101+
coeffsRefI = abs(conv2(imgRefI,ones(2,2)/4,'same'));
102+
coeffsDistI = abs(conv2(imgDistI,ones(2,2)/4,'same'));
103+
end
104+
105+
%% compute weights and similarity for each orientation
106+
for ori = 1:2
107+
weights(:,:,ori) = max(abs(coeffsRefY(:,:,3 + (ori-1)*nScales)), abs(coeffsDistY(:,:,3 + (ori-1)*nScales)));
108+
coeffsRefYMag = abs(coeffsRefY(:,:,(1:2) + (ori-1)*nScales));
109+
coeffsDistYMag = abs(coeffsDistY(:,:,(1:2) + (ori-1)*nScales));
110+
localSimilarities(:,:,ori) = sum(((2*coeffsRefYMag.*coeffsDistYMag + C)./(coeffsRefYMag.^2 + coeffsDistYMag.^2 + C)),3)/2;
111+
end
112+
113+
%% compute similarities for color channels
114+
if colorImage
115+
similarityI = ((2*coeffsRefI.*coeffsDistI + C) ./(coeffsRefI.^2 + coeffsDistI.^2 + C));
116+
similarityQ = ((2*coeffsRefQ.*coeffsDistQ + C) ./(coeffsRefQ.^2 + coeffsDistQ.^2 + C));
117+
localSimilarities(:,:,3) = ((similarityI)+(similarityQ))/2;
118+
weights(:,:,3) = (weights(:,:,1) + weights(:,:,2))/2;
119+
end
120+
121+
%% compute final score
122+
similarity = HaarPSILogInv(sum((HaarPSILog(localSimilarities(:),alpha)).*weights(:))/sum(weights(:)),alpha)^2;
123+
124+
%% output maps
125+
if nargout > 1
126+
similarityMaps = localSimilarities;
127+
end
128+
if nargout > 2
129+
weightMaps = weights;
130+
end
131+
end
132+
133+
function coeffs = HaarPSIDec(X,nScales)
134+
coeffs = zeros([size(X),2*nScales]);
135+
for k = 1:nScales
136+
haarFilter = 2^(-k)*ones(2^k,2^k);
137+
haarFilter(1:(end/2),:) = -haarFilter(1:(end/2),:);
138+
coeffs(:,:,k) = conv2(X,haarFilter,'same');
139+
coeffs(:,:,k + nScales) = conv2(X,haarFilter','same');
140+
end
141+
end
142+
143+
function imgSubsampled = HaarPSISubsample(img)
144+
imgSubsampled = conv2(img, ones(2,2)/4,'same');
145+
imgSubsampled = imgSubsampled(1:2:end,1:2:end);
146+
end
147+
148+
function val = HaarPSILog(x,alpha)
149+
val = 1./(1 + exp(-alpha.*(x)));
150+
end
151+
152+
function val = HaarPSILogInv(x,alpha)
153+
val = log(x./(1-x))./alpha;
154+
end
155+
156+
% Written by Rafael Reisenhofer
157+
% Built on 08/05/2017
158+

HaarPSIExt.m

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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

Comments
 (0)