Loading .ipynb_checkpoints/Encoding_decoding-checkpoint.ipynb +0 −49 Original line number Original line Diff line number Diff line %% Cell type:code id:14f74f21 tags: %% Cell type:code id:14f74f21 tags: ``` python ``` python import numpy as np import numpy as np from matplotlib import pyplot as plt from matplotlib import pyplot as plt from itertools import product from itertools import product import os import os import sys import sys from PIL import Image from PIL import Image from scipy.optimize import minimize,linprog from scipy.optimize import minimize,linprog import time import time import seaborn as sns import seaborn as sns from sklearn.neighbors import KernelDensity from sklearn.neighbors import KernelDensity import pandas as pd import pandas as pd from collections import Counter from collections import Counter import time import time ``` ``` %% Cell type:code id:c16af61f tags: %% Cell type:code id:c16af61f tags: ``` python ``` python def file_extractor(dirname="images"): def file_extractor(dirname="images"): files = os.listdir(dirname) files = os.listdir(dirname) scenes = [] scenes = [] for file in files: for file in files: if file == '.DS_Store': if file == '.DS_Store': continue continue else: else: scenes.append(os.path.join(dirname, file)) scenes.append(os.path.join(dirname, file)) return scenes return scenes def image_extractor(scenes): def image_extractor(scenes): image_folder = [] image_folder = [] for scene in scenes: for scene in scenes: files = os.listdir(scene) files = os.listdir(scene) for file in files: for file in files: #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": continue continue else: else: image_folder.append(os.path.join(scene, file)) image_folder.append(os.path.join(scene, file)) return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor def im_distribution(images, num): def im_distribution(images, num): """ """ Function that extracts tiff files from specific cameras and returns a list of all Function that extracts tiff files from specific cameras and returns a list of all the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise specified camera numbers. specified camera numbers. Parameters: Parameters: images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but of specific tiff files that can be opened right away. This is the list that we iterate through and of specific tiff files that can be opened right away. This is the list that we iterate through and divide. divide. num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits of "_1" for single digits. of "_1" for single digits. Returns: Returns: tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted from the 'images' list that correspond to the given num. from the 'images' list that correspond to the given num. """ """ tiff = [] tiff = [] for im in images: for im in images: if im[-7:-5] == num: if im[-7:-5] == num: tiff.append(im) tiff.append(im) return tiff return tiff ``` ``` %% Cell type:code id:aceba613 tags: %% Cell type:code id:aceba613 tags: ``` python ``` python def predict_pix(tiff_image): def predict_pix(tiff_image): """ """ This function predict the pixel values excluding the boundary. This function predict the pixel values excluding the boundary. Using the 4 neighbor pixel values and MSE to predict the next pixel value Using the 4 neighbor pixel values and MSE to predict the next pixel value (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,0) (0,0) => (0,0) is the one we want to predict (-1,0) (0,0) => (0,0) is the one we want to predict take the derivative of mean square error to solve for the system of equation take the derivative of mean square error to solve for the system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) and the predicted pixel value is c. and the predicted pixel value is c. Input: Input: tiff_image (string): path to the tiff file tiff_image (string): path to the tiff file Return: Return: image (512 X 640): original image image (512 X 640): original image predict (325380,): predicted image exclude the boundary predict (325380,): predicted image exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary error (325380,): difference between the original image and predicted image error (325380,): difference between the original image and predicted image A (3 X 3): system of equation A (3 X 3): system of equation """ """ image = Image.open(tiff_image) #Open the image and read it as an Image object image = Image.open(tiff_image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) image = image.astype(int) print(image.shape) print(image.shape) # use # use A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once # use numpy solver to solve the system of equations all at once #predict = np.floor(np.linalg.solve(A,y)[-1]) #predict = np.floor(np.linalg.solve(A,y)[-1]) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) # flatten the neighbor pixlels and stack them together # flatten the neighbor pixlels and stack them together z0 = np.ravel(z0) z0 = np.ravel(z0) z1 = np.ravel(z1) z1 = np.ravel(z1) z2 = np.ravel(z2) z2 = np.ravel(z2) z3 = np.ravel(z3) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T neighbor = np.vstack((z0,z1,z2,z3)).T # calculate the difference # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # calculate the error # calculate the error error = np.ravel(image[1:-1,1:-1])-predict error = np.ravel(image[1:-1,1:-1])-predict return image, predict, diff, error, A return image, predict, diff, error, A ``` ``` %% Cell type:code id:6b965751 tags: %% Cell type:code id:6b965751 tags: ``` python ``` python """ """ this huffman coding code is found online this huffman coding code is found online https://favtutor.com/blogs/huffman-coding https://favtutor.com/blogs/huffman-coding """ """ class NodeTree(object): class NodeTree(object): def __init__(self, left=None, right=None): def __init__(self, left=None, right=None): self.left = left self.left = left self.right = right self.right = right def children(self): def children(self): return self.left, self.right return self.left, self.right def __str__(self): def __str__(self): return self.left, self.right return self.left, self.right def huffman_code_tree(node, binString=''): def huffman_code_tree(node, binString=''): ''' ''' Function to find Huffman Code Function to find Huffman Code ''' ''' if type(node) is str: if type(node) is str: return {node: binString} return {node: binString} (l, r) = node.children() (l, r) = node.children() d = dict() d = dict() d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(r, binString + '1')) d.update(huffman_code_tree(r, binString + '1')) return d return d def make_tree(nodes): def make_tree(nodes): ''' ''' Function to make tree Function to make tree :param nodes: Nodes :param nodes: Nodes :return: Root of the tree :return: Root of the tree ''' ''' while len(nodes) > 1: while len(nodes) > 1: (key1, c1) = nodes[-1] (key1, c1) = nodes[-1] (key2, c2) = nodes[-2] (key2, c2) = nodes[-2] nodes = nodes[:-2] nodes = nodes[:-2] node = NodeTree(key1, key2) node = NodeTree(key1, key2) nodes.append((node, c1 + c2)) nodes.append((node, c1 + c2)) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) return nodes[0][0] return nodes[0][0] ``` ``` %% Cell type:code id:b7561883 tags: %% Cell type:code id:b7561883 tags: ``` python ``` python def huffman(image, num_bins=4): def huffman(image, num_bins=4): """ """ This function is used to encode the error based on the difference This function is used to encode the error based on the difference and split the difference into different bins and split the difference into different bins Input: Input: image (string): path to the tiff file image (string): path to the tiff file num_bins (int): number of bins num_bins (int): number of bins Return: Return: list_dic (num_bins + 1): a list of dictionary list_dic (num_bins + 1): a list of dictionary image (512, 640): original image image (512, 640): original image new_error (512, 640): error that includes the boundary new_error (512, 640): error that includes the boundary diff (510, 638): difference of min and max of the 4 neighbors diff (510, 638): difference of min and max of the 4 neighbors boundary (2300,): the boundary values after subtracting the very first pixel value boundary (2300,): the boundary values after subtracting the very first pixel value predict (325380,): the list of predicted values predict (325380,): the list of predicted values bins (num_bins - 1,): a list of threshold to cut the bins bins (num_bins - 1,): a list of threshold to cut the bins A (3 X 3): system of equation A (3 X 3): system of equation """ """ # get the prediction error and difference # get the prediction error and difference image, predict, diff, error, A = predict_pix(image) image, predict, diff, error, A = predict_pix(image) # get the number of points in each bins # get the number of points in each bins data_points_per_bin = len(diff) // num_bins data_points_per_bin = len(diff) // num_bins # sort the difference and create the bins # sort the difference and create the bins sorted_diff = diff.copy() sorted_diff = diff.copy() sorted_diff.sort() sorted_diff.sort() bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] # get the boundary # get the boundary boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) # take the difference of the boundary with the very first pixel # take the difference of the boundary with the very first pixel boundary = boundary - image[0,0] boundary = boundary - image[0,0] boundary[0] = image[0,0] boundary[0] = image[0,0] # huffman encode the boundary # huffman encode the boundary string = [str(i) for i in boundary] string = [str(i) for i in boundary] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) # create a list of huffman table # create a list of huffman table list_dic = [encode] list_dic = [encode] n = len(bins) n = len(bins) # loop through different bins # loop through different bins for i in range (0,n): for i in range (0,n): # the fisrt bin # the fisrt bin if i == 0 : if i == 0 : # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff <= bins[i] mask = diff <= bins[i] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the middle bins # the middle bins else: else: # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[i-1] mask = diff > bins[i-1] new_error = error[mask] new_error = error[mask] mask2 = diff[mask] <= bins[i] mask2 = diff[mask] <= bins[i] string = [str(i) for i in new_error[mask2].astype(int)] string = [str(i) for i in new_error[mask2].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the last bin # the last bin # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[-1] mask = diff > bins[-1] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # create a error matrix that includes the boundary (used in encoding matrix) # create a error matrix that includes the boundary (used in encoding matrix) new_error = np.copy(image) new_error = np.copy(image) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) keep = new_error[0,0] keep = new_error[0,0] new_error[0,:] = new_error[0,:] - keep new_error[0,:] = new_error[0,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[0,0] = keep new_error[0,0] = keep diff = np.reshape(diff,(510,638)) diff = np.reshape(diff,(510,638)) # return the huffman dictionary # return the huffman dictionary return list_dic, image, new_error, diff, boundary, predict, bins, A return list_dic, image, new_error, diff, boundary, predict, bins, A ``` ``` %% Cell type:code id:2eb774d2 tags: %% Cell type:code id:2eb774d2 tags: ``` python ``` python def encoder(error, list_dic, diff, bound, bins): def encoder(error, list_dic, diff, bound, bins): """ """ This function This function """ """ # copy the error matrix (including the boundary) # copy the error matrix (including the boundary) encoded = np.copy(error).astype(int).astype(str).astype(object) encoded = np.copy(error).astype(int).astype(str).astype(object) #diff = np.reshape(diff,(510,638)) #diff = np.reshape(diff,(510,638)) # loop through all the pixel to encode # loop through all the pixel to encode for i in range(encoded.shape[0]): for i in range(encoded.shape[0]): for j in range(encoded.shape[1]): for j in range(encoded.shape[1]): if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: encoded[i][j] = list_dic[0][encoded[i][j]] encoded[i][j] = list_dic[0][encoded[i][j]] elif diff[i-1][j-1] <= bins[0]: elif diff[i-1][j-1] <= bins[0]: encoded[i][j] = list_dic[1][encoded[i][j]] encoded[i][j] = list_dic[1][encoded[i][j]] elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: encoded[i][j] = list_dic[2][encoded[i][j]] encoded[i][j] = list_dic[2][encoded[i][j]] elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: encoded[i][j] = list_dic[3][encoded[i][j]] encoded[i][j] = list_dic[3][encoded[i][j]] else: else: encoded[i][j] = list_dic[4][encoded[i][j]] encoded[i][j] = list_dic[4][encoded[i][j]] return encoded return encoded ``` ``` %% Cell type:code id:8eeb40d0 tags: %% Cell type:code id:8eeb40d0 tags: ``` python ``` python def decoder(A, encoded_matrix, list_dic, bins): def decoder(A, encoded_matrix, list_dic, bins): """ """ Function that accecpts the prediction matrix A for the linear system, Function that accecpts the prediction matrix A for the linear system, the encoded matrix of error values, and the encoding dicitonary. the encoded matrix of error values, and the encoding dicitonary. """ """ # change the dictionary back to list # change the dictionary back to list # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins the_keys0 = list(list_dic[0].keys()) the_keys0 = list(list_dic[0].keys()) the_values0 = list(list_dic[0].values()) the_values0 = list(list_dic[0].values()) the_keys1 = list(list_dic[1].keys()) the_keys1 = list(list_dic[1].keys()) the_values1 = list(list_dic[1].values()) the_values1 = list(list_dic[1].values()) the_keys2 = list(list_dic[2].keys()) the_keys2 = list(list_dic[2].keys()) the_values2 = list(list_dic[2].values()) the_values2 = list(list_dic[2].values()) the_keys3 = list(list_dic[3].keys()) the_keys3 = list(list_dic[3].keys()) the_values3 = list(list_dic[3].values()) the_values3 = list(list_dic[3].values()) the_keys4 = list(list_dic[4].keys()) the_keys4 = list(list_dic[4].keys()) the_values4 = list(list_dic[4].values()) the_values4 = list(list_dic[4].values()) error_matrix = np.zeros((512,640)) error_matrix = np.zeros((512,640)) # loop through all the element in the matrix # loop through all the element in the matrix for i in range(error_matrix.shape[0]): for i in range(error_matrix.shape[0]): for j in range(error_matrix.shape[1]): for j in range(error_matrix.shape[1]): # if it's the very first pixel on the image # if it's the very first pixel on the image if i == 0 and j == 0: if i == 0 and j == 0: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) # if it's on the boundary # if it's on the boundary elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] # if not the boundary # if not the boundary else: else: # predict the image with the known pixel value # predict the image with the known pixel value z0 = error_matrix[i-1][j-1] z0 = error_matrix[i-1][j-1] z1 = error_matrix[i-1][j] z1 = error_matrix[i-1][j] z2 = error_matrix[i-1][j+1] z2 = error_matrix[i-1][j+1] z3 = error_matrix[i][j-1] z3 = error_matrix[i][j-1] y0 = int(-z0+z2-z3) y0 = int(-z0+z2-z3) y1 = int(z0+z1+z2) y1 = int(z0+z1+z2) y2 = int(-z0-z1-z2-z3) y2 = int(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) # add on the difference by searching the dictionary # add on the difference by searching the dictionary # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if difference <= bins[0]: if difference <= bins[0]: error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[1] and difference > bins[0]: elif difference <= bins[1] and difference > bins[0]: error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[2] and difference > bins[1]: elif difference <= bins[2] and difference > bins[1]: error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) else: else: error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) return error_matrix.astype(int) return error_matrix.astype(int) ``` ``` %% Cell type:code id:f959fe93 tags: %% Cell type:code id:f959fe93 tags: ``` python ``` python def compress_rate(image, error, diff, bound, list_dic, bins): def compress_rate(image, error, diff, bound, list_dic, bins): # the bits for the original image # the bits for the original image o_len = 0 o_len = 0 # the bits for the compressed image # the bits for the compressed image c_len = 0 c_len = 0 # initializing the varible # initializing the varible im = np.reshape(image,(512, 640)) im = np.reshape(image,(512, 640)) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) original = im[1:-1,1:-1].reshape(-1) original = im[1:-1,1:-1].reshape(-1) diff = diff.reshape(-1) diff = diff.reshape(-1) # calculate the bit for boundary # calculate the bit for boundary for i in range(0,len(bound)): for i in range(0,len(bound)): o_len += len(bin(real_b[i])[2:]) o_len += len(bin(real_b[i])[2:]) c_len += len(list_dic[0][str(bound[i])]) c_len += len(list_dic[0][str(bound[i])]) # calculate the bit for the pixels inside the boundary # calculate the bit for the pixels inside the boundary for i in range(0,len(original)): for i in range(0,len(original)): # for the original image # for the original image o_len += len(bin(original[i])[2:]) o_len += len(bin(original[i])[2:]) # check the difference and find the coresponding huffman table # check the difference and find the coresponding huffman table # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if diff[i] <= bins[0]: if diff[i] <= bins[0]: c_len += len(list_dic[1][str(int(error[i]))]) c_len += len(list_dic[1][str(int(error[i]))]) elif diff[i] <= bins[1] and diff[i] > bins[0]: elif diff[i] <= bins[1] and diff[i] > bins[0]: c_len += len(list_dic[2][str(int(error[i]))]) c_len += len(list_dic[2][str(int(error[i]))]) elif diff[i] <= bins[2] and diff[i] > bins[1]: elif diff[i] <= bins[2] and diff[i] > bins[1]: c_len += len(list_dic[3][str(int(error[i]))]) c_len += len(list_dic[3][str(int(error[i]))]) else: else: c_len += len(list_dic[5][str(int(error[i]))]) c_len += len(list_dic[5][str(int(error[i]))]) return c_len/o_len return c_len/o_len ``` ``` %% Cell type:code id:3e0e9742 tags: %% Cell type:code id:3e0e9742 tags: ``` python ``` python scenes = file_extractor() scenes = file_extractor() images = image_extractor(scenes) images = image_extractor(scenes) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) print(np.allclose(image, reconstruct_image)) print(np.allclose(image, reconstruct_image)) print(len(list_dic)) print(len(list_dic)) ``` ``` %% Output %% Output (512, 640) (512, 640) True True 5 5 %% Cell type:code id:004e8ba8 tags: %% Cell type:code id:004e8ba8 tags: ``` python ``` python print(bins) print(bins) ``` ``` %% Output %% Output [26, 40, 62] [26, 40, 62] %% Cell type:code id:a282f9e6 tags: %% Cell type:code id:a282f9e6 tags: ``` python ``` python def predict_pix_lstsq(tiff_list): """ Predict the next pixel using a fit hyperplane of the four closest pixels. The gradient measure in this function is the summed distance to the fitted hyperplane of each of the four points, aka the residual from the least squares function. The previous predict_pix function uses the difference between the minimal and maximal pixels of the surrounding four. """ image = tiff_list image = Image.open(image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) #round the solution to the nearest integer so that encoding/decoding is easier points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]]) #Matrix system of points that will be used to solve the least squares fitting hyperplane # flatten the neighbor pixels and stack them together z0 = np.ravel(z0) z1 = np.ravel(z1) z2 = np.ravel(z2) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T f, res, rank, s = la.lstsq(points, neighbor.T, rcond=None) # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # flatten the image to a vector image = np.ravel(image[1:-1,1:-1]) error = image-predict return image, predict, res, error, A, diff ``` ``` Encoding_decoding.ipynb +0 −49 Original line number Original line Diff line number Diff line %% Cell type:code id:14f74f21 tags: %% Cell type:code id:14f74f21 tags: ``` python ``` python import numpy as np import numpy as np from matplotlib import pyplot as plt from matplotlib import pyplot as plt from itertools import product from itertools import product import os import os import sys import sys from PIL import Image from PIL import Image from scipy.optimize import minimize,linprog from scipy.optimize import minimize,linprog import time import time import seaborn as sns import seaborn as sns from sklearn.neighbors import KernelDensity from sklearn.neighbors import KernelDensity import pandas as pd import pandas as pd from collections import Counter from collections import Counter import time import time ``` ``` %% Cell type:code id:c16af61f tags: %% Cell type:code id:c16af61f tags: ``` python ``` python def file_extractor(dirname="images"): def file_extractor(dirname="images"): files = os.listdir(dirname) files = os.listdir(dirname) scenes = [] scenes = [] for file in files: for file in files: if file == '.DS_Store': if file == '.DS_Store': continue continue else: else: scenes.append(os.path.join(dirname, file)) scenes.append(os.path.join(dirname, file)) return scenes return scenes def image_extractor(scenes): def image_extractor(scenes): image_folder = [] image_folder = [] for scene in scenes: for scene in scenes: files = os.listdir(scene) files = os.listdir(scene) for file in files: for file in files: #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": continue continue else: else: image_folder.append(os.path.join(scene, file)) image_folder.append(os.path.join(scene, file)) return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor def im_distribution(images, num): def im_distribution(images, num): """ """ Function that extracts tiff files from specific cameras and returns a list of all Function that extracts tiff files from specific cameras and returns a list of all the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise specified camera numbers. specified camera numbers. Parameters: Parameters: images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but of specific tiff files that can be opened right away. This is the list that we iterate through and of specific tiff files that can be opened right away. This is the list that we iterate through and divide. divide. num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits of "_1" for single digits. of "_1" for single digits. Returns: Returns: tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted from the 'images' list that correspond to the given num. from the 'images' list that correspond to the given num. """ """ tiff = [] tiff = [] for im in images: for im in images: if im[-7:-5] == num: if im[-7:-5] == num: tiff.append(im) tiff.append(im) return tiff return tiff ``` ``` %% Cell type:code id:aceba613 tags: %% Cell type:code id:aceba613 tags: ``` python ``` python def predict_pix(tiff_image): def predict_pix(tiff_image): """ """ This function predict the pixel values excluding the boundary. This function predict the pixel values excluding the boundary. Using the 4 neighbor pixel values and MSE to predict the next pixel value Using the 4 neighbor pixel values and MSE to predict the next pixel value (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,0) (0,0) => (0,0) is the one we want to predict (-1,0) (0,0) => (0,0) is the one we want to predict take the derivative of mean square error to solve for the system of equation take the derivative of mean square error to solve for the system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) and the predicted pixel value is c. and the predicted pixel value is c. Input: Input: tiff_image (string): path to the tiff file tiff_image (string): path to the tiff file Return: Return: image (512 X 640): original image image (512 X 640): original image predict (325380,): predicted image exclude the boundary predict (325380,): predicted image exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary error (325380,): difference between the original image and predicted image error (325380,): difference between the original image and predicted image A (3 X 3): system of equation A (3 X 3): system of equation """ """ image = Image.open(tiff_image) #Open the image and read it as an Image object image = Image.open(tiff_image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) image = image.astype(int) print(image.shape) print(image.shape) # use # use A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once # use numpy solver to solve the system of equations all at once #predict = np.floor(np.linalg.solve(A,y)[-1]) #predict = np.floor(np.linalg.solve(A,y)[-1]) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) # flatten the neighbor pixlels and stack them together # flatten the neighbor pixlels and stack them together z0 = np.ravel(z0) z0 = np.ravel(z0) z1 = np.ravel(z1) z1 = np.ravel(z1) z2 = np.ravel(z2) z2 = np.ravel(z2) z3 = np.ravel(z3) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T neighbor = np.vstack((z0,z1,z2,z3)).T # calculate the difference # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # calculate the error # calculate the error error = np.ravel(image[1:-1,1:-1])-predict error = np.ravel(image[1:-1,1:-1])-predict return image, predict, diff, error, A return image, predict, diff, error, A ``` ``` %% Cell type:code id:6b965751 tags: %% Cell type:code id:6b965751 tags: ``` python ``` python """ """ this huffman coding code is found online this huffman coding code is found online https://favtutor.com/blogs/huffman-coding https://favtutor.com/blogs/huffman-coding """ """ class NodeTree(object): class NodeTree(object): def __init__(self, left=None, right=None): def __init__(self, left=None, right=None): self.left = left self.left = left self.right = right self.right = right def children(self): def children(self): return self.left, self.right return self.left, self.right def __str__(self): def __str__(self): return self.left, self.right return self.left, self.right def huffman_code_tree(node, binString=''): def huffman_code_tree(node, binString=''): ''' ''' Function to find Huffman Code Function to find Huffman Code ''' ''' if type(node) is str: if type(node) is str: return {node: binString} return {node: binString} (l, r) = node.children() (l, r) = node.children() d = dict() d = dict() d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(r, binString + '1')) d.update(huffman_code_tree(r, binString + '1')) return d return d def make_tree(nodes): def make_tree(nodes): ''' ''' Function to make tree Function to make tree :param nodes: Nodes :param nodes: Nodes :return: Root of the tree :return: Root of the tree ''' ''' while len(nodes) > 1: while len(nodes) > 1: (key1, c1) = nodes[-1] (key1, c1) = nodes[-1] (key2, c2) = nodes[-2] (key2, c2) = nodes[-2] nodes = nodes[:-2] nodes = nodes[:-2] node = NodeTree(key1, key2) node = NodeTree(key1, key2) nodes.append((node, c1 + c2)) nodes.append((node, c1 + c2)) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) return nodes[0][0] return nodes[0][0] ``` ``` %% Cell type:code id:b7561883 tags: %% Cell type:code id:b7561883 tags: ``` python ``` python def huffman(image, num_bins=4): def huffman(image, num_bins=4): """ """ This function is used to encode the error based on the difference This function is used to encode the error based on the difference and split the difference into different bins and split the difference into different bins Input: Input: image (string): path to the tiff file image (string): path to the tiff file num_bins (int): number of bins num_bins (int): number of bins Return: Return: list_dic (num_bins + 1): a list of dictionary list_dic (num_bins + 1): a list of dictionary image (512, 640): original image image (512, 640): original image new_error (512, 640): error that includes the boundary new_error (512, 640): error that includes the boundary diff (510, 638): difference of min and max of the 4 neighbors diff (510, 638): difference of min and max of the 4 neighbors boundary (2300,): the boundary values after subtracting the very first pixel value boundary (2300,): the boundary values after subtracting the very first pixel value predict (325380,): the list of predicted values predict (325380,): the list of predicted values bins (num_bins - 1,): a list of threshold to cut the bins bins (num_bins - 1,): a list of threshold to cut the bins A (3 X 3): system of equation A (3 X 3): system of equation """ """ # get the prediction error and difference # get the prediction error and difference image, predict, diff, error, A = predict_pix(image) image, predict, diff, error, A = predict_pix(image) # get the number of points in each bins # get the number of points in each bins data_points_per_bin = len(diff) // num_bins data_points_per_bin = len(diff) // num_bins # sort the difference and create the bins # sort the difference and create the bins sorted_diff = diff.copy() sorted_diff = diff.copy() sorted_diff.sort() sorted_diff.sort() bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] # get the boundary # get the boundary boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) # take the difference of the boundary with the very first pixel # take the difference of the boundary with the very first pixel boundary = boundary - image[0,0] boundary = boundary - image[0,0] boundary[0] = image[0,0] boundary[0] = image[0,0] # huffman encode the boundary # huffman encode the boundary string = [str(i) for i in boundary] string = [str(i) for i in boundary] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) # create a list of huffman table # create a list of huffman table list_dic = [encode] list_dic = [encode] n = len(bins) n = len(bins) # loop through different bins # loop through different bins for i in range (0,n): for i in range (0,n): # the fisrt bin # the fisrt bin if i == 0 : if i == 0 : # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff <= bins[i] mask = diff <= bins[i] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the middle bins # the middle bins else: else: # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[i-1] mask = diff > bins[i-1] new_error = error[mask] new_error = error[mask] mask2 = diff[mask] <= bins[i] mask2 = diff[mask] <= bins[i] string = [str(i) for i in new_error[mask2].astype(int)] string = [str(i) for i in new_error[mask2].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the last bin # the last bin # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[-1] mask = diff > bins[-1] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # create a error matrix that includes the boundary (used in encoding matrix) # create a error matrix that includes the boundary (used in encoding matrix) new_error = np.copy(image) new_error = np.copy(image) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) keep = new_error[0,0] keep = new_error[0,0] new_error[0,:] = new_error[0,:] - keep new_error[0,:] = new_error[0,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[0,0] = keep new_error[0,0] = keep diff = np.reshape(diff,(510,638)) diff = np.reshape(diff,(510,638)) # return the huffman dictionary # return the huffman dictionary return list_dic, image, new_error, diff, boundary, predict, bins, A return list_dic, image, new_error, diff, boundary, predict, bins, A ``` ``` %% Cell type:code id:2eb774d2 tags: %% Cell type:code id:2eb774d2 tags: ``` python ``` python def encoder(error, list_dic, diff, bound, bins): def encoder(error, list_dic, diff, bound, bins): """ """ This function This function """ """ # copy the error matrix (including the boundary) # copy the error matrix (including the boundary) encoded = np.copy(error).astype(int).astype(str).astype(object) encoded = np.copy(error).astype(int).astype(str).astype(object) #diff = np.reshape(diff,(510,638)) #diff = np.reshape(diff,(510,638)) # loop through all the pixel to encode # loop through all the pixel to encode for i in range(encoded.shape[0]): for i in range(encoded.shape[0]): for j in range(encoded.shape[1]): for j in range(encoded.shape[1]): if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: encoded[i][j] = list_dic[0][encoded[i][j]] encoded[i][j] = list_dic[0][encoded[i][j]] elif diff[i-1][j-1] <= bins[0]: elif diff[i-1][j-1] <= bins[0]: encoded[i][j] = list_dic[1][encoded[i][j]] encoded[i][j] = list_dic[1][encoded[i][j]] elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: encoded[i][j] = list_dic[2][encoded[i][j]] encoded[i][j] = list_dic[2][encoded[i][j]] elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: encoded[i][j] = list_dic[3][encoded[i][j]] encoded[i][j] = list_dic[3][encoded[i][j]] else: else: encoded[i][j] = list_dic[4][encoded[i][j]] encoded[i][j] = list_dic[4][encoded[i][j]] return encoded return encoded ``` ``` %% Cell type:code id:8eeb40d0 tags: %% Cell type:code id:8eeb40d0 tags: ``` python ``` python def decoder(A, encoded_matrix, list_dic, bins): def decoder(A, encoded_matrix, list_dic, bins): """ """ Function that accecpts the prediction matrix A for the linear system, Function that accecpts the prediction matrix A for the linear system, the encoded matrix of error values, and the encoding dicitonary. the encoded matrix of error values, and the encoding dicitonary. """ """ # change the dictionary back to list # change the dictionary back to list # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins the_keys0 = list(list_dic[0].keys()) the_keys0 = list(list_dic[0].keys()) the_values0 = list(list_dic[0].values()) the_values0 = list(list_dic[0].values()) the_keys1 = list(list_dic[1].keys()) the_keys1 = list(list_dic[1].keys()) the_values1 = list(list_dic[1].values()) the_values1 = list(list_dic[1].values()) the_keys2 = list(list_dic[2].keys()) the_keys2 = list(list_dic[2].keys()) the_values2 = list(list_dic[2].values()) the_values2 = list(list_dic[2].values()) the_keys3 = list(list_dic[3].keys()) the_keys3 = list(list_dic[3].keys()) the_values3 = list(list_dic[3].values()) the_values3 = list(list_dic[3].values()) the_keys4 = list(list_dic[4].keys()) the_keys4 = list(list_dic[4].keys()) the_values4 = list(list_dic[4].values()) the_values4 = list(list_dic[4].values()) error_matrix = np.zeros((512,640)) error_matrix = np.zeros((512,640)) # loop through all the element in the matrix # loop through all the element in the matrix for i in range(error_matrix.shape[0]): for i in range(error_matrix.shape[0]): for j in range(error_matrix.shape[1]): for j in range(error_matrix.shape[1]): # if it's the very first pixel on the image # if it's the very first pixel on the image if i == 0 and j == 0: if i == 0 and j == 0: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) # if it's on the boundary # if it's on the boundary elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] # if not the boundary # if not the boundary else: else: # predict the image with the known pixel value # predict the image with the known pixel value z0 = error_matrix[i-1][j-1] z0 = error_matrix[i-1][j-1] z1 = error_matrix[i-1][j] z1 = error_matrix[i-1][j] z2 = error_matrix[i-1][j+1] z2 = error_matrix[i-1][j+1] z3 = error_matrix[i][j-1] z3 = error_matrix[i][j-1] y0 = int(-z0+z2-z3) y0 = int(-z0+z2-z3) y1 = int(z0+z1+z2) y1 = int(z0+z1+z2) y2 = int(-z0-z1-z2-z3) y2 = int(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) # add on the difference by searching the dictionary # add on the difference by searching the dictionary # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if difference <= bins[0]: if difference <= bins[0]: error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[1] and difference > bins[0]: elif difference <= bins[1] and difference > bins[0]: error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[2] and difference > bins[1]: elif difference <= bins[2] and difference > bins[1]: error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) else: else: error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) return error_matrix.astype(int) return error_matrix.astype(int) ``` ``` %% Cell type:code id:f959fe93 tags: %% Cell type:code id:f959fe93 tags: ``` python ``` python def compress_rate(image, error, diff, bound, list_dic, bins): def compress_rate(image, error, diff, bound, list_dic, bins): # the bits for the original image # the bits for the original image o_len = 0 o_len = 0 # the bits for the compressed image # the bits for the compressed image c_len = 0 c_len = 0 # initializing the varible # initializing the varible im = np.reshape(image,(512, 640)) im = np.reshape(image,(512, 640)) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) original = im[1:-1,1:-1].reshape(-1) original = im[1:-1,1:-1].reshape(-1) diff = diff.reshape(-1) diff = diff.reshape(-1) # calculate the bit for boundary # calculate the bit for boundary for i in range(0,len(bound)): for i in range(0,len(bound)): o_len += len(bin(real_b[i])[2:]) o_len += len(bin(real_b[i])[2:]) c_len += len(list_dic[0][str(bound[i])]) c_len += len(list_dic[0][str(bound[i])]) # calculate the bit for the pixels inside the boundary # calculate the bit for the pixels inside the boundary for i in range(0,len(original)): for i in range(0,len(original)): # for the original image # for the original image o_len += len(bin(original[i])[2:]) o_len += len(bin(original[i])[2:]) # check the difference and find the coresponding huffman table # check the difference and find the coresponding huffman table # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if diff[i] <= bins[0]: if diff[i] <= bins[0]: c_len += len(list_dic[1][str(int(error[i]))]) c_len += len(list_dic[1][str(int(error[i]))]) elif diff[i] <= bins[1] and diff[i] > bins[0]: elif diff[i] <= bins[1] and diff[i] > bins[0]: c_len += len(list_dic[2][str(int(error[i]))]) c_len += len(list_dic[2][str(int(error[i]))]) elif diff[i] <= bins[2] and diff[i] > bins[1]: elif diff[i] <= bins[2] and diff[i] > bins[1]: c_len += len(list_dic[3][str(int(error[i]))]) c_len += len(list_dic[3][str(int(error[i]))]) else: else: c_len += len(list_dic[5][str(int(error[i]))]) c_len += len(list_dic[5][str(int(error[i]))]) return c_len/o_len return c_len/o_len ``` ``` %% Cell type:code id:3e0e9742 tags: %% Cell type:code id:3e0e9742 tags: ``` python ``` python scenes = file_extractor() scenes = file_extractor() images = image_extractor(scenes) images = image_extractor(scenes) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) print(np.allclose(image, reconstruct_image)) print(np.allclose(image, reconstruct_image)) print(len(list_dic)) print(len(list_dic)) ``` ``` %% Output %% Output (512, 640) (512, 640) True True 5 5 %% Cell type:code id:004e8ba8 tags: %% Cell type:code id:004e8ba8 tags: ``` python ``` python print(bins) print(bins) ``` ``` %% Output %% Output [26, 40, 62] [26, 40, 62] %% Cell type:code id:a282f9e6 tags: %% Cell type:code id:a282f9e6 tags: ``` python ``` python def predict_pix_lstsq(tiff_list): """ Predict the next pixel using a fit hyperplane of the four closest pixels. The gradient measure in this function is the summed distance to the fitted hyperplane of each of the four points, aka the residual from the least squares function. The previous predict_pix function uses the difference between the minimal and maximal pixels of the surrounding four. """ image = tiff_list image = Image.open(image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) #round the solution to the nearest integer so that encoding/decoding is easier points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]]) #Matrix system of points that will be used to solve the least squares fitting hyperplane # flatten the neighbor pixels and stack them together z0 = np.ravel(z0) z1 = np.ravel(z1) z2 = np.ravel(z2) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T f, res, rank, s = la.lstsq(points, neighbor.T, rcond=None) # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # flatten the image to a vector image = np.ravel(image[1:-1,1:-1]) error = image-predict return image, predict, res, error, A, diff ``` ``` Loading
.ipynb_checkpoints/Encoding_decoding-checkpoint.ipynb +0 −49 Original line number Original line Diff line number Diff line %% Cell type:code id:14f74f21 tags: %% Cell type:code id:14f74f21 tags: ``` python ``` python import numpy as np import numpy as np from matplotlib import pyplot as plt from matplotlib import pyplot as plt from itertools import product from itertools import product import os import os import sys import sys from PIL import Image from PIL import Image from scipy.optimize import minimize,linprog from scipy.optimize import minimize,linprog import time import time import seaborn as sns import seaborn as sns from sklearn.neighbors import KernelDensity from sklearn.neighbors import KernelDensity import pandas as pd import pandas as pd from collections import Counter from collections import Counter import time import time ``` ``` %% Cell type:code id:c16af61f tags: %% Cell type:code id:c16af61f tags: ``` python ``` python def file_extractor(dirname="images"): def file_extractor(dirname="images"): files = os.listdir(dirname) files = os.listdir(dirname) scenes = [] scenes = [] for file in files: for file in files: if file == '.DS_Store': if file == '.DS_Store': continue continue else: else: scenes.append(os.path.join(dirname, file)) scenes.append(os.path.join(dirname, file)) return scenes return scenes def image_extractor(scenes): def image_extractor(scenes): image_folder = [] image_folder = [] for scene in scenes: for scene in scenes: files = os.listdir(scene) files = os.listdir(scene) for file in files: for file in files: #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": continue continue else: else: image_folder.append(os.path.join(scene, file)) image_folder.append(os.path.join(scene, file)) return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor def im_distribution(images, num): def im_distribution(images, num): """ """ Function that extracts tiff files from specific cameras and returns a list of all Function that extracts tiff files from specific cameras and returns a list of all the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise specified camera numbers. specified camera numbers. Parameters: Parameters: images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but of specific tiff files that can be opened right away. This is the list that we iterate through and of specific tiff files that can be opened right away. This is the list that we iterate through and divide. divide. num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits of "_1" for single digits. of "_1" for single digits. Returns: Returns: tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted from the 'images' list that correspond to the given num. from the 'images' list that correspond to the given num. """ """ tiff = [] tiff = [] for im in images: for im in images: if im[-7:-5] == num: if im[-7:-5] == num: tiff.append(im) tiff.append(im) return tiff return tiff ``` ``` %% Cell type:code id:aceba613 tags: %% Cell type:code id:aceba613 tags: ``` python ``` python def predict_pix(tiff_image): def predict_pix(tiff_image): """ """ This function predict the pixel values excluding the boundary. This function predict the pixel values excluding the boundary. Using the 4 neighbor pixel values and MSE to predict the next pixel value Using the 4 neighbor pixel values and MSE to predict the next pixel value (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,0) (0,0) => (0,0) is the one we want to predict (-1,0) (0,0) => (0,0) is the one we want to predict take the derivative of mean square error to solve for the system of equation take the derivative of mean square error to solve for the system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) and the predicted pixel value is c. and the predicted pixel value is c. Input: Input: tiff_image (string): path to the tiff file tiff_image (string): path to the tiff file Return: Return: image (512 X 640): original image image (512 X 640): original image predict (325380,): predicted image exclude the boundary predict (325380,): predicted image exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary error (325380,): difference between the original image and predicted image error (325380,): difference between the original image and predicted image A (3 X 3): system of equation A (3 X 3): system of equation """ """ image = Image.open(tiff_image) #Open the image and read it as an Image object image = Image.open(tiff_image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) image = image.astype(int) print(image.shape) print(image.shape) # use # use A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once # use numpy solver to solve the system of equations all at once #predict = np.floor(np.linalg.solve(A,y)[-1]) #predict = np.floor(np.linalg.solve(A,y)[-1]) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) # flatten the neighbor pixlels and stack them together # flatten the neighbor pixlels and stack them together z0 = np.ravel(z0) z0 = np.ravel(z0) z1 = np.ravel(z1) z1 = np.ravel(z1) z2 = np.ravel(z2) z2 = np.ravel(z2) z3 = np.ravel(z3) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T neighbor = np.vstack((z0,z1,z2,z3)).T # calculate the difference # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # calculate the error # calculate the error error = np.ravel(image[1:-1,1:-1])-predict error = np.ravel(image[1:-1,1:-1])-predict return image, predict, diff, error, A return image, predict, diff, error, A ``` ``` %% Cell type:code id:6b965751 tags: %% Cell type:code id:6b965751 tags: ``` python ``` python """ """ this huffman coding code is found online this huffman coding code is found online https://favtutor.com/blogs/huffman-coding https://favtutor.com/blogs/huffman-coding """ """ class NodeTree(object): class NodeTree(object): def __init__(self, left=None, right=None): def __init__(self, left=None, right=None): self.left = left self.left = left self.right = right self.right = right def children(self): def children(self): return self.left, self.right return self.left, self.right def __str__(self): def __str__(self): return self.left, self.right return self.left, self.right def huffman_code_tree(node, binString=''): def huffman_code_tree(node, binString=''): ''' ''' Function to find Huffman Code Function to find Huffman Code ''' ''' if type(node) is str: if type(node) is str: return {node: binString} return {node: binString} (l, r) = node.children() (l, r) = node.children() d = dict() d = dict() d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(r, binString + '1')) d.update(huffman_code_tree(r, binString + '1')) return d return d def make_tree(nodes): def make_tree(nodes): ''' ''' Function to make tree Function to make tree :param nodes: Nodes :param nodes: Nodes :return: Root of the tree :return: Root of the tree ''' ''' while len(nodes) > 1: while len(nodes) > 1: (key1, c1) = nodes[-1] (key1, c1) = nodes[-1] (key2, c2) = nodes[-2] (key2, c2) = nodes[-2] nodes = nodes[:-2] nodes = nodes[:-2] node = NodeTree(key1, key2) node = NodeTree(key1, key2) nodes.append((node, c1 + c2)) nodes.append((node, c1 + c2)) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) return nodes[0][0] return nodes[0][0] ``` ``` %% Cell type:code id:b7561883 tags: %% Cell type:code id:b7561883 tags: ``` python ``` python def huffman(image, num_bins=4): def huffman(image, num_bins=4): """ """ This function is used to encode the error based on the difference This function is used to encode the error based on the difference and split the difference into different bins and split the difference into different bins Input: Input: image (string): path to the tiff file image (string): path to the tiff file num_bins (int): number of bins num_bins (int): number of bins Return: Return: list_dic (num_bins + 1): a list of dictionary list_dic (num_bins + 1): a list of dictionary image (512, 640): original image image (512, 640): original image new_error (512, 640): error that includes the boundary new_error (512, 640): error that includes the boundary diff (510, 638): difference of min and max of the 4 neighbors diff (510, 638): difference of min and max of the 4 neighbors boundary (2300,): the boundary values after subtracting the very first pixel value boundary (2300,): the boundary values after subtracting the very first pixel value predict (325380,): the list of predicted values predict (325380,): the list of predicted values bins (num_bins - 1,): a list of threshold to cut the bins bins (num_bins - 1,): a list of threshold to cut the bins A (3 X 3): system of equation A (3 X 3): system of equation """ """ # get the prediction error and difference # get the prediction error and difference image, predict, diff, error, A = predict_pix(image) image, predict, diff, error, A = predict_pix(image) # get the number of points in each bins # get the number of points in each bins data_points_per_bin = len(diff) // num_bins data_points_per_bin = len(diff) // num_bins # sort the difference and create the bins # sort the difference and create the bins sorted_diff = diff.copy() sorted_diff = diff.copy() sorted_diff.sort() sorted_diff.sort() bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] # get the boundary # get the boundary boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) # take the difference of the boundary with the very first pixel # take the difference of the boundary with the very first pixel boundary = boundary - image[0,0] boundary = boundary - image[0,0] boundary[0] = image[0,0] boundary[0] = image[0,0] # huffman encode the boundary # huffman encode the boundary string = [str(i) for i in boundary] string = [str(i) for i in boundary] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) # create a list of huffman table # create a list of huffman table list_dic = [encode] list_dic = [encode] n = len(bins) n = len(bins) # loop through different bins # loop through different bins for i in range (0,n): for i in range (0,n): # the fisrt bin # the fisrt bin if i == 0 : if i == 0 : # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff <= bins[i] mask = diff <= bins[i] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the middle bins # the middle bins else: else: # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[i-1] mask = diff > bins[i-1] new_error = error[mask] new_error = error[mask] mask2 = diff[mask] <= bins[i] mask2 = diff[mask] <= bins[i] string = [str(i) for i in new_error[mask2].astype(int)] string = [str(i) for i in new_error[mask2].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the last bin # the last bin # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[-1] mask = diff > bins[-1] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # create a error matrix that includes the boundary (used in encoding matrix) # create a error matrix that includes the boundary (used in encoding matrix) new_error = np.copy(image) new_error = np.copy(image) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) keep = new_error[0,0] keep = new_error[0,0] new_error[0,:] = new_error[0,:] - keep new_error[0,:] = new_error[0,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[0,0] = keep new_error[0,0] = keep diff = np.reshape(diff,(510,638)) diff = np.reshape(diff,(510,638)) # return the huffman dictionary # return the huffman dictionary return list_dic, image, new_error, diff, boundary, predict, bins, A return list_dic, image, new_error, diff, boundary, predict, bins, A ``` ``` %% Cell type:code id:2eb774d2 tags: %% Cell type:code id:2eb774d2 tags: ``` python ``` python def encoder(error, list_dic, diff, bound, bins): def encoder(error, list_dic, diff, bound, bins): """ """ This function This function """ """ # copy the error matrix (including the boundary) # copy the error matrix (including the boundary) encoded = np.copy(error).astype(int).astype(str).astype(object) encoded = np.copy(error).astype(int).astype(str).astype(object) #diff = np.reshape(diff,(510,638)) #diff = np.reshape(diff,(510,638)) # loop through all the pixel to encode # loop through all the pixel to encode for i in range(encoded.shape[0]): for i in range(encoded.shape[0]): for j in range(encoded.shape[1]): for j in range(encoded.shape[1]): if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: encoded[i][j] = list_dic[0][encoded[i][j]] encoded[i][j] = list_dic[0][encoded[i][j]] elif diff[i-1][j-1] <= bins[0]: elif diff[i-1][j-1] <= bins[0]: encoded[i][j] = list_dic[1][encoded[i][j]] encoded[i][j] = list_dic[1][encoded[i][j]] elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: encoded[i][j] = list_dic[2][encoded[i][j]] encoded[i][j] = list_dic[2][encoded[i][j]] elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: encoded[i][j] = list_dic[3][encoded[i][j]] encoded[i][j] = list_dic[3][encoded[i][j]] else: else: encoded[i][j] = list_dic[4][encoded[i][j]] encoded[i][j] = list_dic[4][encoded[i][j]] return encoded return encoded ``` ``` %% Cell type:code id:8eeb40d0 tags: %% Cell type:code id:8eeb40d0 tags: ``` python ``` python def decoder(A, encoded_matrix, list_dic, bins): def decoder(A, encoded_matrix, list_dic, bins): """ """ Function that accecpts the prediction matrix A for the linear system, Function that accecpts the prediction matrix A for the linear system, the encoded matrix of error values, and the encoding dicitonary. the encoded matrix of error values, and the encoding dicitonary. """ """ # change the dictionary back to list # change the dictionary back to list # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins the_keys0 = list(list_dic[0].keys()) the_keys0 = list(list_dic[0].keys()) the_values0 = list(list_dic[0].values()) the_values0 = list(list_dic[0].values()) the_keys1 = list(list_dic[1].keys()) the_keys1 = list(list_dic[1].keys()) the_values1 = list(list_dic[1].values()) the_values1 = list(list_dic[1].values()) the_keys2 = list(list_dic[2].keys()) the_keys2 = list(list_dic[2].keys()) the_values2 = list(list_dic[2].values()) the_values2 = list(list_dic[2].values()) the_keys3 = list(list_dic[3].keys()) the_keys3 = list(list_dic[3].keys()) the_values3 = list(list_dic[3].values()) the_values3 = list(list_dic[3].values()) the_keys4 = list(list_dic[4].keys()) the_keys4 = list(list_dic[4].keys()) the_values4 = list(list_dic[4].values()) the_values4 = list(list_dic[4].values()) error_matrix = np.zeros((512,640)) error_matrix = np.zeros((512,640)) # loop through all the element in the matrix # loop through all the element in the matrix for i in range(error_matrix.shape[0]): for i in range(error_matrix.shape[0]): for j in range(error_matrix.shape[1]): for j in range(error_matrix.shape[1]): # if it's the very first pixel on the image # if it's the very first pixel on the image if i == 0 and j == 0: if i == 0 and j == 0: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) # if it's on the boundary # if it's on the boundary elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] # if not the boundary # if not the boundary else: else: # predict the image with the known pixel value # predict the image with the known pixel value z0 = error_matrix[i-1][j-1] z0 = error_matrix[i-1][j-1] z1 = error_matrix[i-1][j] z1 = error_matrix[i-1][j] z2 = error_matrix[i-1][j+1] z2 = error_matrix[i-1][j+1] z3 = error_matrix[i][j-1] z3 = error_matrix[i][j-1] y0 = int(-z0+z2-z3) y0 = int(-z0+z2-z3) y1 = int(z0+z1+z2) y1 = int(z0+z1+z2) y2 = int(-z0-z1-z2-z3) y2 = int(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) # add on the difference by searching the dictionary # add on the difference by searching the dictionary # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if difference <= bins[0]: if difference <= bins[0]: error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[1] and difference > bins[0]: elif difference <= bins[1] and difference > bins[0]: error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[2] and difference > bins[1]: elif difference <= bins[2] and difference > bins[1]: error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) else: else: error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) return error_matrix.astype(int) return error_matrix.astype(int) ``` ``` %% Cell type:code id:f959fe93 tags: %% Cell type:code id:f959fe93 tags: ``` python ``` python def compress_rate(image, error, diff, bound, list_dic, bins): def compress_rate(image, error, diff, bound, list_dic, bins): # the bits for the original image # the bits for the original image o_len = 0 o_len = 0 # the bits for the compressed image # the bits for the compressed image c_len = 0 c_len = 0 # initializing the varible # initializing the varible im = np.reshape(image,(512, 640)) im = np.reshape(image,(512, 640)) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) original = im[1:-1,1:-1].reshape(-1) original = im[1:-1,1:-1].reshape(-1) diff = diff.reshape(-1) diff = diff.reshape(-1) # calculate the bit for boundary # calculate the bit for boundary for i in range(0,len(bound)): for i in range(0,len(bound)): o_len += len(bin(real_b[i])[2:]) o_len += len(bin(real_b[i])[2:]) c_len += len(list_dic[0][str(bound[i])]) c_len += len(list_dic[0][str(bound[i])]) # calculate the bit for the pixels inside the boundary # calculate the bit for the pixels inside the boundary for i in range(0,len(original)): for i in range(0,len(original)): # for the original image # for the original image o_len += len(bin(original[i])[2:]) o_len += len(bin(original[i])[2:]) # check the difference and find the coresponding huffman table # check the difference and find the coresponding huffman table # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if diff[i] <= bins[0]: if diff[i] <= bins[0]: c_len += len(list_dic[1][str(int(error[i]))]) c_len += len(list_dic[1][str(int(error[i]))]) elif diff[i] <= bins[1] and diff[i] > bins[0]: elif diff[i] <= bins[1] and diff[i] > bins[0]: c_len += len(list_dic[2][str(int(error[i]))]) c_len += len(list_dic[2][str(int(error[i]))]) elif diff[i] <= bins[2] and diff[i] > bins[1]: elif diff[i] <= bins[2] and diff[i] > bins[1]: c_len += len(list_dic[3][str(int(error[i]))]) c_len += len(list_dic[3][str(int(error[i]))]) else: else: c_len += len(list_dic[5][str(int(error[i]))]) c_len += len(list_dic[5][str(int(error[i]))]) return c_len/o_len return c_len/o_len ``` ``` %% Cell type:code id:3e0e9742 tags: %% Cell type:code id:3e0e9742 tags: ``` python ``` python scenes = file_extractor() scenes = file_extractor() images = image_extractor(scenes) images = image_extractor(scenes) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) print(np.allclose(image, reconstruct_image)) print(np.allclose(image, reconstruct_image)) print(len(list_dic)) print(len(list_dic)) ``` ``` %% Output %% Output (512, 640) (512, 640) True True 5 5 %% Cell type:code id:004e8ba8 tags: %% Cell type:code id:004e8ba8 tags: ``` python ``` python print(bins) print(bins) ``` ``` %% Output %% Output [26, 40, 62] [26, 40, 62] %% Cell type:code id:a282f9e6 tags: %% Cell type:code id:a282f9e6 tags: ``` python ``` python def predict_pix_lstsq(tiff_list): """ Predict the next pixel using a fit hyperplane of the four closest pixels. The gradient measure in this function is the summed distance to the fitted hyperplane of each of the four points, aka the residual from the least squares function. The previous predict_pix function uses the difference between the minimal and maximal pixels of the surrounding four. """ image = tiff_list image = Image.open(image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) #round the solution to the nearest integer so that encoding/decoding is easier points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]]) #Matrix system of points that will be used to solve the least squares fitting hyperplane # flatten the neighbor pixels and stack them together z0 = np.ravel(z0) z1 = np.ravel(z1) z2 = np.ravel(z2) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T f, res, rank, s = la.lstsq(points, neighbor.T, rcond=None) # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # flatten the image to a vector image = np.ravel(image[1:-1,1:-1]) error = image-predict return image, predict, res, error, A, diff ``` ```
Encoding_decoding.ipynb +0 −49 Original line number Original line Diff line number Diff line %% Cell type:code id:14f74f21 tags: %% Cell type:code id:14f74f21 tags: ``` python ``` python import numpy as np import numpy as np from matplotlib import pyplot as plt from matplotlib import pyplot as plt from itertools import product from itertools import product import os import os import sys import sys from PIL import Image from PIL import Image from scipy.optimize import minimize,linprog from scipy.optimize import minimize,linprog import time import time import seaborn as sns import seaborn as sns from sklearn.neighbors import KernelDensity from sklearn.neighbors import KernelDensity import pandas as pd import pandas as pd from collections import Counter from collections import Counter import time import time ``` ``` %% Cell type:code id:c16af61f tags: %% Cell type:code id:c16af61f tags: ``` python ``` python def file_extractor(dirname="images"): def file_extractor(dirname="images"): files = os.listdir(dirname) files = os.listdir(dirname) scenes = [] scenes = [] for file in files: for file in files: if file == '.DS_Store': if file == '.DS_Store': continue continue else: else: scenes.append(os.path.join(dirname, file)) scenes.append(os.path.join(dirname, file)) return scenes return scenes def image_extractor(scenes): def image_extractor(scenes): image_folder = [] image_folder = [] for scene in scenes: for scene in scenes: files = os.listdir(scene) files = os.listdir(scene) for file in files: for file in files: #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": #if file[-4:] == ".jp4" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": if file[-5:] != ".tiff" or file[-7:] == "_6.tiff": continue continue else: else: image_folder.append(os.path.join(scene, file)) image_folder.append(os.path.join(scene, file)) return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor return image_folder #returns a list of file paths to .tiff files in the specified directory given in file_extractor def im_distribution(images, num): def im_distribution(images, num): """ """ Function that extracts tiff files from specific cameras and returns a list of all Function that extracts tiff files from specific cameras and returns a list of all the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise the tiff files corresponding to that camera. i.e. all pictures labeled "_7.tiff" or otherwise specified camera numbers. specified camera numbers. Parameters: Parameters: images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but of specific tiff files that can be opened right away. This is the list that we iterate through and of specific tiff files that can be opened right away. This is the list that we iterate through and divide. divide. num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits num (str): a string designation for the camera number that we want to extract i.e. "14" for double digits of "_1" for single digits. of "_1" for single digits. Returns: Returns: tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted from the 'images' list that correspond to the given num. from the 'images' list that correspond to the given num. """ """ tiff = [] tiff = [] for im in images: for im in images: if im[-7:-5] == num: if im[-7:-5] == num: tiff.append(im) tiff.append(im) return tiff return tiff ``` ``` %% Cell type:code id:aceba613 tags: %% Cell type:code id:aceba613 tags: ``` python ``` python def predict_pix(tiff_image): def predict_pix(tiff_image): """ """ This function predict the pixel values excluding the boundary. This function predict the pixel values excluding the boundary. Using the 4 neighbor pixel values and MSE to predict the next pixel value Using the 4 neighbor pixel values and MSE to predict the next pixel value (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,1) (0,1) (1,1) => relative position of the 4 other given values (-1,0) (0,0) => (0,0) is the one we want to predict (-1,0) (0,0) => (0,0) is the one we want to predict take the derivative of mean square error to solve for the system of equation take the derivative of mean square error to solve for the system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) A @ [a, b, c] = [-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3] where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) and the predicted pixel value is c. and the predicted pixel value is c. Input: Input: tiff_image (string): path to the tiff file tiff_image (string): path to the tiff file Return: Return: image (512 X 640): original image image (512 X 640): original image predict (325380,): predicted image exclude the boundary predict (325380,): predicted image exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary diff. (325380,): difference between the min and max of four neighbors exclude the boundary error (325380,): difference between the original image and predicted image error (325380,): difference between the original image and predicted image A (3 X 3): system of equation A (3 X 3): system of equation """ """ image = Image.open(tiff_image) #Open the image and read it as an Image object image = Image.open(tiff_image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) image = image.astype(int) print(image.shape) print(image.shape) # use # use A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) # where z0 = (-1,1), z1 = (0,1), z2 = (1,1), z3 = (-1,0) z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once # use numpy solver to solve the system of equations all at once #predict = np.floor(np.linalg.solve(A,y)[-1]) #predict = np.floor(np.linalg.solve(A,y)[-1]) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) # flatten the neighbor pixlels and stack them together # flatten the neighbor pixlels and stack them together z0 = np.ravel(z0) z0 = np.ravel(z0) z1 = np.ravel(z1) z1 = np.ravel(z1) z2 = np.ravel(z2) z2 = np.ravel(z2) z3 = np.ravel(z3) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T neighbor = np.vstack((z0,z1,z2,z3)).T # calculate the difference # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # calculate the error # calculate the error error = np.ravel(image[1:-1,1:-1])-predict error = np.ravel(image[1:-1,1:-1])-predict return image, predict, diff, error, A return image, predict, diff, error, A ``` ``` %% Cell type:code id:6b965751 tags: %% Cell type:code id:6b965751 tags: ``` python ``` python """ """ this huffman coding code is found online this huffman coding code is found online https://favtutor.com/blogs/huffman-coding https://favtutor.com/blogs/huffman-coding """ """ class NodeTree(object): class NodeTree(object): def __init__(self, left=None, right=None): def __init__(self, left=None, right=None): self.left = left self.left = left self.right = right self.right = right def children(self): def children(self): return self.left, self.right return self.left, self.right def __str__(self): def __str__(self): return self.left, self.right return self.left, self.right def huffman_code_tree(node, binString=''): def huffman_code_tree(node, binString=''): ''' ''' Function to find Huffman Code Function to find Huffman Code ''' ''' if type(node) is str: if type(node) is str: return {node: binString} return {node: binString} (l, r) = node.children() (l, r) = node.children() d = dict() d = dict() d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(l, binString + '0')) d.update(huffman_code_tree(r, binString + '1')) d.update(huffman_code_tree(r, binString + '1')) return d return d def make_tree(nodes): def make_tree(nodes): ''' ''' Function to make tree Function to make tree :param nodes: Nodes :param nodes: Nodes :return: Root of the tree :return: Root of the tree ''' ''' while len(nodes) > 1: while len(nodes) > 1: (key1, c1) = nodes[-1] (key1, c1) = nodes[-1] (key2, c2) = nodes[-2] (key2, c2) = nodes[-2] nodes = nodes[:-2] nodes = nodes[:-2] node = NodeTree(key1, key2) node = NodeTree(key1, key2) nodes.append((node, c1 + c2)) nodes.append((node, c1 + c2)) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) nodes = sorted(nodes, key=lambda x: x[1], reverse=True) return nodes[0][0] return nodes[0][0] ``` ``` %% Cell type:code id:b7561883 tags: %% Cell type:code id:b7561883 tags: ``` python ``` python def huffman(image, num_bins=4): def huffman(image, num_bins=4): """ """ This function is used to encode the error based on the difference This function is used to encode the error based on the difference and split the difference into different bins and split the difference into different bins Input: Input: image (string): path to the tiff file image (string): path to the tiff file num_bins (int): number of bins num_bins (int): number of bins Return: Return: list_dic (num_bins + 1): a list of dictionary list_dic (num_bins + 1): a list of dictionary image (512, 640): original image image (512, 640): original image new_error (512, 640): error that includes the boundary new_error (512, 640): error that includes the boundary diff (510, 638): difference of min and max of the 4 neighbors diff (510, 638): difference of min and max of the 4 neighbors boundary (2300,): the boundary values after subtracting the very first pixel value boundary (2300,): the boundary values after subtracting the very first pixel value predict (325380,): the list of predicted values predict (325380,): the list of predicted values bins (num_bins - 1,): a list of threshold to cut the bins bins (num_bins - 1,): a list of threshold to cut the bins A (3 X 3): system of equation A (3 X 3): system of equation """ """ # get the prediction error and difference # get the prediction error and difference image, predict, diff, error, A = predict_pix(image) image, predict, diff, error, A = predict_pix(image) # get the number of points in each bins # get the number of points in each bins data_points_per_bin = len(diff) // num_bins data_points_per_bin = len(diff) // num_bins # sort the difference and create the bins # sort the difference and create the bins sorted_diff = diff.copy() sorted_diff = diff.copy() sorted_diff.sort() sorted_diff.sort() bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)] # get the boundary # get the boundary boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1])) # take the difference of the boundary with the very first pixel # take the difference of the boundary with the very first pixel boundary = boundary - image[0,0] boundary = boundary - image[0,0] boundary[0] = image[0,0] boundary[0] = image[0,0] # huffman encode the boundary # huffman encode the boundary string = [str(i) for i in boundary] string = [str(i) for i in boundary] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) # create a list of huffman table # create a list of huffman table list_dic = [encode] list_dic = [encode] n = len(bins) n = len(bins) # loop through different bins # loop through different bins for i in range (0,n): for i in range (0,n): # the fisrt bin # the fisrt bin if i == 0 : if i == 0 : # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff <= bins[i] mask = diff <= bins[i] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the middle bins # the middle bins else: else: # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[i-1] mask = diff > bins[i-1] new_error = error[mask] new_error = error[mask] mask2 = diff[mask] <= bins[i] mask2 = diff[mask] <= bins[i] string = [str(i) for i in new_error[mask2].astype(int)] string = [str(i) for i in new_error[mask2].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # the last bin # the last bin # get the point within the bin and huffman encode # get the point within the bin and huffman encode mask = diff > bins[-1] mask = diff > bins[-1] string = [str(i) for i in error[mask].astype(int)] string = [str(i) for i in error[mask].astype(int)] freq = dict(Counter(string)) freq = dict(Counter(string)) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) node = make_tree(freq) node = make_tree(freq) encode = huffman_code_tree(node) encode = huffman_code_tree(node) list_dic.append(encode) list_dic.append(encode) # create a error matrix that includes the boundary (used in encoding matrix) # create a error matrix that includes the boundary (used in encoding matrix) new_error = np.copy(image) new_error = np.copy(image) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) new_error[1:-1,1:-1] = np.reshape(error,(510, 638)) keep = new_error[0,0] keep = new_error[0,0] new_error[0,:] = new_error[0,:] - keep new_error[0,:] = new_error[0,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[-1,:] = new_error[-1,:] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,0] = new_error[1:-1,0] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[1:-1,-1] = new_error[1:-1,-1] - keep new_error[0,0] = keep new_error[0,0] = keep diff = np.reshape(diff,(510,638)) diff = np.reshape(diff,(510,638)) # return the huffman dictionary # return the huffman dictionary return list_dic, image, new_error, diff, boundary, predict, bins, A return list_dic, image, new_error, diff, boundary, predict, bins, A ``` ``` %% Cell type:code id:2eb774d2 tags: %% Cell type:code id:2eb774d2 tags: ``` python ``` python def encoder(error, list_dic, diff, bound, bins): def encoder(error, list_dic, diff, bound, bins): """ """ This function This function """ """ # copy the error matrix (including the boundary) # copy the error matrix (including the boundary) encoded = np.copy(error).astype(int).astype(str).astype(object) encoded = np.copy(error).astype(int).astype(str).astype(object) #diff = np.reshape(diff,(510,638)) #diff = np.reshape(diff,(510,638)) # loop through all the pixel to encode # loop through all the pixel to encode for i in range(encoded.shape[0]): for i in range(encoded.shape[0]): for j in range(encoded.shape[1]): for j in range(encoded.shape[1]): if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: if i == 0 or i == encoded.shape[0]-1 or j == 0 or j == encoded.shape[1]-1: encoded[i][j] = list_dic[0][encoded[i][j]] encoded[i][j] = list_dic[0][encoded[i][j]] elif diff[i-1][j-1] <= bins[0]: elif diff[i-1][j-1] <= bins[0]: encoded[i][j] = list_dic[1][encoded[i][j]] encoded[i][j] = list_dic[1][encoded[i][j]] elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]: encoded[i][j] = list_dic[2][encoded[i][j]] encoded[i][j] = list_dic[2][encoded[i][j]] elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]: encoded[i][j] = list_dic[3][encoded[i][j]] encoded[i][j] = list_dic[3][encoded[i][j]] else: else: encoded[i][j] = list_dic[4][encoded[i][j]] encoded[i][j] = list_dic[4][encoded[i][j]] return encoded return encoded ``` ``` %% Cell type:code id:8eeb40d0 tags: %% Cell type:code id:8eeb40d0 tags: ``` python ``` python def decoder(A, encoded_matrix, list_dic, bins): def decoder(A, encoded_matrix, list_dic, bins): """ """ Function that accecpts the prediction matrix A for the linear system, Function that accecpts the prediction matrix A for the linear system, the encoded matrix of error values, and the encoding dicitonary. the encoded matrix of error values, and the encoding dicitonary. """ """ # change the dictionary back to list # change the dictionary back to list # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins the_keys0 = list(list_dic[0].keys()) the_keys0 = list(list_dic[0].keys()) the_values0 = list(list_dic[0].values()) the_values0 = list(list_dic[0].values()) the_keys1 = list(list_dic[1].keys()) the_keys1 = list(list_dic[1].keys()) the_values1 = list(list_dic[1].values()) the_values1 = list(list_dic[1].values()) the_keys2 = list(list_dic[2].keys()) the_keys2 = list(list_dic[2].keys()) the_values2 = list(list_dic[2].values()) the_values2 = list(list_dic[2].values()) the_keys3 = list(list_dic[3].keys()) the_keys3 = list(list_dic[3].keys()) the_values3 = list(list_dic[3].values()) the_values3 = list(list_dic[3].values()) the_keys4 = list(list_dic[4].keys()) the_keys4 = list(list_dic[4].keys()) the_values4 = list(list_dic[4].values()) the_values4 = list(list_dic[4].values()) error_matrix = np.zeros((512,640)) error_matrix = np.zeros((512,640)) # loop through all the element in the matrix # loop through all the element in the matrix for i in range(error_matrix.shape[0]): for i in range(error_matrix.shape[0]): for j in range(error_matrix.shape[1]): for j in range(error_matrix.shape[1]): # if it's the very first pixel on the image # if it's the very first pixel on the image if i == 0 and j == 0: if i == 0 and j == 0: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) # if it's on the boundary # if it's on the boundary elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1: error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] error_matrix[i][j] = int(the_keys0[the_values0.index(encoded_matrix[i,j])]) + error_matrix[0][0] # if not the boundary # if not the boundary else: else: # predict the image with the known pixel value # predict the image with the known pixel value z0 = error_matrix[i-1][j-1] z0 = error_matrix[i-1][j-1] z1 = error_matrix[i-1][j] z1 = error_matrix[i-1][j] z2 = error_matrix[i-1][j+1] z2 = error_matrix[i-1][j+1] z3 = error_matrix[i][j-1] z3 = error_matrix[i][j-1] y0 = int(-z0+z2-z3) y0 = int(-z0+z2-z3) y1 = int(z0+z1+z2) y1 = int(z0+z1+z2) y2 = int(-z0-z1-z2-z3) y2 = int(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) y = np.vstack((y0,y1,y2)) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1)) # add on the difference by searching the dictionary # add on the difference by searching the dictionary # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if difference <= bins[0]: if difference <= bins[0]: error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[1] and difference > bins[0]: elif difference <= bins[1] and difference > bins[0]: error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys2[the_values2.index(encoded_matrix[i,j])]) + int(predict) elif difference <= bins[2] and difference > bins[1]: elif difference <= bins[2] and difference > bins[1]: error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys3[the_values3.index(encoded_matrix[i,j])]) + int(predict) else: else: error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) error_matrix[i][j] = int(the_keys4[the_values4.index(encoded_matrix[i,j])]) + int(predict) return error_matrix.astype(int) return error_matrix.astype(int) ``` ``` %% Cell type:code id:f959fe93 tags: %% Cell type:code id:f959fe93 tags: ``` python ``` python def compress_rate(image, error, diff, bound, list_dic, bins): def compress_rate(image, error, diff, bound, list_dic, bins): # the bits for the original image # the bits for the original image o_len = 0 o_len = 0 # the bits for the compressed image # the bits for the compressed image c_len = 0 c_len = 0 # initializing the varible # initializing the varible im = np.reshape(image,(512, 640)) im = np.reshape(image,(512, 640)) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1])) original = im[1:-1,1:-1].reshape(-1) original = im[1:-1,1:-1].reshape(-1) diff = diff.reshape(-1) diff = diff.reshape(-1) # calculate the bit for boundary # calculate the bit for boundary for i in range(0,len(bound)): for i in range(0,len(bound)): o_len += len(bin(real_b[i])[2:]) o_len += len(bin(real_b[i])[2:]) c_len += len(list_dic[0][str(bound[i])]) c_len += len(list_dic[0][str(bound[i])]) # calculate the bit for the pixels inside the boundary # calculate the bit for the pixels inside the boundary for i in range(0,len(original)): for i in range(0,len(original)): # for the original image # for the original image o_len += len(bin(original[i])[2:]) o_len += len(bin(original[i])[2:]) # check the difference and find the coresponding huffman table # check the difference and find the coresponding huffman table # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins if diff[i] <= bins[0]: if diff[i] <= bins[0]: c_len += len(list_dic[1][str(int(error[i]))]) c_len += len(list_dic[1][str(int(error[i]))]) elif diff[i] <= bins[1] and diff[i] > bins[0]: elif diff[i] <= bins[1] and diff[i] > bins[0]: c_len += len(list_dic[2][str(int(error[i]))]) c_len += len(list_dic[2][str(int(error[i]))]) elif diff[i] <= bins[2] and diff[i] > bins[1]: elif diff[i] <= bins[2] and diff[i] > bins[1]: c_len += len(list_dic[3][str(int(error[i]))]) c_len += len(list_dic[3][str(int(error[i]))]) else: else: c_len += len(list_dic[5][str(int(error[i]))]) c_len += len(list_dic[5][str(int(error[i]))]) return c_len/o_len return c_len/o_len ``` ``` %% Cell type:code id:3e0e9742 tags: %% Cell type:code id:3e0e9742 tags: ``` python ``` python scenes = file_extractor() scenes = file_extractor() images = image_extractor(scenes) images = image_extractor(scenes) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) list_dic, image, new_error, diff, bound, predict, bins, A = huffman(images[0], 4) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) encoded_matrix = encoder(new_error, list_dic, diff, bound, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) reconstruct_image = decoder(A, encoded_matrix, list_dic, bins) print(np.allclose(image, reconstruct_image)) print(np.allclose(image, reconstruct_image)) print(len(list_dic)) print(len(list_dic)) ``` ``` %% Output %% Output (512, 640) (512, 640) True True 5 5 %% Cell type:code id:004e8ba8 tags: %% Cell type:code id:004e8ba8 tags: ``` python ``` python print(bins) print(bins) ``` ``` %% Output %% Output [26, 40, 62] [26, 40, 62] %% Cell type:code id:a282f9e6 tags: %% Cell type:code id:a282f9e6 tags: ``` python ``` python def predict_pix_lstsq(tiff_list): """ Predict the next pixel using a fit hyperplane of the four closest pixels. The gradient measure in this function is the summed distance to the fitted hyperplane of each of the four points, aka the residual from the least squares function. The previous predict_pix function uses the difference between the minimal and maximal pixels of the surrounding four. """ image = tiff_list image = Image.open(image) #Open the image and read it as an Image object image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data image = image.astype(int) A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation z0 = image[0:-2,0:-2] # get all the first pixel for the entire image z1 = image[0:-2,1:-1] # get all the second pixel for the entire image z2 = image[0:-2,2::] # get all the third pixel for the entire image z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image # calculate the out put of the system of equation y0 = np.ravel(-z0+z2-z3) y1 = np.ravel(z0+z1+z2) y2 = np.ravel(-z0-z1-z2-z3) y = np.vstack((y0,y1,y2)) # use numpy solver to solve the system of equations all at once predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1)) #round the solution to the nearest integer so that encoding/decoding is easier points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]]) #Matrix system of points that will be used to solve the least squares fitting hyperplane # flatten the neighbor pixels and stack them together z0 = np.ravel(z0) z1 = np.ravel(z1) z2 = np.ravel(z2) z3 = np.ravel(z3) neighbor = np.vstack((z0,z1,z2,z3)).T f, res, rank, s = la.lstsq(points, neighbor.T, rcond=None) # calculate the difference diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1) # flatten the image to a vector image = np.ravel(image[1:-1,1:-1]) error = image-predict return image, predict, res, error, A, diff ``` ```