Commit 89fbb7f5 authored by Bryce Hepner's avatar Bryce Hepner
Browse files

various tests

parent 4286c54a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -5,3 +5,4 @@ attic
*.log
/compress_start.pyc
/compress_experiment.ipynb
*.txt
 No newline at end of file
+87 −11
Original line number Diff line number Diff line
%% Cell type:code id: tags:

``` 
``` python
import numpy as np
from matplotlib import pyplot as plt
from itertools import product
import os
import sys
from PIL import Image
from scipy.optimize import minimize,linprog
from sklearn.neighbors import KernelDensity
from collections import Counter
import numpy.linalg as la
```

%% Cell type:code id: tags:

``` 
``` python
def file_extractor(dirname="images"):
    files = os.listdir(dirname)
    scenes = []
    for file in files:
        if file == '.DS_Store':
            continue
        else:
            scenes.append(os.path.join(dirname, file))
    return scenes

def image_extractor(scenes):
    image_folder = []
    for scene in scenes:
        files = os.listdir(scene)
        for file in files:
            if file[-5:] != ".tiff" or file[-7:] == "_6.tiff":
                continue
            else:
                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

def im_distribution(images, num):
    """
    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
    specified camera numbers.

    Parameters:
        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
        divide.

        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.

    Returns:
        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.
    """
    tiff = []
    for im in images:
        if im[-7:-5] == num:
            tiff.append(im)
    return tiff
```

%% Cell type:code id: tags:

``` 
``` python
def predict_pix(tiff_image_path, difference = True):
    """
    This function predict the pixel values excluding the boundary.
    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,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
    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)
    and the predicted pixel value is c.

    Input:
    tiff_image_path (string): path to the tiff file

    Return:
    image   ndarray(512 X 640): original image
    predict ndarray(325380,): predicted image excluding the boundary
    diff.   ndarray(325380,): IF difference = TRUE, difference between the min and max of four neighbors exclude the boundary
                            ELSE: the residuals of the four nearest pixels to a fitted hyperplane
    error   ndarray(325380,): difference between the original image and predicted image
    A       ndarray(3 X 3): system of equation
    """
    image_obj = Image.open(tiff_image_path)    #Open the image and read it as an Image object
    image_array = np.array(image_obj)[1:,:].astype(int)    #Convert to an array, leaving out the first row because the first row is just housekeeping data
    # image_array = image_array.astype(int)
    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)
    z0 = image_array[0:-2,0:-2]   # get all the first pixel for the entire image
    z1 = image_array[0:-2,1:-1]   # get all the second pixel for the entire image
    z2 = image_array[0:-2,2::]    # get all the third pixel for the entire image
    z3 = image_array[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.floor(np.linalg.solve(A,y)[-1])
    predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1))

    #Matrix system of points that will be used to solve the least squares fitting hyperplane
    points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]])

    # flatten the neighbor pixlels 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

    if difference:
        # calculate the difference
        diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1)

    else:
        #Compute the best fitting hyperplane using least squares
        #The res is the residuals of the four points used to fit the hyperplane (summed distance of each of the
        #points to the hyperplane), it is a measure of gradient
        f, diff, rank, s = la.lstsq(points, neighbor.T, rcond=None)
        diff = diff.astype(int)

    # calculate the error
    error = np.ravel(image_array[1:-1,1:-1])-predict

    return image_array, predict, diff, error
```

%% Cell type:code id: tags:

``` 
``` python
"""
this huffman encoding code is found online
https://favtutor.com/blogs/huffman-coding
"""

class NodeTree(object):
    def __init__(self, left=None, right=None):
        self.left = left
        self.right = right

    def children(self):
        return self.left, self.right

    def __str__(self):
        return self.left, self.right


def huffman_code_tree(node, binString=''):
    '''
    Function to find Huffman Code
    '''
    if type(node) is str:
        return {node: binString}
    (l, r) = node.children()
    d = dict()
    d.update(huffman_code_tree(l, binString + '0'))
    d.update(huffman_code_tree(r, binString + '1'))
    return d


def make_tree(nodes):
    '''
    Function to make tree
    :param nodes: Nodes
    :return: Root of the tree
    '''
    while len(nodes) > 1:
        (key1, c1) = nodes[-1]
        (key2, c2) = nodes[-2]
        nodes = nodes[:-2]
        node = NodeTree(key1, key2)
        nodes.append((node, c1 + c2))
        #reverse True, decending order
        nodes = sorted(nodes, key=lambda x: x[1], reverse=True)
    return nodes[0][0]
def decode_string(huffman_string, the_keys, the_values):
    for i in range(len(huffman_string)):
        try:
            return (int(the_keys[the_values.index(huffman_string[:i+1])]),huffman_string[i+1:])
        except:
            pass
```

%% Cell type:code id: tags:

