Skip to content

Commit eb76ab9

Browse files
committed
init commit
1 parent b6e5054 commit eb76ab9

22 files changed

+2223
-0
lines changed

BinaryTree.py

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import copy
2+
import numpy as np
3+
4+
class BinaryTree:
5+
@staticmethod
6+
def saver(idx):
7+
def idxConvert(idx):
8+
for i in range(1, len(idx)):
9+
r = idx[i].shape[1] // idx[i-1].shape[1]
10+
for k in range(idx[i].shape[0]):
11+
for ii in range(idx[i].shape[1]):
12+
for jj in range(idx[i].shape[2]):
13+
if idx[i-1][k,ii//r,jj//r,0] < 0.5:
14+
idx[i][k, ii, jj, 0] = -2
15+
return idx
16+
stream = []
17+
idx = idxConvert(idx)
18+
for i in range(0, len(idx)):
19+
for k in range(idx[i].shape[0]):
20+
for ii in range(idx[i].shape[1]):
21+
for jj in range(idx[i].shape[2]):
22+
if idx[i][k,ii,jj,0] > -1:
23+
stream.append(idx[i][k,ii,jj,0])
24+
return stream
25+
@staticmethod
26+
def loader(stream, S):
27+
idx, ct = [], 0
28+
for i in range(len(S)):
29+
idx.append(np.zeros(S[i]).astype('int16'))
30+
for k in range(idx[0].shape[0]):
31+
for ii in range(idx[0].shape[1]):
32+
for jj in range(idx[0].shape[2]):
33+
idx[0][k,ii,jj,0] = stream[ct]
34+
ct += 1
35+
for i in range(1, len(idx)):
36+
r = idx[i].shape[1] // idx[i-1].shape[1]
37+
for k in range(idx[i].shape[0]):
38+
for ii in range(idx[i].shape[1]):
39+
for jj in range(idx[i].shape[2]):
40+
if idx[i-1][k,ii//r,jj//r,0] == 0:
41+
idx[i][k,ii,jj,0] = 0
42+
else:
43+
idx[i][k,ii,jj,0] = stream[ct]
44+
ct += 1
45+
return idx
46+
@staticmethod
47+
def checker(idx, ref_idx):
48+
for i in range(len(idx)):
49+
s = np.sum(np.abs(idx[i]-ref_idx[i]))
50+
assert(s == 0), "Error!"
51+
52+
@staticmethod
53+
def UnitTest():
54+
def gen_data(S):
55+
idx = [np.random.randint(2, size=S[0])]
56+
for i in range(1,len(S)):
57+
r = S[i][1] // S[i-1][1]
58+
idx.append(np.random.randint(2, size=S[i]))
59+
for k in range(idx[i].shape[0]):
60+
for ii in range(idx[i].shape[1]):
61+
for jj in range(idx[i].shape[2]):
62+
if idx[i-1][k,ii//r,jj//r, 0] == 0:
63+
idx[i][k,ii,jj,0] = 0
64+
return idx
65+
S = [(5,4,4,1), (5,8,8,1),(5,16,16,1),(5,64,64,1)]
66+
idx = gen_data(S)
67+
stream = BinaryTree.saver(copy.deepcopy(idx))
68+
idxd = BinaryTree.loader(stream, S)
69+
BinaryTree.checker(idxd, idx)
70+
print("UnitTest Pass")

EntropyCoding.py

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import numpy as np
2+
import copy
3+
from Huffman import Huffman
4+
from BinaryTree import BinaryTree
5+
6+
class EntropyCoding():
7+
def __init__(self, par):
8+
self.par = par
9+
self.EC_list = {}
10+
11+
def idx_select(self, label, idx=None):
12+
if idx is None:
13+
return label
14+
tmp = []
15+
r = label.shape[1] // idx.shape[1]
16+
for i in range(label.shape[0]):
17+
for j in range(label.shape[1]):
18+
for k in range(label.shape[2]):
19+
if idx[i, j//r, k//r] == 1:
20+
tmp.append(label[i,j,k, 0])
21+
return np.array(tmp).astype('int32')
22+
23+
def inverse_idx_select(self, tmp, idx, S):
24+
label = np.zeros(S)
25+
r = label.shape[1] // idx.shape[1]
26+
ct = 0
27+
for i in range(label.shape[0]):
28+
for j in range(label.shape[1]):
29+
for k in range(label.shape[2]):
30+
if idx[i, j//r, k//r] == 1:
31+
label[i,j,k,0] = tmp[ct]
32+
ct += 1
33+
return label
34+
35+
def fit(self, save):
36+
label_list, idx_list = save['label'], save['idx']
37+
for i in range(1, self.par['n_hop']+1):
38+
label, idx = label_list['hop'+str(i)], idx_list['hop'+str(i)]
39+
tmp_list = [Huffman().fit(label[0])]
40+
for j in range(1, len(self.par['win']['hop'+str(i)])):
41+
tmp_list.append(Huffman().fit(self.idx_select(label[j], idx[j-1])))
42+
self.EC_list['hop'+str(i)] = tmp_list
43+
return self
44+
45+
def refit(self, save, par):
46+
label_list, idx_list = save['label'], save['idx']
47+
for i in range(1, self.par['n_hop']+1):
48+
label, idx = label_list['hop'+str(i)], idx_list['hop'+str(i)]
49+
if par['hop'+str(i)][0][0] == True:
50+
self.EC_list['hop'+str(i)][0] = Huffman().fit(label[0])
51+
for j in range(1, len(self.par['win']['hop'+str(i)])):
52+
if par['hop'+str(i)][j][0] == True:
53+
self.EC_list['hop'+str(i)][j] = Huffman().fit(self.idx_select(label[j], idx[j-1]))
54+
return self
55+
56+
def encode(self, save, S=1024):
57+
stream = {'idx':{}, 'label':{}}
58+
label_list, idx_list = save['label'], save['idx']
59+
n_img = label_list['hop1'][0].shape[0]
60+
for i in range(1, self.par['n_hop']+1):
61+
label, idx = label_list['hop'+str(i)], idx_list['hop'+str(i)]
62+
st = BinaryTree.saver(idx)
63+
stream['idx']['hop'+str(i)] = st
64+
print('Hop-%d'%(i))
65+
print(' save tree:%1.8f'%(len(st)/(n_img*S**2)))
66+
tmp_st = [self.EC_list['hop'+str(i)][0].encode(label[0])]
67+
print(' Level-0 Huffman %1.8f bpp'%((len(tmp_st[-1])) / (n_img*S**2)))
68+
for j in range(1, len(self.par['win']['hop'+str(i)])):
69+
st = self.EC_list['hop'+str(i)][j].encode(self.idx_select(label[j], idx[j-1]))
70+
tmp_st.append(st)
71+
print(' Level-%d Huffman %1.8f bpp'%(j, len(st)/(n_img*S**2)))
72+
stream['label']['hop'+str(i)] = tmp_st
73+
return stream
74+
75+
def decode(self, stream):
76+
save = {'label':{}, 'idx':{}}
77+
for i in range(1, self.par['n_hop']+1):
78+
if len(self.par['shape']['hop'+str(i)]) > 1:
79+
save['idx']['hop'+str(i)] = BinaryTree.loader(stream['idx']['hop'+str(i)], self.par['shape']['hop'+str(i)][:-1])
80+
else:
81+
save['idx']['hop'+str(i)] = []
82+
tmp, _ = self.EC_list['hop'+str(i)][0].decode(stream['label']['hop'+str(i)][0])
83+
tmp = tmp.reshape(self.par['shape']['hop'+str(i)][0])
84+
label = [tmp]
85+
for j in range(1, len(self.par['win']['hop'+str(i)])):
86+
tmp, _ = self.EC_list['hop'+str(i)][j].decode(stream['label']['hop'+str(i)][j])
87+
tmp = self.inverse_idx_select(tmp, save['idx']['hop'+str(i)][j-1], self.par['shape']['hop'+str(i)][j])
88+
label.append(tmp)
89+
save['label']['hop'+str(i)] = label
90+
return save

GIC.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import numpy as np
2+
import os
3+
import pickle
4+
import copy
5+
import json
6+
import warnings
7+
warnings.filterwarnings("ignore")
8+
os.environ["CUDA_VISIBLE_DEVICES"]="6,7"
9+
from load_img import Load_from_Folder, Load_Images
10+
from evaluate import Time, MSE, PSNR
11+
from MBMBVQ import MBMBVQ
12+
from EntropyCoding import EntropyCoding
13+
14+
class GIC():
15+
def __init__(self, par):
16+
self.MBMBVQ = MBMBVQ(par)
17+
self.EC = EntropyCoding(par)
18+
def change_n_img(self, n_img):
19+
for i in range(1, self.EC.par['n_hop']+1):
20+
for j in range(len(self.EC.par['shape']['hop'+str(i)])):
21+
self.EC.par['shape']['hop'+str(i)][j][0] = n_img
22+
@Time
23+
def fit(self, Y):
24+
self.change_n_img(Y.shape[0])
25+
self.MBMBVQ.fit(copy.deepcopy(Y))
26+
save = self.MBMBVQ.encode(copy.deepcopy(Y))
27+
self.EC.fit(save)
28+
return self
29+
@Time
30+
def refit(self, Y, par):
31+
self.change_n_img(Y.shape[0])
32+
self.MBMBVQ.refit(copy.deepcopy(Y), par)
33+
save = self.MBMBVQ.encode(copy.deepcopy(Y))
34+
self.EC.refit(save, par)
35+
return self
36+
@Time
37+
def encode(self, Y):
38+
self.change_n_img(Y.shape[0])
39+
save = self.MBMBVQ.encode(Y)
40+
stream = self.EC.encode(save, S=Y.shape[1])
41+
return stream, save['DC'], save
42+
43+
@Time
44+
def decode(self, stream, DC):
45+
save = self.EC.decode(stream)
46+
save['DC'] = DC
47+
iY = self.MBMBVQ.decode(save)
48+
return iY
49+
50+
if __name__ == "__main__":
51+
with open('./test_data/test_par1.json', 'r') as f:
52+
par = json.load(f)
53+
gic = GIC_Y(par)
54+
55+
Y_list = Load_from_Folder(folder='./test_data/', color='YUV', ct=-1)
56+
Y = np.array(Y_list)[:,:,:,:1]
57+
58+
gic.fit(Y)
59+
60+
stream, dc = gic.encode(Y)
61+
62+
iY = gic.decode(stream, dc)
63+
print('MSE=%5.3f, PSNR=%3.5f'%(MSE(Y, iY), PSNR(Y, iY)))
64+
print('------------------')
65+
print(" * Ref result: "+'MSE=129.342, PSNR=27.01340')
66+

Huffman.py

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# @yifan
2+
#
3+
import numpy as np
4+
import huffman
5+
6+
class Huffman():
7+
def __init__(self):
8+
self.hist = None
9+
self.dict = {}
10+
self.inv_dict = {}
11+
self.version = '2021.05.20'
12+
13+
def Hist(self, x, bins=64):
14+
x = x.reshape(-1).astype('int32')
15+
res = np.zeros(bins)
16+
for i in range(bins):
17+
res[i] = len(x[x == i])
18+
return res
19+
20+
def make_dict(self):
21+
tmp = []
22+
for i in range(len(self.hist)):
23+
tmp.append((str(i), self.hist[i]))
24+
self.dict = huffman.codebook(tmp)
25+
self.inv_dict = {v: k for k, v in self.dict.items()}
26+
27+
def fit(self, X):
28+
bins = len(np.unique(X.astype('int16')))
29+
self.hist = self.Hist(X, bins=bins)
30+
self.make_dict()
31+
return self
32+
33+
def encode(self, X):
34+
X = X.reshape(-1).astype('int32')
35+
stream = ''
36+
for i in range(len(X)):
37+
stream += self.dict[str(X[i])]
38+
return stream
39+
40+
def decode(self, stream, start=0, size=-1):
41+
if size < 0:
42+
size = len(stream)
43+
dX, last, ct = [], start, 0
44+
for i in range(start, len(stream)):
45+
if stream[last:i] in self.inv_dict:
46+
dX.append((int)(self.inv_dict[stream[last:i]]))
47+
last = i
48+
ct += 1
49+
if ct >= size:
50+
break
51+
if ct < size:
52+
dX.append((int)(self.inv_dict[stream[last:]]))
53+
last = len(stream)
54+
return np.array(dX), last

LANCZOS.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import numpy as np
2+
from PIL import Image
3+
4+
class LANCZOS:
5+
@staticmethod
6+
def split(X, ratio=2):
7+
DC_L = LANCZOS.resample(X, ratio)
8+
X_inv_L = LANCZOS.resample(DC_L, 1/ratio)
9+
X_inv_L = np.round(X_inv_L)
10+
AC = X - X_inv_L
11+
return DC_L, AC
12+
@staticmethod
13+
def inv_split(DC, AC, ratio=2):
14+
DC = LANCZOS.resample(DC, 1/ratio)
15+
return DC+AC
16+
def inv_split_moreRef(DC, AC, k, i, j, win, ratio=2):
17+
DC = LANCZOS.resample(DC, 1/ratio)
18+
DC = Shrink(DC, win=win)
19+
return DC[k, i, j].reshape(-1)+AC.reshape(-1)
20+
@staticmethod
21+
def resample(X, ratio=2):
22+
image_list = []
23+
for i in range(X.shape[0]):
24+
tmp = []
25+
for k in range(X.shape[-1]):
26+
size1 = int(X.shape[1]/ratio)
27+
size2 = int(X.shape[2]/ratio)
28+
image_tmp = Image.fromarray(X[i,:,:,k]).resize(size=(size1, size2), resample=Image.LANCZOS)
29+
tmp.append(np.array(image_tmp).reshape(1, size1, size2, 1))
30+
image_list.append(np.concatenate(tmp, axis=-1))
31+
output = np.concatenate(image_list, axis=0)
32+
return output

LLSR.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# 2020.01.28
2+
# @yifan
3+
#
4+
import numpy as np
5+
6+
class LLSR():
7+
def __init__(self, onehot=True, normalize=False):
8+
self.onehot = onehot
9+
self.normalize = normalize
10+
self.weight = []
11+
12+
def fit(self, X, Y):
13+
if self.onehot == True:
14+
Y = np.eye(len(np.unique(Y)))[Y.reshape(-1)]
15+
A = np.ones((X.shape[0], 1))
16+
X = np.concatenate((X, A), axis=1)
17+
self.weight, _, _, _ = np.linalg.lstsq(X, Y, rcond=None)
18+
return self
19+
20+
def predict(self, X):
21+
pred = self.predict_proba(X)
22+
return np.argmax(pred, axis=1)
23+
24+
def predict_proba(self, X):
25+
A = np.ones((X.shape[0], 1))
26+
X = np.concatenate((X, A), axis=1)
27+
pred = np.matmul(X, self.weight)
28+
if self.normalize == True:
29+
pred = (pred - np.min(pred, axis=1, keepdims=True))/ np.sum((pred - np.min(pred, axis=1, keepdims=True) + 1e-15), axis=1, keepdims=True)
30+
return pred
31+
32+
def score(self, X, Y):
33+
pred = self.predict(X)
34+
return accuracy_score(Y, pred)

0 commit comments

Comments
 (0)