1
+ import matplotlib .pyplot as plt
2
+ import matplotlib .image as mpimg
3
+ from scipy import ndimage
4
+ from scipy import optimize
5
+ import numpy as np
6
+ import math
7
+
8
+ # Manipulate channels
9
+
10
+ def get_greyscale_image (img ):
11
+ return np .mean (img [:,:,:2 ], 2 )
12
+
13
+ def extract_rgb (img ):
14
+ return img [:,:,0 ], img [:,:,1 ], img [:,:,2 ]
15
+
16
+ def assemble_rbg (img_r , img_g , img_b ):
17
+ shape = (img_r .shape [0 ], img_r .shape [1 ], 1 )
18
+ return np .concatenate ((np .reshape (img_r , shape ), np .reshape (img_g , shape ),
19
+ np .reshape (img_b , shape )), axis = 2 )
20
+
21
+ # Transformations
22
+
23
+ def reduce (img , factor ):
24
+ result = np .zeros ((img .shape [0 ] // factor , img .shape [1 ] // factor ))
25
+ for i in range (result .shape [0 ]):
26
+ for j in range (result .shape [1 ]):
27
+ result [i ,j ] = np .mean (img [i * factor :(i + 1 )* factor ,j * factor :(j + 1 )* factor ])
28
+ return result
29
+
30
+ def rotate (img , angle ):
31
+ return ndimage .rotate (img , angle , reshape = False )
32
+
33
+ def flip (img , direction ):
34
+ return img [::direction ,:]
35
+
36
+ def apply_transformation (img , direction , angle , contrast = 1.0 , brightness = 0.0 ):
37
+ return contrast * rotate (flip (img , direction ), angle ) + brightness
38
+
39
+ # Contrast and brightness
40
+
41
+ def find_contrast_and_brightness1 (D , S ):
42
+ # Fix the contrast and only fit the brightness
43
+ contrast = 0.75
44
+ brightness = (np .sum (D - contrast * S )) / D .size
45
+ return contrast , brightness
46
+
47
+ def find_contrast_and_brightness2 (D , S ):
48
+ # Fit the contrast and the brightness
49
+ A = np .concatenate ((np .ones ((S .size , 1 )), np .reshape (S , (S .size , 1 ))), axis = 1 )
50
+ b = np .reshape (D , (D .size ,))
51
+ x , _ , _ , _ = np .linalg .lstsq (A , b )
52
+ #x = optimize.lsq_linear(A, b, [(-np.inf, -2.0), (np.inf, 2.0)]).x
53
+ return x [1 ], x [0 ]
54
+
55
+ # Compression for greyscale images
56
+
57
+ def generate_all_transformed_blocks (img , source_size , destination_size , step ):
58
+ factor = source_size // destination_size
59
+ transformed_blocks = []
60
+ for k in range ((img .shape [0 ] - source_size ) // step + 1 ):
61
+ for l in range ((img .shape [1 ] - source_size ) // step + 1 ):
62
+ # Extract the source block and reduce it to the shape of a destination block
63
+ S = reduce (img [k * step :k * step + source_size ,l * step :l * step + source_size ], factor )
64
+ # Generate all possible transformed blocks
65
+ for direction , angle in candidates :
66
+ transformed_blocks .append ((k , l , direction , angle , apply_transformation (S , direction , angle )))
67
+ return transformed_blocks
68
+
69
+ def compress (img , source_size , destination_size , step ):
70
+ transformations = []
71
+ transformed_blocks = generate_all_transformed_blocks (img , source_size , destination_size , step )
72
+ i_count = img .shape [0 ] // destination_size
73
+ j_count = img .shape [1 ] // destination_size
74
+ for i in range (i_count ):
75
+ transformations .append ([])
76
+ for j in range (j_count ):
77
+ print ("{}/{} ; {}/{}" .format (i , i_count , j , j_count ))
78
+ transformations [i ].append (None )
79
+ min_d = float ('inf' )
80
+ # Extract the destination block
81
+ D = img [i * destination_size :(i + 1 )* destination_size ,j * destination_size :(j + 1 )* destination_size ]
82
+ # Test all possible transformations and take the best one
83
+ for k , l , direction , angle , S in transformed_blocks :
84
+ contrast , brightness = find_contrast_and_brightness2 (D , S )
85
+ S = contrast * S + brightness
86
+ d = np .sum (np .square (D - S ))
87
+ if d < min_d :
88
+ min_d = d
89
+ transformations [i ][j ] = (k , l , direction , angle , contrast , brightness )
90
+ return transformations
91
+
92
+ def decompress (transformations , source_size , destination_size , step , nb_iter = 8 ):
93
+ factor = source_size // destination_size
94
+ height = len (transformations ) * destination_size
95
+ width = len (transformations [0 ]) * destination_size
96
+ iterations = [np .random .randint (0 , 256 , (height , width ))]
97
+ cur_img = np .zeros ((height , width ))
98
+ for i_iter in range (nb_iter ):
99
+ print (i_iter )
100
+ for i in range (len (transformations )):
101
+ for j in range (len (transformations [i ])):
102
+ # Apply transform
103
+ k , l , flip , angle , contrast , brightness = transformations [i ][j ]
104
+ S = reduce (iterations [- 1 ][k * step :k * step + source_size ,l * step :l * step + source_size ], factor )
105
+ D = apply_transformation (S , flip , angle , contrast , brightness )
106
+ cur_img [i * destination_size :(i + 1 )* destination_size ,j * destination_size :(j + 1 )* destination_size ] = D
107
+ iterations .append (cur_img )
108
+ cur_img = np .zeros ((height , width ))
109
+ return iterations
110
+
111
+ # Compression for color images
112
+
113
+ def reduce_rgb (img , factor ):
114
+ img_r , img_g , img_b = extract_rgb (img )
115
+ img_r = reduce (img_r , factor )
116
+ img_g = reduce (img_g , factor )
117
+ img_b = reduce (img_b , factor )
118
+ return assemble_rbg (img_r , img_g , img_b )
119
+
120
+ def compress_rgb (img , source_size , destination_size , step ):
121
+ img_r , img_g , img_b = extract_rgb (img )
122
+ return [compress (img_r , source_size , destination_size , step ), \
123
+ compress (img_g , source_size , destination_size , step ), \
124
+ compress (img_b , source_size , destination_size , step )]
125
+
126
+ def decompress_rgb (transformations , source_size , destination_size , step , nb_iter = 8 ):
127
+ img_r = decompress (transformations [0 ], source_size , destination_size , step , nb_iter )[- 1 ]
128
+ img_g = decompress (transformations [1 ], source_size , destination_size , step , nb_iter )[- 1 ]
129
+ img_b = decompress (transformations [2 ], source_size , destination_size , step , nb_iter )[- 1 ]
130
+ return assemble_rbg (img_r , img_g , img_b )
131
+
132
+ # Plot
133
+
134
+ def plot_iterations (iterations , target = None ):
135
+ # Configure plot
136
+ plt .figure ()
137
+ nb_row = math .ceil (np .sqrt (len (iterations )))
138
+ nb_cols = nb_row
139
+ # Plot
140
+ for i , img in enumerate (iterations ):
141
+ plt .subplot (nb_row , nb_cols , i + 1 )
142
+ plt .imshow (img , cmap = 'gray' , vmin = 0 , vmax = 255 , interpolation = 'none' )
143
+ if target is None :
144
+ plt .title (str (i ))
145
+ else :
146
+ # Display the RMSE
147
+ plt .title (str (i ) + ' (' + '{0:.2f}' .format (np .sqrt (np .mean (np .square (target - img )))) + ')' )
148
+ frame = plt .gca ()
149
+ frame .axes .get_xaxis ().set_visible (False )
150
+ frame .axes .get_yaxis ().set_visible (False )
151
+ plt .tight_layout ()
152
+
153
+ # Parameters
154
+
155
+ directions = [1 , - 1 ]
156
+ angles = [0 , 90 , 180 , 270 ]
157
+ candidates = [[direction , angle ] for direction in directions for angle in angles ]
158
+
159
+ # Tests
160
+
161
+ def test_greyscale ():
162
+ img = mpimg .imread ('raw.jpg' )
163
+ img = get_greyscale_image (img )
164
+ img = reduce (img , 4 )
165
+ plt .figure ()
166
+ plt .imshow (img , cmap = 'gray' , interpolation = 'none' )
167
+ transformations = compress (img , 8 , 4 , 8 )
168
+ iterations = decompress (transformations , 8 , 4 , 8 )
169
+ plot_iterations (iterations , img )
170
+ plt .show ()
171
+
172
+ def test_rgb ():
173
+ img = mpimg .imread ('raw.jpg' )
174
+ img = reduce_rgb (img , 8 )
175
+ transformations = compress_rgb (img , 8 , 4 , 8 )
176
+ retrieved_img = decompress_rgb (transformations , 8 , 4 , 8 )
177
+ plt .figure ()
178
+ plt .subplot (121 )
179
+ plt .imshow (np .array (img ).astype (np .uint8 ), interpolation = 'none' )
180
+ plt .subplot (122 )
181
+ plt .imshow (retrieved_img .astype (np .uint8 ), interpolation = 'none' )
182
+ plt .show ()
183
+ plt .imsave ("hasilFractal.jpg" ,retrieved_img .astype (np .uint8 ))
184
+
185
+ if __name__ == '__main__' :
186
+ #test_greyscale()
187
+ test_rgb ()
0 commit comments