``` 
``` python
def make_dictionary(tiff_image_path_list, num_bins=4, difference = True):
    """
    This function is used to encode the error based on the difference
    and split the difference into different bins

    Input:
    tiff_image_path     (string): path to the tiff file
    num_bins            (int): number of bins

    Return:
    huffman_encoding_list  list    (num_bins + 1): a list of dictionary
    image_array            ndarray (512, 640): original image
    new_error              ndarray (512, 640): error that includes the boundary
    diff                   ndarray (510, 638): difference of min and max of the 4 neighbors
    boundary               ndarray (2300,): the boundary values after subtracting the very first pixel value
    predict                ndarray (325380,): the list of predicted values
    bins                   list    (num_bins - 1,): a list of threshold to cut the bins
    A                      ndarray (3 X 3): system of equation

    """
    list_of_all_vals = []
    huffman_encoding_list = []
    for i in range(num_bins+1):
        list_of_all_vals.append([])
    for i, tiff_image_path in enumerate(tiff_image_path_list):
        # get the image_array, etc
        image_array, predict, diff, error= predict_pix(tiff_image_path, difference)

        # calculate the number of points that will go in each bin
        data_points_per_bin = diff.size // num_bins

        # sort the difference and create the bins
        sorted_diff = np.sort(diff.copy())
        # bins = [12,60,180]
        bins = [21,31,48]
        # get the boundary
        boundary = np.hstack((image_array[0,:],image_array[-1,:],image_array[1:-1,0],image_array[1:-1,-1]))

        # take the difference of the boundary with the very first pixel
        boundary = boundary - image_array[0,0]

        #boundary is 1dim, so boundary[0] is just the first element
        boundary[0] = image_array[0,0]

        # huffman encode the boundary
        for j in boundary:
            list_of_all_vals[0].append(str(j))

        # create a list of huffman table
        n = len(bins)

        # loop through different bins
        for k in range (0,n):
            # the first bin
            if k == 0 :
                # get the point within the bin and huffman huffman_encoding_dict
                mask = diff <= bins[k]
                for j in error[mask].astype(int):
                    list_of_all_vals[k+1].append(str(j))


            # the middle bins
            else:
                # get the point within the bin and huffman huffman_encoding_dict
                mask = diff > bins[k-1]
                new_error = error[mask]
                mask2 = diff[mask] <= bins[k]
                for j in new_error[mask2].astype(int):
                    list_of_all_vals[k+1].append(str(j))


        # the last bin
        # get the point within the bin and huffman huffman_encoding_dict
        mask = diff > bins[-1]
        for j in error[mask].astype(int):
            list_of_all_vals[-1].append(str(j))
    for item in list_of_all_vals:
        freq = dict(Counter(item))
        freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
        node = make_tree(freq)
        huffman_encoding_list.append(huffman_code_tree(node))
        # create a error matrix that includes the boundary (used in encoding matrix)
    new_error = np.copy(image_array)
    new_error[1:-1,1:-1] = np.reshape(error,(510, 638))
    keep = new_error[0,0]
    new_error[0,:] = new_error[0,:] - keep
    new_error[-1,:] = new_error[-1,:] - 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[0,0] = keep
        # huffman_encoding_list = list(set(huffman_encoding_list))
    diff = np.reshape(diff,(510,638))
        # return the huffman dictionary
    return huffman_encoding_list,bins
```

%% Cell type:code id: tags:

``` 
``` python
def huffman(tiff_image_path, num_bins=4, difference = True):
    """
    This function is used to encode the error based on the difference
    and split the difference into different bins

    Input:
    tiff_image_path     (string): path to the tiff file
    num_bins            (int): number of bins

    Return:
    huffman_encoding_list  list    (num_bins + 1): a list of dictionary
    image_array            ndarray (512, 640): original image
    new_error              ndarray (512, 640): error that includes the boundary
    diff                   ndarray (510, 638): difference of min and max of the 4 neighbors
    boundary               ndarray (2300,): the boundary values after subtracting the very first pixel value
    predict                ndarray (325380,): the list of predicted values
    bins                   list    (num_bins - 1,): a list of threshold to cut the bins
    A                      ndarray (3 X 3): system of equation
    """
    # get the image_array, etc
    image_array, predict, diff, error= predict_pix(tiff_image_path, difference)

    # calculate the number of points that will go in each bin
    data_points_per_bin = diff.size // num_bins

    # sort the difference and create the bins
    sorted_diff = np.sort(diff.copy())
    # bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)]
    # bins = [12,60,180]
    bins = [21,31,48]
    # get the boundary
    boundary = np.hstack((image_array[0,:],image_array[-1,:],image_array[1:-1,0],image_array[1:-1,-1]))

    # take the difference of the boundary with the very first pixel
    boundary = boundary - image_array[0,0]

    #boundary is 1dim, so boundary[0] is just the first element
    boundary[0] = image_array[0,0]

    # huffman encode the boundary
    bound_vals_as_string = [str(i) for i in boundary]
    freq = dict(Counter(bound_vals_as_string))
    freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
    node = make_tree(freq)
    huffman_encoding_dict = huffman_code_tree(node)

    # create a list of huffman table
    huffman_encoding_list = [huffman_encoding_dict]
    n = len(bins)

    # loop through different bins
    for i in range (0,n):
        # the first bin
        if i == 0 :
            # get the point within the bin and huffman huffman_encoding_dict
            mask = diff <= bins[i]
            line_as_string = [str(i) for i in error[mask].astype(int)]
            freq = dict(Counter(line_as_string))
            freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
            node = make_tree(freq)
            huffman_encoding_dict = huffman_code_tree(node)
            huffman_encoding_list.append(huffman_encoding_dict)

        # the middle bins
        else:
            # get the point within the bin and huffman huffman_encoding_dict
            mask = diff > bins[i-1]
            new_error = error[mask]
            mask2 = diff[mask] <= bins[i]
            line_as_string = [str(i) for i in new_error[mask2].astype(int)]
            freq = dict(Counter(line_as_string))
            freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
            node = make_tree(freq)
            huffman_encoding_dict = huffman_code_tree(node)
            huffman_encoding_list.append(huffman_encoding_dict)

    # the last bin
    # get the point within the bin and huffman huffman_encoding_dict
    mask = diff > bins[-1]
    line_as_string = [str(i) for i in error[mask].astype(int)]
    freq = dict(Counter(line_as_string))
    freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
    node = make_tree(freq)
    huffman_encoding_dict = huffman_code_tree(node)
    huffman_encoding_list.append(huffman_encoding_dict)

    # create a error matrix that includes the boundary (used in encoding matrix)
    new_error = np.copy(image_array)
    new_error[1:-1,1:-1] = np.reshape(error,(510, 638))
    keep = new_error[0,0]
    new_error[0,:] = new_error[0,:] - keep
    new_error[-1,:] = new_error[-1,:] - 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[0,0] = keep
    # huffman_encoding_list = list(set(huffman_encoding_list))
    diff = np.reshape(diff,(510,638))
    # return the huffman dictionary

    return huffman_encoding_list, image_array, new_error, diff, boundary, predict, bins

```

%% Cell type:code id: tags:

