Skip to content

Commit cc142b1

Browse files
pablociancclauss
andauthored
Implemention of an algorithm for image style reconstruction (#14233)
* Add gramian algorithm * Update docstring with additional references Added references to Gram matrices and neural style transfer in the docstring. --------- Co-authored-by: Christian Clauss <cclauss@me.com>
1 parent c9a815a commit cc142b1

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

computer_vision/gramian.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""
2+
Image style reconstruction with Gram matrices.
3+
4+
https://en.wikipedia.org/wiki/Gram_matrix
5+
https://en.wikipedia.org/wiki/Neural_style_transfer
6+
https://arxiv.org/pdf/1603.08155#page=7&zoom=auto,-294,3
7+
"""
8+
9+
import numpy as np
10+
11+
12+
def gram_matrix(mat: np.ndarray) -> np.ndarray:
13+
"""
14+
Returns the Gram (Gramian) matrix of an image.
15+
16+
:param mat: matrix of shape (C, H, W); C = color channels, H = height, W = width.
17+
:type mat: np.ndarray
18+
:return: matrix of shape (C, C).
19+
:rtype: np.ndarray
20+
21+
Examples
22+
--------
23+
>>> gram_matrix(np.ones((2,5,5)))
24+
array([[0.5, 0.5],
25+
[0.5, 0.5]])
26+
>>> gram_matrix(np.ones((3,5,5)))
27+
array([[0.33333333, 0.33333333, 0.33333333],
28+
[0.33333333, 0.33333333, 0.33333333],
29+
[0.33333333, 0.33333333, 0.33333333]])
30+
>>> gram_matrix(np.ones((3,5,5))).shape
31+
(3, 3)
32+
"""
33+
color, height, width = mat.shape
34+
vec = mat.reshape(color, height * width)
35+
gram = vec @ vec.T
36+
return gram / (color * height * width)
37+
38+
39+
def gram_loss(input_features: np.ndarray, reference_features: np.ndarray) -> np.float64:
40+
"""
41+
Calculates the squared Frobenius norm of the difference between
42+
the Gram matrices of the input and reference image.
43+
44+
:param input_features: Feature map of shape (C, H, W)
45+
:type input_features: np.ndarray
46+
:param reference_features: Feature map of shape (C, H, W)
47+
:type reference_features: np.ndarray
48+
:return: Gram loss between the two feature maps.
49+
:rtype: float64
50+
51+
Examples
52+
--------
53+
>>> a = np.random.randn(3,5,5)
54+
>>> gram_loss(a, a)
55+
np.float64(0.0)
56+
>>> a = np.zeros((3,5,5))
57+
>>> b = np.ones((3,5,5))
58+
>>> gram_loss(a, b)
59+
np.float64(1.0)
60+
"""
61+
input_gram = gram_matrix(input_features)
62+
reference_gram = gram_matrix(reference_features)
63+
return np.sum(np.square(input_gram - reference_gram)).astype(np.float64)
64+
65+
66+
if __name__ == "__main__":
67+
import doctest
68+
69+
doctest.testmod()

0 commit comments

Comments
 (0)