``` 
``` python
def encoder(error, list_dic, diff, bound, bins):
    """
    This function encode the matrix with huffman coding tables

    Input:
    error     (512, 640): a matrix with all the errors
    list_dic  (num_dic + 1,): a list of huffman coding table
    bound     (2300,): the boundary values after subtracting the very first pixel value
    bins       (num_bins - 1,): a list of threshold to cut the bins

    Return:
    encoded   (512, 640): encoded matrix
    """
    returnable_encode = ""
    # copy the error matrix (including the boundary)
    encoded = np.copy(error).astype(int).astype(str).astype(object)
    #diff = np.reshape(diff,(510,638))
    # loop through all the pixel to encode
    for i in range(encoded.shape[0]):
        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:
                returnable_encode += list_dic[0][encoded[i][j]]
            elif diff[i-1][j-1] <= bins[0]:
                returnable_encode += list_dic[1][encoded[i][j]]
            elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]:
                returnable_encode +=list_dic[2][encoded[i][j]]
            elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]:
                returnable_encode +=list_dic[3][encoded[i][j]]
            else:
                returnable_encode += list_dic[4][encoded[i][j]]
    return returnable_encode
```

%% Cell type:code id: tags:

``` 
``` python
# def bitstring_to_bytes(s):
#     v = int(s, 2)
#     b = bytearray()
#     while v:
#         b.append(v & 0xff)
#         v >>= 8
#     return bytes(b[::-1])
def bitstring_to_bytes(input_string):
    int_array = []
    length_of_string = len(input_string)
    while length_of_string >= 8:
        int_array.append(int(input_string[:8],2))
        input_string = input_string[8:]
        length_of_string = len(input_string)
    if length_of_string > 0:
        zerobuffer = ""
        for _ in range(8-length_of_string):
            zerobuffer += "0"
        int_array.append(int(input_string+zerobuffer,2))
    # print(int_array[0:20])
    # print(int_array[-12:])
    return bytes(int_array)
```

%% Cell type:code id: tags:

``` 
``` python
def decoder(encoded_string, list_dic, bins, use_diff):
    """
    This function decodes the encoded_matrix.
    Input:
    A               (3 X 3): system of equation
    list_dic        (num_dic + 1,): a list of huffman coding table
    encoded_matrix  (512, 640): encoded matrix
    bins            (num_bins - 1,): a list of threshold to cut the bins

    Return:
    decode_matrix   (512, 640): decoded matrix
    """
    A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation
    # change the dictionary back to list
    # !!!!!WARNING!!!! has to change this part, everytime you change the number of bins
    the_keys0 = list(list_dic[0].keys())
    the_values0 = list(list_dic[0].values())

    the_keys1 = list(list_dic[1].keys())
    the_values1 = list(list_dic[1].values())

    the_keys2 = list(list_dic[2].keys())
    the_values2 = list(list_dic[2].values())

    the_keys3 = list(list_dic[3].keys())
    the_values3 = list(list_dic[3].values())

    the_keys4 = list(list_dic[4].keys())
    the_values4 = list(list_dic[4].values())

    #Matrix system of points that will be used to solve the least squares fitting hyperplane
    points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]])

    decode_matrix = np.zeros((512,640))
    # loop through all the element in the matrix
    for i in range(decode_matrix.shape[0]):
        for j in range(decode_matrix.shape[1]):
            # if it's the very first pixel on the image
            if i == 0 and j == 0:
                colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys0, the_values=the_values0)
                decode_matrix[i][j] = colorvalue

            # if it's on the boundary (any of the 4 edges)
            elif i == 0 or i == decode_matrix.shape[0]-1 or j == 0 or j == decode_matrix.shape[1]-1:
                colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys0, the_values=the_values0)
                decode_matrix[i][j] = colorvalue + decode_matrix[0][0]
            # if not the boundary
            else:
                # predict the image with the known pixel value
                z0 = decode_matrix[i-1][j-1]
                z1 = decode_matrix[i-1][j]
                z2 = decode_matrix[i-1][j+1]
                z3 = decode_matrix[i][j-1]
                y0 = int(-z0+z2-z3)
                y1 = int(z0+z1+z2)
                y2 = int(-z0-z1-z2-z3)
                y = np.vstack((y0,y1,y2))
                if use_diff:
                    difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3)
                else:

                    f, difference, rank, s = la.lstsq(points, [z0,z1,z2,z3], rcond=None)
                    difference = difference.astype(int)

                predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1))

                # add on the difference by searching the dictionary
                # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins
                if difference <= bins[0]:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys1, the_values=the_values1)
                    decode_matrix[i][j] = colorvalue + int(predict)
                elif difference <= bins[1] and difference > bins[0]:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys2, the_values=the_values2)
                    decode_matrix[i][j] = colorvalue + int(predict)
                elif difference <= bins[2] and difference > bins[1]:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys3, the_values=the_values3)
                    decode_matrix[i][j] = colorvalue + int(predict)
                else:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys4, the_values=the_values4)
                    decode_matrix[i][j] = colorvalue + int(predict)

    return decode_matrix.astype(int)
```

%% Cell type:code id: tags:

``` 
``` python
def read_from_file(filename):
    with open(filename, 'rb') as file:
        return file.read()
```

%% Cell type:code id: tags:

``` 
``` python
scenes = file_extractor()
newnamesforlater = []
images = image_extractor(scenes)
oglist_dic, ogbins = make_dictionary(images[:10], 1, False)
file_size_ratios = []
np.save("first_dic.npy", oglist_dic)
for i in range(10):
    list_dic, image, new_error, diff, bound, predict, bins = huffman(images[i], 1, False)
    encoded_string1 = encoder(new_error, oglist_dic, diff, bound, ogbins)
    # reconstruct_image = decoder(A, encoded_string, list_dic, bins, False)
    # print(np.allclose(image, reconstruct_image))
    inletters = bitstring_to_bytes(encoded_string1)
    if images[i][:-5] == ".tiff":
        newname = images[i][:-5]
    else:
        newname = images[i][:-4]
    newnamesforlater.append(newname + "_Compressed.txt")
    with open(newname + "_Compressed.txt", 'wb') as f:
        f.write(inletters)
    file_size_ratios.append((os.path.getsize(newname + "_Compressed.txt"))/os.path.getsize('images/1626032610_393963/1626032610_393963_0.tiff'))
```

%% Cell type:code id: tags:

``` python
def check_bin_size(tiff_image_path_list, num_bins=4, difference = True):
    """
    This function is used to encode the error based on the difference
    and split the difference into different bins

    Input:
    tiff_image_path     (string): path to the tiff file
    num_bins            (int): number of bins

    Return:
    huffman_encoding_list  list    (num_bins + 1): a list of dictionary
    image_array            ndarray (512, 640): original image
    new_error              ndarray (512, 640): error that includes the boundary
    diff                   ndarray (510, 638): difference of min and max of the 4 neighbors
    boundary               ndarray (2300,): the boundary values after subtracting the very first pixel value
    predict                ndarray (325380,): the list of predicted values
    bins                   list    (num_bins - 1,): a list of threshold to cut the bins
    A                      ndarray (3 X 3): system of equation

    """
    all_bins = []
    for i, tiff_image_path in enumerate(tiff_image_path_list):
        # get the image_array, etc
        image_array, predict, diff, error= predict_pix(tiff_image_path, difference)

        # calculate the number of points that will go in each bin
        data_points_per_bin = diff.size // num_bins

        # sort the difference and create the bins
        sorted_diff = np.sort(diff.copy())
        bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)]
        all_bins.append(bins)
    return np.mean(all_bins,axis = 0), np.min(all_bins,axis = 0), np.max(all_bins,axis=0)
```

%% Cell type:code id: tags:

``` python
scenes = file_extractor()
newnamesforlater = []
images = image_extractor(scenes)
print(check_bin_size(images))
```

%% Output

    (array([21.00404858, 31.92712551, 48.06477733]), array([11, 16, 22]), array([ 30,  70, 141]))

%% Cell type:code id: tags:

``` python
scenes = file_extractor()
newnamesforlater = []
images = image_extractor(scenes)
oglist_dic, ogbins = make_dictionary(images[:10], 1, False)
file_size_ratios = []
np.save("first_dic.npy", oglist_dic)
for i in range(10):
    list_dic, image, new_error, diff, bound, predict, bins = huffman(images[i], 1, False)
    encoded_string1 = encoder(new_error, oglist_dic, diff, bound, ogbins)
    # reconstruct_image = decoder(A, encoded_string, list_dic, bins, False)
    # print(np.allclose(image, reconstruct_image))
    inletters = bitstring_to_bytes(encoded_string1)
    if images[i][:-5] == ".tiff":
        newname = images[i][:-5]
    else:
        newname = images[i][:-4]
    newnamesforlater.append(newname + "_Compressed.txt")
    with open(newname + "_Compressed.txt", 'wb') as f:
        f.write(inletters)
    file_size_ratios.append((os.path.getsize(newname + "_Compressed.txt"))/os.path.getsize('images/1626032610_393963/1626032610_393963_0.tiff'))
```
+22 −20
Original line number Diff line number Diff line
%% Cell type:code id: tags:

``` python
import numpy as np
from matplotlib import pyplot as plt
from itertools import product
import os
import sys
from PIL import Image
from scipy.optimize import minimize,linprog
from sklearn.neighbors import KernelDensity
from collections import Counter
import numpy.linalg as la
```

%% Cell type:code id: tags:

``` python
def file_extractor(dirname="images"):
    files = os.listdir(dirname)
    scenes = []
    for file in files:
        if file == '.DS_Store':
            continue
        else:
            scenes.append(os.path.join(dirname, file))
    return scenes

def image_extractor(scenes):
    image_folder = []
    for scene in scenes:
        files = os.listdir(scene)
        for file in files:
            if file[-5:] != ".tiff" or file[-7:] == "_6.tiff":
                continue
            else:
                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

def im_distribution(images, num):
    """
    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
    specified camera numbers.

    Parameters:
        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
        divide.

        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.

    Returns:
        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.
    """
    tiff = []
    for im in images:
        if im[-7:-5] == num:
            tiff.append(im)
    return tiff
```

%% Cell type:code id: tags:

``` python
def predict_pix(tiff_image_path, difference = True):
    """
    This function predict the pixel values excluding the boundary.
    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,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
    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)
    and the predicted pixel value is c.

    Input:
    tiff_image_path (string): path to the tiff file

    Return:
    image   ndarray(512 X 640): original image
    predict ndarray(325380,): predicted image excluding the boundary
    diff.   ndarray(325380,): IF difference = TRUE, difference between the min and max of four neighbors exclude the boundary
                            ELSE: the residuals of the four nearest pixels to a fitted hyperplane
    error   ndarray(325380,): difference between the original image and predicted image
    A       ndarray(3 X 3): system of equation
    """
    image_obj = Image.open(tiff_image_path)    #Open the image and read it as an Image object
    image_array = np.array(image_obj)[1:,:].astype(int)    #Convert to an array, leaving out the first row because the first row is just housekeeping data
    # image_array = image_array.astype(int)
    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)
    z0 = image_array[0:-2,0:-2]   # get all the first pixel for the entire image
    z1 = image_array[0:-2,1:-1]   # get all the second pixel for the entire image
    z2 = image_array[0:-2,2::]    # get all the third pixel for the entire image
    z3 = image_array[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.floor(np.linalg.solve(A,y)[-1])
    predict = np.round(np.round((np.linalg.solve(A,y)[-1]),1))

    #Matrix system of points that will be used to solve the least squares fitting hyperplane
    points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]])

    # flatten the neighbor pixlels 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

    if difference:
        # calculate the difference
        diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1)

    else:
        #Compute the best fitting hyperplane using least squares
        #The res is the residuals of the four points used to fit the hyperplane (summed distance of each of the
        #points to the hyperplane), it is a measure of gradient
        f, diff, rank, s = la.lstsq(points, neighbor.T, rcond=None)
        diff = diff.astype(int)

    # calculate the error
    error = np.ravel(image_array[1:-1,1:-1])-predict

    return image_array, diff, error
```

%% Cell type:code id: tags:

``` python
"""
this huffman encoding code is found online
https://favtutor.com/blogs/huffman-coding
"""

class NodeTree(object):
    def __init__(self, left=None, right=None):
        self.left = left
        self.right = right

    def children(self):
        return self.left, self.right

    def __str__(self):
        return self.left, self.right


def huffman_code_tree(node, binString=''):
    '''
    Function to find Huffman Code
    '''
    if type(node) is str:
        return {node: binString}
    (l, r) = node.children()
    d = dict()
    d.update(huffman_code_tree(l, binString + '0'))
    d.update(huffman_code_tree(r, binString + '1'))
    return d


def make_tree(nodes):
    '''
    Function to make tree
    :param nodes: Nodes
    :return: Root of the tree
    '''
    while len(nodes) > 1:
        (key1, c1) = nodes[-1]
        (key2, c2) = nodes[-2]
        nodes = nodes[:-2]
        node = NodeTree(key1, key2)
        nodes.append((node, c1 + c2))
        #reverse True, decending order
        nodes = sorted(nodes, key=lambda x: x[1], reverse=True)
    return nodes[0][0]
def decode_string(huffman_string, the_keys, the_values):
    for i in range(len(huffman_string)):
        try:
            return (int(the_keys[the_values.index(huffman_string[:i+1])]),huffman_string[i+1:])
        except:
            pass
```

%% Cell type:code id: tags:

``` python
def make_dictionary(tiff_image_path_list, num_bins=4, difference = True):
    """
    This function is used to encode the error based on the difference
    and split the difference into different bins

    Input:
    tiff_image_path     (string): path to the tiff file
    num_bins            (int): number of bins

    Return:
    huffman_encoding_list  list    (num_bins + 1): a list of dictionary
    image_array            ndarray (512, 640): original image
    new_error              ndarray (512, 640): error that includes the boundary
    diff                   ndarray (510, 638): difference of min and max of the 4 neighbors
    boundary               ndarray (2300,): the boundary values after subtracting the very first pixel value
    predict                ndarray (325380,): the list of predicted values
    bins                   list    (num_bins - 1,): a list of threshold to cut the bins
    A                      ndarray (3 X 3): system of equation

    """
    list_of_all_vals = []
    huffman_encoding_list = []
    for _ in range(num_bins+1):
        list_of_all_vals.append([])
    for _, tiff_image_path in enumerate(tiff_image_path_list):
        # get the image_array, etc
        image_array, diff, error= predict_pix(tiff_image_path, difference)

        bins = [21,32,48]
        bins = [30,70,141]
        # get the boundary
        boundary = np.hstack((image_array[0,:],image_array[-1,:],image_array[1:-1,0],image_array[1:-1,-1]))

        # take the difference of the boundary with the very first pixel
        boundary = boundary - image_array[0,0]

        #boundary is 1dim, so boundary[0] is just the first element
        boundary[0] = image_array[0,0]

        # huffman encode the boundary
        for j in boundary:
            list_of_all_vals[0].append(str(j))

        # create a list of huffman table
        n = len(bins)

        # loop through different bins
        for k in range (0,n):
            # the first bin
            if k == 0 :
                # get the point within the bin and huffman huffman_encoding_dict
                mask = diff <= bins[k]
                for j in error[mask].astype(int):
                    list_of_all_vals[k+1].append(str(j))


            # the middle bins
            else:
                # get the point within the bin and huffman huffman_encoding_dict
                mask = diff > bins[k-1]
                new_error = error[mask]
                mask2 = diff[mask] <= bins[k]
                for j in new_error[mask2].astype(int):
                    list_of_all_vals[k+1].append(str(j))


        # the last bin
        # get the point within the bin and huffman huffman_encoding_dict
        mask = diff > bins[-1]
        for j in error[mask].astype(int):
            list_of_all_vals[-1].append(str(j))
    for item in list_of_all_vals:
        freq = dict(Counter(item))
        freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
        node = make_tree(freq)
        huffman_encoding_list.append(huffman_code_tree(node))
        # create a error matrix that includes the boundary (used in encoding matrix)
    new_error = np.copy(image_array)
    new_error[1:-1,1:-1] = np.reshape(error,(510, 638))
    keep = new_error[0,0]
    new_error[0,:] = new_error[0,:] - keep
    new_error[-1,:] = new_error[-1,:] - 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[0,0] = keep
        # huffman_encoding_list = list(set(huffman_encoding_list))
    diff = np.reshape(diff,(510,638))
        # return the huffman dictionary
    return huffman_encoding_list,bins
```

%% Cell type:code id: tags:

``` python
def huffman(tiff_image_path, num_bins=4, difference = True):
    """
    This function is used to encode the error based on the difference
    and split the difference into different bins

    Input:
    tiff_image_path     (string): path to the tiff file
    num_bins            (int): number of bins

    Return:
    huffman_encoding_list  list    (num_bins + 1): a list of dictionary
    image_as_array         ndarray (512, 640): original image
    new_error              ndarray (512, 640): error that includes the boundary
    diff                   ndarray (510, 638): difference of min and max of the 4 neighbors
    boundary               ndarray (2300,): the boundary values after subtracting the very first pixel value
    predict                ndarray (325380,): the list of predicted values
    bins                   list    (num_bins - 1,): a list of threshold to cut the bins
    A                      ndarray (3 X 3): system of equation
    """
    # get the image_as_array, etc
    image_as_array, diff, error= predict_pix(tiff_image_path, difference)

    # calculate the number of points that will go in each bin


    # sort the difference and create the bins
    bins = [21,32,48]
    bins = [30,70,141]
    # get the boundary
    boundary = np.hstack((image_as_array[0,:],image_as_array[-1,:],image_as_array[1:-1,0],image_as_array[1:-1,-1]))

    # take the difference of the boundary with the very first pixel
    boundary = boundary - image_as_array[0,0]

    #boundary is 1dim, so boundary[0] is just the first element
    boundary[0] = image_as_array[0,0]

    # huffman encode the boundary
    bound_vals_as_string = [str(i) for i in boundary]
    freq = dict(Counter(bound_vals_as_string))
    freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
    node = make_tree(freq)
    huffman_encoding_dict = huffman_code_tree(node)

    # create a list of huffman table
    huffman_encoding_list = [huffman_encoding_dict]
    n = len(bins)

    # loop through different bins
    for i in range (0,n):
        # the first bin
        if i == 0 :
            # get the point within the bin and huffman huffman_encoding_dict
            mask = diff <= bins[i]
            line_as_string = [str(i) for i in error[mask].astype(int)]
            freq = dict(Counter(line_as_string))
            freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
            node = make_tree(freq)
            huffman_encoding_dict = huffman_code_tree(node)
            huffman_encoding_list.append(huffman_encoding_dict)

        # the middle bins
        else:
            # get the point within the bin and huffman huffman_encoding_dict
            mask = diff > bins[i-1]
            new_error = error[mask]
            mask2 = diff[mask] <= bins[i]
            line_as_string = [str(i) for i in new_error[mask2].astype(int)]
            freq = dict(Counter(line_as_string))
            freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
            node = make_tree(freq)
            huffman_encoding_dict = huffman_code_tree(node)
            huffman_encoding_list.append(huffman_encoding_dict)

    # the last bin
    # get the point within the bin and huffman huffman_encoding_dict
    mask = diff > bins[-1]
    line_as_string = [str(i) for i in error[mask].astype(int)]
    freq = dict(Counter(line_as_string))
    freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
    node = make_tree(freq)
    huffman_encoding_dict = huffman_code_tree(node)
    huffman_encoding_list.append(huffman_encoding_dict)

    # create a error matrix that includes the boundary (used in encoding matrix)
    new_error = np.copy(image_as_array)
    new_error[1:-1,1:-1] = np.reshape(error,(510, 638))
    keep = new_error[0,0]
    new_error[0,:] = new_error[0,:] - keep
    new_error[-1,:] = new_error[-1,:] - 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[0,0] = keep
    # huffman_encoding_list = list(set(huffman_encoding_list))
    diff = np.reshape(diff,(510,638))

    return image_as_array, new_error, diff
```

%% Cell type:code id: tags:

``` python
def encoder(error, list_dic, diff, bins):
    """
    This function encode the matrix with huffman coding tables

    Input:
    error     (512, 640): a matrix with all the errors
    list_dic  (num_dic + 1,): a list of huffman coding table
    bins       (num_bins - 1,): a list of threshold to cut the bins

    Return:
    encoded   (512, 640): encoded matrix
    """
    returnable_encode = ""
    # copy the error matrix (including the boundary)
    encoded = np.copy(error).astype(int).astype(str).astype(object)
    #diff = np.reshape(diff,(510,638))
    # loop through all the pixel to encode
    for i in range(encoded.shape[0]):
        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:
                returnable_encode += list_dic[0][encoded[i][j]]
            elif diff[i-1][j-1] <= bins[0]:
                returnable_encode += list_dic[1][encoded[i][j]]
            elif diff[i-1][j-1] <= bins[1] and diff[i-1][j-1] > bins[0]:
                returnable_encode +=list_dic[2][encoded[i][j]]
            elif diff[i-1][j-1] <= bins[2] and diff[i-1][j-1] > bins[1]:
                returnable_encode +=list_dic[3][encoded[i][j]]
            else:
                returnable_encode += list_dic[4][encoded[i][j]]
    return returnable_encode
```

%% Cell type:code id: tags:

``` python
# def bitstring_to_bytes(s):
#     v = int(s, 2)
#     b = bytearray()
#     while v:
#         b.append(v & 0xff)
#         v >>= 8
#     return bytes(b[::-1])
def bitstring_to_bytes(input_string):
    int_array = []
    length_of_string = len(input_string)
    while length_of_string >= 8:
        int_array.append(int(input_string[:8],2))
        input_string = input_string[8:]
        length_of_string = len(input_string)
    if length_of_string > 0:
        zerobuffer = ""
        for _ in range(8-length_of_string):
            zerobuffer += "0"
        int_array.append(int(input_string+zerobuffer,2))
    return bytes(int_array)
```

%% Cell type:code id: tags:

``` python
def decoder(encoded_string, list_dic, bins, use_diff):
    """
    This function decodes the encoded_matrix.
    Input:
    A               (3 X 3): system of equation
    list_dic        (num_dic + 1,): a list of huffman coding table
    encoded_matrix  (512, 640): encoded matrix
    bins            (num_bins - 1,): a list of threshold to cut the bins

    Return:
    decode_matrix   (512, 640): decoded matrix
    """
    A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation
    # change the dictionary back to list
    # !!!!!WARNING!!!! has to change this part, everytime you change the number of bins
    the_keys0 = list(list_dic[0].keys())
    the_values0 = list(list_dic[0].values())

    the_keys1 = list(list_dic[1].keys())
    the_values1 = list(list_dic[1].values())

    the_keys2 = list(list_dic[2].keys())
    the_values2 = list(list_dic[2].values())

    the_keys3 = list(list_dic[3].keys())
    the_values3 = list(list_dic[3].values())

    the_keys4 = list(list_dic[4].keys())
    the_values4 = list(list_dic[4].values())

    #Matrix system of points that will be used to solve the least squares fitting hyperplane
    points = np.array([[-1,-1,1], [-1,0,1], [-1,1,1], [0,-1,1]])

    decode_matrix = np.zeros((512,640))
    # loop through all the element in the matrix
    for i in range(decode_matrix.shape[0]):
        for j in range(decode_matrix.shape[1]):
            # if it's the very first pixel on the image
            if i == 0 and j == 0:
                colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys0, the_values=the_values0)
                decode_matrix[i][j] = colorvalue

            # if it's on the boundary (any of the 4 edges)
            elif i == 0 or i == decode_matrix.shape[0]-1 or j == 0 or j == decode_matrix.shape[1]-1:
                colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys0, the_values=the_values0)
                decode_matrix[i][j] = colorvalue + decode_matrix[0][0]
            # if not the boundary
            else:
                # predict the image with the known pixel value
                z0 = decode_matrix[i-1][j-1]
                z1 = decode_matrix[i-1][j]
                z2 = decode_matrix[i-1][j+1]
                z3 = decode_matrix[i][j-1]
                y0 = int(-z0+z2-z3)
                y1 = int(z0+z1+z2)
                y2 = int(-z0-z1-z2-z3)
                y = np.vstack((y0,y1,y2))
                if use_diff:
                    difference = max(z0,z1,z2,z3) - min(z0,z1,z2,z3)
                else:

                    f, difference, rank, s = la.lstsq(points, [z0,z1,z2,z3], rcond=None)
                    difference = difference.astype(int)

                predict = np.round(np.round(np.linalg.solve(A,y)[-1][0],1))
                # add on the difference by searching the dictionary
                # !!!!!WARNING!!!! has to change this part, eveytime you change the number of bins
                if difference <= bins[0]:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys1, the_values=the_values1)
                    decode_matrix[i][j] = colorvalue + int(predict)
                elif difference <= bins[1] and difference > bins[0]:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys2, the_values=the_values2)
                    decode_matrix[i][j] = colorvalue + int(predict)
                elif difference <= bins[2] and difference > bins[1]:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys3, the_values=the_values3)
                    decode_matrix[i][j] = colorvalue + int(predict)
                else:
                    colorvalue, encoded_string = decode_string(encoded_string,the_keys=the_keys4, the_values=the_values4)
                    decode_matrix[i][j] = colorvalue + int(predict)

    return decode_matrix.astype(int)
```

%% Cell type:code id: tags:

``` python
def read_from_file(filename):
    with open(filename, 'rb') as file:
        return file.read()
```

%% Cell type:code id: tags:

``` python
scenes = file_extractor()
newnamesforlater = []
images = image_extractor(scenes)
list_dic, ogbins = make_dictionary(images[0:10], 4, False)
list_dic, ogbins = make_dictionary(images, 4, False)
file_size_ratios = []
np.save("first_dic.npy", list_dic)
for i in range(10):
for i in range(125,126):
    image, new_error, diff = huffman(images[i], 4, False)
    encoded_string1 = encoder(new_error, list_dic, diff, ogbins)
    # reconstruct_image = decoder(A, encoded_string, list_dic, bins, False)
    # print(np.allclose(image, reconstruct_image))
    inletters = bitstring_to_bytes(encoded_string1)
    if images[i][:-5] == ".tiff":
        newname = images[i][:-5]
    else:
        newname = images[i][:-4]
    newnamesforlater.append(newname + "_Compressed.txt")
    with open(newname + "_Compressed.txt", 'wb') as f:
        f.write(inletters)
    file_size_ratios.append((os.path.getsize(newname + "_Compressed.txt"))/os.path.getsize('images/1626032610_393963/1626032610_393963_0.tiff'))
```

%% Cell type:code id: tags:

``` python
print(np.mean(file_size_ratios))
```

%% Output

    0.3955120002069395
    0.4946477235897303

%% Cell type:code id: tags:

``` python
0.39535481750525336
```

%% Output

    0.39535481750525336

%% Cell type:markdown id: tags:

Tomorrow note: Make new thing so that it rounds better, can be used losslessly while maintaining the same dict. Currently: wildly off.

%% Cell type:markdown id: tags:

info@elphel.com
801.599.6216
pdf4eclipse
Don't use 6, the channel is broken

%% Cell type:code id: tags:

``` python
```

%% Cell type:code id: tags:

``` python
def bytes_to_bitstring(input_bytearray):
    end_string = ""
    int_array = [i for i in input_bytearray]
    for i, item in enumerate(int_array):
        end_string += (bin(item)[2:].zfill(8))
    return end_string
list_dic = np.load("first_dic.npy", allow_pickle="TRUE")


# ogbins = [12,60,180]
ogbins = [21,32,48]
for i,item in enumerate(newnamesforlater[0:10]):
    image, new_error, diff = huffman(images[i], 4, False)
ogbins = [30,70,141]
for i,item in enumerate(newnamesforlater):
    image, new_error, diff = huffman(images[125+i], 4, False)
    encoded_string2 = bytes_to_bitstring(read_from_file(item))
    reconstruct_image = decoder(encoded_string2, list_dic, ogbins, False)
    print(np.allclose(image, reconstruct_image))
```

%% Output

    True
    True
    True
    True
    True
    True
    True
    True
    True
    True

%% Cell type:code id: tags:

``` python
def check_bin_size(tiff_image_path_list, num_bins=4, difference = True):
    """
    This function is used to encode the error based on the difference
    and split the difference into different bins

    Input:
    tiff_image_path     (string): path to the tiff file
    num_bins            (int): number of bins

    Return:
    huffman_encoding_list  list    (num_bins + 1): a list of dictionary
    image_array            ndarray (512, 640): original image
    new_error              ndarray (512, 640): error that includes the boundary
    diff                   ndarray (510, 638): difference of min and max of the 4 neighbors
    boundary               ndarray (2300,): the boundary values after subtracting the very first pixel value
    predict                ndarray (325380,): the list of predicted values
    bins                   list    (num_bins - 1,): a list of threshold to cut the bins
    A                      ndarray (3 X 3): system of equation

    """
    all_bins = []
    for i, tiff_image_path in enumerate(tiff_image_path_list):
        # get the image_array, etc
        image_array, predict, diff= predict_pix(tiff_image_path, difference)
        image_array, predict, diff, error= predict_pix(tiff_image_path, difference)

        # calculate the number of points that will go in each bin
        data_points_per_bin = diff.size // num_bins

        # sort the difference and create the bins
        sorted_diff = np.sort(diff.copy())
        bins = [sorted_diff[i*data_points_per_bin] for i in range(1,num_bins)]
        all_bins.append(bins)
    return np.mean(all_bins,axis = 0)
    return np.mean(all_bins,axis = 0), np.min(all_bins,axis = 0), np.max(all_bins,axis=0)
```

%% Cell type:code id: tags:

``` python
print(check_bin_size(images))
```

%% Output

    [-13.07692308   0.          13.08097166]
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    /home/bryce/git/master/SameTableEncoder.ipynb Cell 19' in <cell line: 1>()
    ----> <a href='vscode-notebook-cell:/home/bryce/git/master/SameTableEncoder.ipynb#ch0000019?line=0'>1</a> print(check_bin_size(images))
    /home/bryce/git/master/SameTableEncoder.ipynb Cell 18' in check_bin_size(tiff_image_path_list, num_bins, difference)
         <a href='vscode-notebook-cell:/home/bryce/git/master/SameTableEncoder.ipynb#ch0000017?line=20'>21</a> all_bins = []
         <a href='vscode-notebook-cell:/home/bryce/git/master/SameTableEncoder.ipynb#ch0000017?line=21'>22</a> for i, tiff_image_path in enumerate(tiff_image_path_list):
         <a href='vscode-notebook-cell:/home/bryce/git/master/SameTableEncoder.ipynb#ch0000017?line=22'>23</a>     # get the image_array, etc
    ---> <a href='vscode-notebook-cell:/home/bryce/git/master/SameTableEncoder.ipynb#ch0000017?line=23'>24</a>     image_array, predict, diff, error= predict_pix(tiff_image_path, difference)
         <a href='vscode-notebook-cell:/home/bryce/git/master/SameTableEncoder.ipynb#ch0000017?line=25'>26</a>     # calculate the number of points that will go in each bin
         <a href='vscode-notebook-cell:/home/bryce/git/master/SameTableEncoder.ipynb#ch0000017?line=26'>27</a>     data_points_per_bin = diff.size // num_bins
    ValueError: not enough values to unpack (expected 4, got 3)

%% Cell type:code id: tags:

``` python
```
+25 −24
Original line number Diff line number Diff line
@@ -10,6 +10,9 @@ from collections import Counter
import numpy.linalg as la
from time import time

folder_name = "images"
outputlocation = ""

def file_extractor(dirname="images"):
    files = os.listdir(dirname)
    scenes = []
@@ -480,7 +483,6 @@ def read_from_file(filename):
    with open(filename, 'rb') as file:
        return file.read()


def bitstring_to_bytes(input_string):
    int_array = []
    length_of_string = len(input_string)
@@ -495,7 +497,6 @@ def bitstring_to_bytes(input_string):
        int_array.append(int(input_string+zerobuffer,2))
    return bytes(int_array)


def bytes_to_bitstring(input_bytearray):
    end_string = ""
    int_array = [i for i in input_bytearray]
@@ -503,33 +504,33 @@ def bytes_to_bitstring(input_bytearray):
        end_string += (bin(item)[2:].zfill(8))
    return end_string

starttime = time()
scenes = file_extractor()
# starttime = time()
scenes = file_extractor(folder_name)
newnamesforlater = []
images = image_extractor(scenes)
list_dic, ogbins = make_dictionary(images[0:10], 4, False)
# list_dic, bins = make_dictionary(images, 4, False)
file_size_ratios = []
np.save("first_dic.npy", list_dic)
for i in range(10):
    image, new_error, diff = huffman(images[i], 4, False)
    encoded_string1 = encoder(new_error, list_dic, diff, ogbins)
    # reconstruct_image = decoder(A, encoded_string, list_dic, bins, False)
    # print(np.allclose(image, reconstruct_image))
    inletters = bitstring_to_bytes(encoded_string1)
# np.save("first_dic.npy", list_dic)
for i in range(len(images)):
    # image, new_error, diff = huffman(images[i], 4, False)
    # encoded_string = encoder(new_error, list_dic, diff, bins)
    # inletters = bitstring_to_bytes(encoded_string)
    if images[i][:-5] == ".tiff":
        newname = images[i][:-5]
    else:
        newname = images[i][:-4]
    newnamesforlater.append(newname + "_Compressed.txt")
    with open(newname + "_Compressed.txt", 'wb') as f:
        f.write(inletters)

list_dic = np.load("first_dic.npy", allow_pickle="TRUE")

ogbins = [21,32,48]
for i,item in enumerate(newnamesforlater[0:10]):
    image, new_error, diff = huffman(images[i], 4, False)
    encoded_string2 = bytes_to_bitstring(read_from_file(item))
    reconstruct_image = decoder(encoded_string2, list_dic, ogbins, False)
    print(np.allclose(image, reconstruct_image))
print(time() - starttime)
 No newline at end of file
    # with open(newname + "_Compressed.txt", 'wb') as f:
    #     f.write(inletters)
    file_size_ratios.append((os.path.getsize(newname + "_Compressed.txt"))/os.path.getsize(images[i]))
# list_dic = np.load("first_dic.npy", allow_pickle="TRUE")

# for i,item in enumerate(newnamesforlater[0:10]):
#     image, new_error, diff = huffman(images[i], 4, False)
#     encoded_string2 = bytes_to_bitstring(read_from_file(item))
#     reconstruct_image = decoder(encoded_string2, list_dic, bins, False)
#     print(np.allclose(image, reconstruct_image))
print(np.mean(file_size_ratios))
print(np.max(file_size_ratios))
print(np.min(file_size_ratios))
print(np.argmax(file_size_ratios))
 No newline at end of file
+175 KiB (228 KiB)

File changed.

No diff preview for this file type.

Loading