Commit 007a74aa authored by Nathaniel Callens's avatar Nathaniel Callens

changes

parents 51df1348 bbb3dc00
{ {
"cells": [], "cells": [
{
"cell_type": "code",
"execution_count": 2,
"id": "8868bc30",
"metadata": {}, "metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from matplotlib import pyplot as plt\n",
"from itertools import product\n",
"import os\n",
"import sys\n",
"from PIL import Image\n",
"from scipy.optimize import minimize,linprog\n",
"import time\n",
"import seaborn as sns\n",
"from sklearn.neighbors import KernelDensity\n",
"import pandas as pd\n",
"from collections import Counter\n",
"import time"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "76317b02",
"metadata": {},
"outputs": [],
"source": [
"def file_extractor(dirname=\"images\"):\n",
" files = os.listdir(dirname)\n",
" scenes = []\n",
" for file in files:\n",
" scenes.append(os.path.join(dirname, file))\n",
" return scenes\n",
"\n",
"def image_extractor(scenes):\n",
" image_folder = []\n",
" for scene in scenes:\n",
" files = os.listdir(scene)\n",
" for file in files:\n",
" image_folder.append(os.path.join(scene, file))\n",
" images = []\n",
" for folder in image_folder:\n",
" ims = os.listdir(folder)\n",
" for im in ims:\n",
" if im[-4:] == \".jp4\" or im[-7:] == \"_6.tiff\":\n",
" continue\n",
" else:\n",
" images.append(os.path.join(folder, im))\n",
" return images #returns a list of file paths to .tiff files in the specified directory given in file_extractor\n",
"\n",
"def im_distribution(images, num):\n",
" \"\"\"\n",
" Function that extracts tiff files from specific cameras and returns a list of all\n",
" the tiff files corresponding to that camera. i.e. all pictures labeled \"_7.tiff\" or otherwise\n",
" specified camera numbers.\n",
" \n",
" Parameters:\n",
" images (list): list of all tiff files, regardless of classification. This is NOT a list of directories but\n",
" of specific tiff files that can be opened right away. This is the list that we iterate through and \n",
" divide.\n",
" \n",
" num (str): a string designation for the camera number that we want to extract i.e. \"14\" for double digits\n",
" of \"_1\" for single digits.\n",
" \n",
" Returns:\n",
" tiff (list): A list of tiff files that have the specified designation from num. They are the files extracted\n",
" from the 'images' list that correspond to the given num.\n",
" \"\"\"\n",
" tiff = []\n",
" for im in images:\n",
" if im[-7:-6] == num:\n",
" tiff.append(im)\n",
" return tiff"
]
},
{
"cell_type": "code",
"execution_count": 62,
"id": "be1ff8a1",
"metadata": {},
"outputs": [],
"source": [
"def plot_hist(tiff_list):\n",
" \"\"\"\n",
" This function is the leftovers from the first attempt to plot histograms.\n",
" As it stands it needs some work in order to function again. We will\n",
" fix this later. 1/25/22\n",
" \"\"\"\n",
" \n",
" image = tiff_list\n",
" image = Image.open(image) #Open the image and read it as an Image object\n",
" image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data\n",
" image = image.astype(int)\n",
" A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation\n",
" z0 = image[0:-2,0:-2] # get all the first pixel for the entire image\n",
" z1 = image[0:-2,1:-1] # get all the second pixel for the entire image\n",
" z2 = image[0:-2,2::] # get all the third pixel for the entire image\n",
" z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image\n",
" # calculate the out put of the system of equation\n",
" y0 = np.ravel(-z0+z2-z3)\n",
" y1 = np.ravel(z0+z1+z2)\n",
" y2 = np.ravel(-z0-z1-z2-z3)\n",
" y = np.vstack((y0,y1,y2))\n",
" # use numpy solver to solve the system of equations all at once\n",
" predict = np.floor(np.linalg.solve(A,y)[-1])\n",
" # flatten the neighbor pixlels and stack them together\n",
" z0 = np.ravel(z0)\n",
" z1 = np.ravel(z1)\n",
" z2 = np.ravel(z2)\n",
" z3 = np.ravel(z3)\n",
" neighbor = np.vstack((z0,z1,z2,z3)).T\n",
" # calculate the difference\n",
" diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1)\n",
" \n",
" # flatten the image to a vector\n",
" image = np.ravel(image[1:-1,1:-1])\n",
" error = image-predict\n",
" \n",
" return image, predict, diff, error, A"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "8483903e",
"metadata": {},
"outputs": [],
"source": [
"class NodeTree(object):\n",
" def __init__(self, left=None, right=None):\n",
" self.left = left\n",
" self.right = right\n",
"\n",
" def children(self):\n",
" return self.left, self.right\n",
"\n",
" def __str__(self):\n",
" return self.left, self.right\n",
"\n",
"\n",
"def huffman_code_tree(node, binString=''):\n",
" '''\n",
" Function to find Huffman Code\n",
" '''\n",
" if type(node) is str:\n",
" return {node: binString}\n",
" (l, r) = node.children()\n",
" d = dict()\n",
" d.update(huffman_code_tree(l, binString + '0'))\n",
" d.update(huffman_code_tree(r, binString + '1'))\n",
" return d\n",
"\n",
"\n",
"def make_tree(nodes):\n",
" '''\n",
" Function to make tree\n",
" :param nodes: Nodes\n",
" :return: Root of the tree\n",
" '''\n",
" while len(nodes) > 1:\n",
" (key1, c1) = nodes[-1]\n",
" (key2, c2) = nodes[-2]\n",
" nodes = nodes[:-2]\n",
" node = NodeTree(key1, key2)\n",
" nodes.append((node, c1 + c2))\n",
" nodes = sorted(nodes, key=lambda x: x[1], reverse=True)\n",
" return nodes[0][0]"
]
},
{
"cell_type": "code",
"execution_count": 86,
"id": "64a3a193",
"metadata": {},
"outputs": [],
"source": [
"def reconstruct(error, A):\n",
" \"\"\"\n",
" Function that reconstructs the original image\n",
" from the error matrix and using the predictive\n",
" algorithm developed in the encoding.\n",
" \n",
" Parameters:\n",
" error (array): matrix of errors computed in encoding. Same \n",
" shape as the original image (512, 640) in this case\n",
" A (array): Matrix used for the system of equations to create predictions\n",
" Returns: \n",
" image (array): The reconstructed image\n",
" \"\"\"\n",
" new_e = error.copy()\n",
" rows, columns = new_e.shape\n",
"\n",
" for r in range(1, rows-1):\n",
" for c in range(1, columns-1):\n",
" z0, z1, z2, z3 = new_e[r-1][c-1], new_e[r-1][c], new_e[r-1][c+1], new_e[r][c-1]\n",
" y = np.vstack((-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3))\n",
"\n",
" '''if r == 345 and c == 421:\n",
" print(new_e[r][c])\n",
" print(np.linalg.solve(A,y)[-1])\n",
" print(new_e[r][c] + np.linalg.solve(A,y)[-1])\n",
" print(np.ceil(new_e[r][c]) + np.floor(np.linalg.solve(A,y)[-1]))\n",
" \n",
" y0 = np.ravel(-z0+z2-z3)\n",
" y1 = np.ravel(z0+z1+z2)\n",
" y2 = np.ravel(-z0-z1-z2-z3)\n",
" y = np.vstack((y0,y1,y2))\n",
" # use numpy solver to solve the system of equations all at once\n",
" predict = np.floor(np.linalg.solve(A,y)[-1])\n",
" # flatten the neighbor pixlels and stack them together\n",
" z0 = np.ravel(z0)\n",
" z1 = np.ravel(z1)\n",
" z2 = np.ravel(z2)\n",
" z3 = np.ravel(z3)\n",
" neighbor = np.vstack((z0,z1,z2,z3)).T'''\n",
" \n",
" #Real solution that works, DO NOT DELETE\n",
" print(new_e[r][c]+ np.floor(np.linalg.solve(A,y)[-1]))\n",
" new_e[r][c] = new_e[r][c] + np.floor(np.linalg.solve(A,y)[-1])\n",
" print(new_e[r][c])\n",
" #new_e[r][c] = np.ceil(new_e[r][c]) + np.floor(np.linalg.solve(A,y)[-1])\n",
" \n",
" return new_e"
]
},
{
"cell_type": "code",
"execution_count": 132,
"id": "91879f19",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"257\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"-154.0\n",
"197.0\n"
]
}
],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"origin, predict, diff, error, A = plot_hist(images[0])\n",
"image = Image.open(images[0]) #Open the image and read it as an Image object\n",
"image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data\n",
"image = image.astype(int)\n",
"print(len(set(list(error))))\n",
"plt.hist(error,100)\n",
"plt.show()\n",
"print(min(error))\n",
"print(max(error))"
]
},
{
"cell_type": "code",
"execution_count": 145,
"id": "207b0bd2",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"458\n",
"{'61': '000000000', '87': '000000001000', '140': '000000001001000', '142': '000000001001001', '250': '000000001001010', '179': '000000001001011', '151': '000000001001100', '207': '0000000010011010', '141': '0000000010011011', '101': '00000000100111', '77': '00000000101', '69': '0000000011', '53': '00000001', '44': '0000001', '33': '000001', '20': '00001', '19': '00010', '18': '00011', '43': '0010000', '75': '00100010000', '84': '001000100010', '104': '00100010001100', '122': '001000100011010', '120': '001000100011011', '94': '0010001000111', '83': '001000100100', '153': '001000100101000', '130': '001000100101001', '143': '001000100101010', '127': '001000100101011', '93': '0010001001011', '115': '0010001001100000', '375': '0010001001100001', '366': '0010001001100010', '373': '0010001001100011', '377': '0010001001100100', '314': '0010001001100101', '402': '0010001001100110', '367': '0010001001100111', '133': '0010001001101000', '210': '0010001001101001', '334': '0010001001101010', '298': '0010001001101011', '176': '0010001001101100', '332': '0010001001101101', '335': '0010001001101110', '362': '0010001001101111', '371': '0010001001110000', '333': '0010001001110001', '251': '0010001001110010', '226': '0010001001110011', '247': '0010001001110100', '315': '0010001001110101', '304': '0010001001110110', '258': '0010001001110111', '306': '0010001001111000', '261': '0010001001111001', '289': '0010001001111010', '372': '0010001001111011', '239': '0010001001111100', '252': '0010001001111101', '224': '0010001001111110', '205': '0010001001111111', '60': '001000101', '52': '00100011', '32': '001001', '17': '00101', '51': '00110000', '139': '001100010000000', '149': '001100010000001', '132': '001100010000010', '154': '001100010000011', '163': '001100010000100', '162': '001100010000101', '281': '001100010000110', '346': '001100010000111', '384': '00110001000100000', '331': '00110001000100001', '383': '00110001000100010', '155': '00110001000100011', '354': '00110001000100100', '456': '00110001000100101', '229': '00110001000100110', '388': '00110001000100111', '294': '00110001000101000', '413': '00110001000101001', '211': '00110001000101010', '292': '00110001000101011', '376': '00110001000101100', '382': '00110001000101101', '387': '00110001000101110', '309': '00110001000101111', '158': '001100010001100', '159': '001100010001101', '313': '00110001000111000', '126': '00110001000111001', '327': '00110001000111010', '319': '00110001000111011', '302': '00110001000111100', '330': '00110001000111101', '385': '00110001000111110', '573': '00110001000111111', '76': '00110001001', '214': '0011000101000000', '259': '0011000101000001', '243': '0011000101000010', '255': '0011000101000011', '410': '0011000101000100', '399': '0011000101000101', '134': '0011000101000110', '270': '0011000101000111', '216': '0011000101001000', '236': '0011000101001001', '213': '0011000101001010', '196': '0011000101001011', '290': '0011000101001100', '231': '0011000101001101', '128': '0011000101001110', '193': '0011000101001111', '169': '0011000101010000', '178': '0011000101010001', '328': '0011000101010010', '160': '0011000101010011', '394': '0011000101010100', '336': '0011000101010101', '204': '0011000101010110', '227': '0011000101010111', '200': '0011000101011000', '212': '0011000101011001', '352': '0011000101011010', '147': '0011000101011011', '342': '0011000101011100', '308': '0011000101011101', '329': '0011000101011110', '379': '0011000101011111', '221': '00110001011000000', '267': '00110001011000001', '269': '001100010110000100', '177': '001100010110000101', '220': '001100010110000110', '202': '001100010110000111', '225': '00110001011000100', '185': '00110001011000101', '170': '00110001011000110', '198': '00110001011000111', '429': '001100010110010000', '206': '001100010110010001', '426': '001100010110010010', '438': '001100010110010011', '403': '001100010110010100', '424': '001100010110010101', '299': '001100010110010110', '325': '001100010110010111', '237': '001100010110011000', '152': '001100010110011001', '145': '001100010110011010', '230': '001100010110011011', '411': '001100010110011100', '286': '001100010110011101', '374': '001100010110011110', '469': '001100010110011111', '293': '00110001011010000', '406': '00110001011010001', '407': '00110001011010010', '421': '00110001011010011', '301': '00110001011010100', '275': '00110001011010101', '423': '00110001011010110', '395': '00110001011010111', '244': '00110001011011000', '337': '00110001011011001', '300': '00110001011011010', '233': '00110001011011011', '322': '00110001011011100', '400': '00110001011011101', '253': '00110001011011110', '361': '00110001011011111', '297': '001100010111000000', '390': '001100010111000001', '444': '001100010111000010', '242': '001100010111000011', '606': '001100010111000100', '498': '001100010111000101', '397': '001100010111000110', '532': '001100010111000111', '209': '001100010111001000', '283': '001100010111001001', '430': '001100010111001010', '351': '001100010111001011', '539': '001100010111001100', '530': '001100010111001101', '256': '001100010111001110', '491': '001100010111001111', '511': '001100010111010000', '570': '001100010111010001', '559': '001100010111010010', '478': '001100010111010011', '359': '001100010111010100', '22554': '001100010111010101', '512': '001100010111010110', '503': '001100010111010111', '474': '001100010111011000', '489': '001100010111011001', '404': '001100010111011010', '380': '001100010111011011', '519': '001100010111011100', '568': '001100010111011101', '515': '001100010111011110', '543': '001100010111011111', '439': '001100010111100000', '418': '001100010111100001', '419': '001100010111100010', '425': '001100010111100011', '454': '001100010111100100', '228': '001100010111100101', '447': '001100010111100110', '452': '001100010111100111', '414': '001100010111101000', '435': '001100010111101001', '416': '001100010111101010', '345': '001100010111101011', '401': '001100010111101100', '440': '001100010111101101', '409': '001100010111101110', '350': '001100010111101111', '494': '001100010111110000', '482': '001100010111110001', '502': '001100010111110010', '393': '001100010111110011', '422': '001100010111110100', '370': '001100010111110101', '461': '001100010111110110', '369': '001100010111110111', '398': '001100010111111000', '445': '001100010111111001', '203': '001100010111111010', '249': '001100010111111011', '405': '001100010111111100', '486': '001100010111111101', '467': '001100010111111110', '470': '001100010111111111', '68': '0011000110', '74': '00110001110', '91': '0011000111100', '114': '001100011110100', '307': '001100011110101', '199': '001100011110110', '110': '001100011110111', '89': '0011000111110', '109': '00110001111110', '105': '001100011111110', '150': '0011000111111110', '129': '0011000111111111', '42': '0011001', '31': '001101', '16': '00111', '15': '01000', '67': '0100100000', '66': '0100100001', '59': '010010001', '50': '01001001', '41': '0100101', '30': '010011', '14': '01010', '13': '01011', '12': '01100', '29': '011010', '49': '01101100', '73': '01101101000', '82': '011011010010', '88': '0110110100110', '90': '0110110100111', '264': '0110110101000000', '272': '0110110101000001', '181': '0110110101000010', '218': '0110110101000011', '368': '0110110101000100', '347': '0110110101000101', '186': '0110110101000110', '248': '0110110101000111', '365': '0110110101001000', '187': '0110110101001001', '165': '0110110101001010', '164': '0110110101001011', '305': '0110110101001100', '161': '0110110101001101', '271': '0110110101001110', '340': '0110110101001111', '386': '0110110101010000', '280': '0110110101010001', '112': '0110110101010010', '137': '0110110101010011', '100': '01101101010101', '326': '0110110101011000', '277': '0110110101011001', '288': '0110110101011010', '316': '0110110101011011', '148': '0110110101011100', '287': '0110110101011101', '131': '0110110101011110', '183': '0110110101011111', '81': '011011010110', '188': '011011010111000', '125': '011011010111001', '171': '0110110101110100', '166': '0110110101110101', '167': '011011010111011', '116': '011011010111100', '174': '011011010111101', '108': '011011010111110', '107': '011011010111111', '58': '011011011', '40': '0110111', '11': '01110', '10': '01111', '28': '100000', '39': '1000010', '57': '100001100', '65': '1000011010', '72': '10000110110', '70': '10000110111', '48': '10000111', '9': '10001', '7': '10010', '8': '10011', '27': '101000', '38': '1010010', '47': '10100110', '63': '1010011100', '71': '10100111010', '79': '101001110110', '97': '10100111011100', '103': '10100111011101', '96': '10100111011110', '138': '10100111011111000', '146': '10100111011111001', '282': '10100111011111010', '222': '10100111011111011', '118': '101001110111111', '56': '101001111', '6': '10101', '5': '10110', '0': '101110', '26': '101111', '3': '11000', '2': '11001', '1': '11010', '4': '11011', '25': '111000', '37': '1110010', '64': '1110011000', '119': '11100110010000000', '349': '11100110010000001', '364': '11100110010000010', '392': '11100110010000011', '358': '11100110010000100', '378': '11100110010000101', '197': '11100110010000110', '279': '11100110010000111', '323': '11100110010001000', '318': '11100110010001001', '360': '11100110010001010', '436': '11100110010001011', '217': '11100110010001100', '124': '11100110010001101', '311': '11100110010001110', '324': '11100110010001111', '274': '11100110010010000', '278': '11100110010010001', '310': '11100110010010010', '296': '11100110010010011', '353': '11100110010010100', '357': '11100110010010101', '262': '11100110010010110', '223': '11100110010010111', '303': '11100110010011000', '284': '11100110010011001', '396': '11100110010011010', '338': '11100110010011011', '135': '11100110010011100', '355': '11100110010011101', '234': '11100110010011110', '441': '11100110010011111', '195': '1110011001010000', '320': '1110011001010001', '257': '11100110010100100', '215': '11100110010100101', '254': '11100110010100110', '263': '11100110010100111', '157': '1110011001010100', '285': '1110011001010101', '172': '1110011001010110', '192': '1110011001010111', '381': '11100110010110000', '389': '11100110010110001', '321': '11100110010110010', '189': '11100110010110011', '415': '11100110010110100', '190': '11100110010110101', '232': '11100110010110110', '245': '11100110010110111', '180': '11100110010111000', '235': '11100110010111001', '273': '11100110010111010', '317': '11100110010111011', '240': '11100110010111100', '219': '11100110010111101', '182': '11100110010111110', '246': '11100110010111111', '113': '1110011001100000', '276': '1110011001100001', '265': '1110011001100010', '175': '1110011001100011', '121': '1110011001100100', '123': '1110011001100101', '144': '1110011001100110', '156': '1110011001100111', '184': '1110011001101000', '344': '1110011001101001', '266': '1110011001101010', '173': '1110011001101011', '348': '1110011001101100', '268': '1110011001101101', '363': '1110011001101110', '312': '1110011001101111', '80': '111001100111', '55': '111001101', '46': '11100111', '24': '111010', '36': '1110110', '54': '111011100', '62': '1110111010', '92': '11101110110000', '98': '11101110110001', '86': '1110111011001', '95': '11101110110100', '99': '11101110110101', '106': '111011101101100', '117': '111011101101101', '136': '1110111011011100', '241': '1110111011011101', '102': '111011101101111', '85': '1110111011100', '201': '1110111011101000', '238': '1110111011101001', '191': '1110111011101010', '208': '1110111011101011', '343': '1110111011101100', '111': '1110111011101101', '168': '1110111011101110', '339': '1110111011101111', '78': '111011101111', '45': '11101111', '23': '111100', '35': '1111010', '34': '1111011', '22': '111110', '21': '111111'}\n"
]
}
],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"start = time.time()\n",
"origin, predict, diff, error, A = plot_hist(images[0])\n",
"image = Image.open(images[0]) #Open the image and read it as an Image object\n",
"image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data\n",
"image = image.astype(int)\n",
"new_error = np.copy(image)\n",
"new_error[1:-1,1:-1] = np.reshape(error,(510, 638))\n",
"keep = new_error[0,0]\n",
"new_error[0,:] = new_error[0,:] - keep\n",
"new_error[-1,:] = new_error[-1,:] - keep\n",
"new_error[1:-1,0] = new_error[1:-1,0] - keep\n",
"new_error[1:-1,-1] = new_error[1:-1,-1] - keep\n",
"new_error[0,0] = keep\n",
"new_error = np.ravel(new_error)\n",
"plt.hist(new_error[1:],bins=100)\n",
"plt.show()\n",
"ab_error = np.abs(new_error)\n",
"string = [str(i) for i in ab_error]\n",
"#string = [str(i) for i in new_error]\n",
"#string = [str(i) for i in np.arange(0,5)] + [str(i) for i in np.arange(0,5)] + [str(i) for i in np.arange(0,2)]*2\n",
"freq = dict(Counter(string))\n",
"#print(freq)\n",
"freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)\n",
"node = make_tree(freq)\n",
"encoding = huffman_code_tree(node)\n",
"#encoded = [\"1\"+encoding[str(-i)] if i < 0 else \"0\"+encoding[str(i)] for i in error]\n",
"#print(time.time()-start)\n",
"print(len(encoding))\n",
"print(encoding)"
]
},
{
"cell_type": "code",
"execution_count": 154,
"id": "14075c94",
"metadata": {},
"outputs": [],
"source": [
"def compress_rate(original, error, encoding):\n",
" original = original.reshape(-1)\n",
" error = error.reshape(-1)\n",
" o_len = 0\n",
" c_len = 0\n",
" for i in range(0, len(original)):\n",
" o_len += len(bin(original[i])[2:])\n",
" c_len += len(encoding[str(abs(error[i]))])\n",
" c_len += 1\n",
" \n",
" return c_len/o_len"
]
},
{
"cell_type": "code",
"execution_count": 155,
"id": "b93c068b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.4473590087890625"
]
},
"execution_count": 155,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"compress_rate(image,new_error,encoding)"
]
},
{
"cell_type": "code",
"execution_count": 140,
"id": "a8dc8674",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 140,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"int('0100',2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "992dd8bb",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 5 "nbformat_minor": 5
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -343,7 +343,7 @@ ...@@ -343,7 +343,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.8.11" "version": "3.9.1"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
#
# Compression application using adaptive arithmetic coding
#
# Usage: python adaptive-arithmetic-compress.py InputFile OutputFile
# Then use the corresponding adaptive-arithmetic-decompress.py application to recreate the original input file.
# Note that the application starts with a flat frequency table of 257 symbols (all set to a frequency of 1),
# and updates it after each byte encoded. The corresponding decompressor program also starts with a flat
# frequency table and updates it after each byte decoded. It is by design that the compressor and
# decompressor have synchronized states, so that the data can be decompressed properly.
#
# Copyright (c) Project Nayuki
#
# https://www.nayuki.io/page/reference-arithmetic-coding
# https://github.com/nayuki/Reference-arithmetic-coding
#
import sys
import arithmeticcoding
python3 = sys.version_info.major >= 3
# Command line main application function.
def main(args):
# Handle command line arguments
if len(args) != 2:
sys.exit("Usage: python adaptive-arithmetic-compress.py InputFile OutputFile")
inputfile = args[0]
outputfile = args[1]
# Perform file compression
with open(inputfile, "rb") as inp:
bitout = arithmeticcoding.BitOutputStream(open(outputfile, "wb"))
try:
compress(inp, bitout)
finally:
bitout.close()
def compress(inp, bitout):
initfreqs = arithmeticcoding.FlatFrequencyTable(257)
freqs = arithmeticcoding.SimpleFrequencyTable(initfreqs)
enc = arithmeticcoding.ArithmeticEncoder(bitout)
while True:
# Read and encode one byte
symbol = inp.read(1)
if len(symbol) == 0:
break
symbol = symbol[0] if python3 else ord(symbol)
enc.write(freqs, symbol)
freqs.increment(symbol)
enc.write(freqs, 256) # EOF
enc.finish() # Flush remaining code bits
# Main launcher
if __name__ == "__main__":
main(sys.argv[1 : ])
# Example implementation of simple arithmetic coding in Python (2.7+).
#
# USAGE
#
# python -i arithmetic.py
# >>> m = {'a': 1, 'b': 1, 'c': 1}
# >>> model = dirichlet(m)
# >>> encode(model, "aabbaacc")
# '00011110011110010'
#
# NOTES
#
# This implementation has many shortcomings, e.g.,
# - There are several inefficient tests, loops, and conversions
# - There are a few places where code is uncessarily duplicated
# - It does not output the coded message as a stream
# - It can only code short messages due to machine precision
# - The is no defensive coding against errors (e.g., out-of-model symbols)
# - I've not implemented a decoder!
#
# The aim was to make the implementation here as close as possible to
# the algorithm described in lectures while giving some extra detail about
# routines such as finding extensions to binary intervals.
#
# For a more sophisticated implementation, please refer to:
#
# "Arithmetic Coding for Data Compression"
# I. H. Witten, R. M. Neal, and J. G. Cleary
# Communications of the ACM, Col. 30 (6), 1987
#
# AUTHOR: Mark Reid
# CREATED: 2014-09-30
def encode(G, stream):
'''
Arithmetically encodes the given stream using the guesser function G
which returns probabilities over symbols P(x|xs) given a sequence xs.
'''
u, v = 0.0, 1.0 # The interval [u, v) for the message
xs, bs = "", "" # The message xs, and binary code bs
p = G(xs) # Compute the initial distribution over symbols
# Iterate through stream, repeatedly finding the longest binary code
# that surrounds the interval for the message so far
for x in stream:
# Record the new symbol
xs += x
# Find the interval for the message so far
F_lo, F_hi = cdf_interval(p, x)
u, v = u + (v-u)*F_lo, u + (v-u)*F_hi
# Find a binary code whose interval surrounds [u,v)
bs = extend_around(bs, u, v)
# Update the symbol probabilities
p = G(xs)
# Stream finished so find shortest extension of the code that sits inside
# the top half of [u, v)
bs = extend_inside(bs, u + (v-u)/2, v)
return bs
##############################################################################
# Models
def dirichlet(m):
'''
Returns a Dirichlet model (as a function) for probabilities with
prior counts given by the symbol to count dictionary m.
Probabilities returned by the returned functions are (symbol, prob)
dictionaries.
'''
# Build a function that returns P(x|xs) based on the priors in m
# and the counts of the symbols in xs
def p(xs):
counts = m.copy()
for x in xs:
counts[x] += 1
total = sum(counts.values())
return { a: float(c)/total for a, c in counts.items() }
# Return the constructed function
return p
##############################################################################
# Interval methods
def cdf_interval(p, a):
'''
Compute the cumulative distribution interval [F(a'), F(a)) for the
probabilities p (represented as a (symbol,prob) dict) where
F(a) = P(x <= a) and a' is the symbol preceeding a.
'''
F_lo, F_hi = 0, 0
A = sorted(p)
for x in A:
F_lo, F_hi = F_hi, F_hi + p[x]
if x == a:
break
return F_lo, F_hi
def binary_interval(bs):
'''
Returns an interval [n, m) for n and m integers, and denominator d
representing the interval [n/d, m/d) for the binary string bs.
'''
n, d = to_rational(bs)
return n, n + 1, d
def to_rational(bs):
'''Return numerator and denominator for ratio of 0.bs.'''
n = 0
for b in bs:
n *= 2
n += int(b)
return n, 2**len(bs)
def around(bs, u, v):
'''Tests whether [0.bs, 0.bs111...) contains [u, v).'''
n, m, d = binary_interval(bs)
return (n <= u*d) and (v*d <= m)
def extend_around(bs, u, v):
'''Find the longest extension of the given binary string so its interval
wraps around the interval [u, v).'''
contained = True
while contained:
if around(bs + "0", u, v):
bs += "0"
elif around(bs + "1", u, v):
bs += "1"
else:
contained = False
return bs
def inside(bs, u, v):
'''Tests whether [0.bs, 0.bs111...) is contained by [u, v).'''
n, m, d = binary_interval(bs)
return (u*d <= n) and (m <= v*d)
def extend_inside(bs, u, v):
'''Find the shortest extension of the given binary string so its interval
sits inside the interval [u, v).'''
while not inside(bs, u, v):
# Test whether gap between binary interval and [u,v) is bigger at the
# bottom than at the top
n, m, d = binary_interval(bs)
if u*d - n > m - v*d:
bs += "1" # If so, move bottom up by halving
else:
bs += "0" # If not, move top down by halving
return bs
#
# Reference arithmetic coding
# Copyright (c) Project Nayuki
#
# https://www.nayuki.io/page/reference-arithmetic-coding
# https://github.com/nayuki/Reference-arithmetic-coding
#
import sys
python3 = sys.version_info.major >= 3
# ---- Arithmetic coding core classes ----
# Provides the state and behaviors that arithmetic coding encoders and decoders share.
class ArithmeticCoderBase(object):
# Number of bits for 'low' and 'high'. Configurable and must be at least 1.
STATE_SIZE = 32
# Maximum range during coding (trivial), i.e. 1000...000.
MAX_RANGE = 1 << STATE_SIZE
# Minimum range during coding (non-trivial), i.e. 010...010.
MIN_RANGE = (MAX_RANGE >> 2) + 2
# Maximum allowed total frequency at all times during coding.
MAX_TOTAL = MIN_RANGE
# Mask of STATE_SIZE ones, i.e. 111...111.
MASK = MAX_RANGE - 1
# Mask of the top bit at width STATE_SIZE, i.e. 100...000.
TOP_MASK = MAX_RANGE >> 1
# Mask of the second highest bit at width STATE_SIZE, i.e. 010...000.
SECOND_MASK = TOP_MASK >> 1
# Constructs an arithmetic coder, which initializes the code range.
def __init__(self):
# Low end of this arithmetic coder's current range. Conceptually has an infinite number of trailing 0s.
self.low = 0
# High end of this arithmetic coder's current range. Conceptually has an infinite number of trailing 1s.
self.high = ArithmeticCoderBase.MASK
# Updates the code range (low and high) of this arithmetic coder as a result
# of processing the given symbol with the given frequency table.
# Invariants that are true before and after encoding/decoding each symbol:
# - 0 <= low <= code <= high < 2^STATE_SIZE. ('code' exists only in the decoder.)
# Therefore these variables are unsigned integers of STATE_SIZE bits.
# - (low < 1/2 * 2^STATE_SIZE) && (high >= 1/2 * 2^STATE_SIZE).
# In other words, they are in different halves of the full range.
# - (low < 1/4 * 2^STATE_SIZE) || (high >= 3/4 * 2^STATE_SIZE).
# In other words, they are not both in the middle two quarters.
# - Let range = high - low + 1, then MAX_RANGE/4 < MIN_RANGE <= range
# <= MAX_RANGE = 2^STATE_SIZE. These invariants for 'range' essentially
# dictate the maximum total that the incoming frequency table can have.
def update(self, freqs, symbol):
# State check
low = self.low
high = self.high
if low >= high or (low & ArithmeticCoderBase.MASK) != low or (high & ArithmeticCoderBase.MASK) != high:
raise AssertionError("Low or high out of range")
range = high - low + 1
if not (ArithmeticCoderBase.MIN_RANGE <= range <= ArithmeticCoderBase.MAX_RANGE):
raise AssertionError("Range out of range")
# Frequency table values check
total = freqs.get_total()
symlow = freqs.get_low(symbol)
symhigh = freqs.get_high(symbol)
if symlow == symhigh:
raise ValueError("Symbol has zero frequency")
if total > ArithmeticCoderBase.MAX_TOTAL:
raise ValueError("Cannot code symbol because total is too large")
# Update range
newlow = low + symlow * range // total
newhigh = low + symhigh * range // total - 1
self.low = newlow
self.high = newhigh
# While the highest bits are equal
while ((self.low ^ self.high) & ArithmeticCoderBase.TOP_MASK) == 0:
self.shift()
self.low = (self.low << 1) & ArithmeticCoderBase.MASK
self.high = ((self.high << 1) & ArithmeticCoderBase.MASK) | 1
# While the second highest bit of low is 1 and the second highest bit of high is 0
while (self.low & ~self.high & ArithmeticCoderBase.SECOND_MASK) != 0:
self.underflow()
self.low = (self.low << 1) & (ArithmeticCoderBase.MASK >> 1)
self.high = ((self.high << 1) & (ArithmeticCoderBase.MASK >> 1)) | ArithmeticCoderBase.TOP_MASK | 1
# Called to handle the situation when the top bit of 'low' and 'high' are equal.
def shift(self):
raise NotImplementedError()
# Called to handle the situation when low=01(...) and high=10(...).
def underflow(self):
raise NotImplementedError()
# Encodes symbols and writes to an arithmetic-coded bit stream.
class ArithmeticEncoder(ArithmeticCoderBase):
# Constructs an arithmetic coding encoder based on the given bit output stream.
def __init__(self, bitout):
super(ArithmeticEncoder, self).__init__()
# The underlying bit output stream.
self.output = bitout
# Number of saved underflow bits. This value can grow without bound.
self.num_underflow = 0
# Encodes the given symbol based on the given frequency table.
# This updates this arithmetic coder's state and may write out some bits.
def write(self, freqs, symbol):
if not isinstance(freqs, CheckedFrequencyTable):
freqs = CheckedFrequencyTable(freqs)
self.update(freqs, symbol)
# Terminates the arithmetic coding by flushing any buffered bits, so that the output can be decoded properly.
# It is important that this method must be called at the end of the each encoding process.
# Note that this method merely writes data to the underlying output stream but does not close it.
def finish(self):
self.output.write(1)
def shift(self):
bit = self.low >> (ArithmeticCoderBase.STATE_SIZE - 1)
self.output.write(bit)
# Write out the saved underflow bits
for i in range(self.num_underflow):
self.output.write(bit ^ 1)
self.num_underflow = 0
def underflow(self):
self.num_underflow += 1
# Reads from an arithmetic-coded bit stream and decodes symbols.
class ArithmeticDecoder(ArithmeticCoderBase):
# Constructs an arithmetic coding decoder based on the
# given bit input stream, and fills the code bits.
def __init__(self, bitin):
super(ArithmeticDecoder, self).__init__()
# The underlying bit input stream.
self.input = bitin
# The current raw code bits being buffered, which is always in the range [low, high].
self.code = 0
for i in range(ArithmeticCoderBase.STATE_SIZE):
self.code = self.code << 1 | self.read_code_bit()
# Decodes the next symbol based on the given frequency table and returns it.
# Also updates this arithmetic coder's state and may read in some bits.
def read(self, freqs):
if not isinstance(freqs, CheckedFrequencyTable):
freqs = CheckedFrequencyTable(freqs)
# Translate from coding range scale to frequency table scale
total = freqs.get_total()
if total > ArithmeticCoderBase.MAX_TOTAL:
raise ValueError("Cannot decode symbol because total is too large")
range = self.high - self.low + 1
offset = self.code - self.low
value = ((offset + 1) * total - 1) // range
assert value * range // total <= offset
assert 0 <= value < total
# A kind of binary search. Find highest symbol such that freqs.get_low(symbol) <= value.
start = 0
end = freqs.get_symbol_limit()
while end - start > 1:
middle = (start + end) >> 1
if freqs.get_low(middle) > value:
end = middle
else:
start = middle
assert start + 1 == end
symbol = start
assert freqs.get_low(symbol) * range // total <= offset < freqs.get_high(symbol) * range // total
self.update(freqs, symbol)
if not (self.low <= self.code <= self.high):
raise AssertionError("Code out of range")
return symbol
def shift(self):
self.code = ((self.code << 1) & ArithmeticCoderBase.MASK) | self.read_code_bit()
def underflow(self):
self.code = (self.code & ArithmeticCoderBase.TOP_MASK) | ((self.code << 1) & (ArithmeticCoderBase.MASK >> 1)) | self.read_code_bit()
# Returns the next bit (0 or 1) from the input stream. The end
# of stream is treated as an infinite number of trailing zeros.
def read_code_bit(self):
temp = self.input.read()
if temp == -1:
temp = 0
return temp
# ---- Frequency table classes ----
# A table of symbol frequencies. The table holds data for symbols numbered from 0
# to get_symbol_limit()-1. Each symbol has a frequency, which is a non-negative integer.
# Frequency table objects are primarily used for getting cumulative symbol
# frequencies. These objects can be mutable depending on the implementation.
class FrequencyTable(object):
# Returns the number of symbols in this frequency table, which is a positive number.
def get_symbol_limit(self):
raise NotImplementedError()
# Returns the frequency of the given symbol. The returned value is at least 0.
def get(self, symbol):
raise NotImplementedError()
# Sets the frequency of the given symbol to the given value.
# The frequency value must be at least 0.
def set(self, symbol, freq):
raise NotImplementedError()
# Increments the frequency of the given symbol.
def increment(self, symbol):
raise NotImplementedError()
# Returns the total of all symbol frequencies. The returned value is at
# least 0 and is always equal to get_high(get_symbol_limit() - 1).
def get_total(self):
raise NotImplementedError()
# Returns the sum of the frequencies of all the symbols strictly
# below the given symbol value. The returned value is at least 0.
def get_low(self, symbol):
raise NotImplementedError()
# Returns the sum of the frequencies of the given symbol
# and all the symbols below. The returned value is at least 0.
def get_high(self, symbol):
raise NotImplementedError()
# An immutable frequency table where every symbol has the same frequency of 1.
# Useful as a fallback model when no statistics are available.
class FlatFrequencyTable(FrequencyTable):
# Constructs a flat frequency table with the given number of symbols.
def __init__(self, numsyms):
if numsyms < 1:
raise ValueError("Number of symbols must be positive")
self.numsymbols = numsyms # Total number of symbols, which is at least 1
# Returns the number of symbols in this table, which is at least 1.
def get_symbol_limit(self):
return self.numsymbols
# Returns the frequency of the given symbol, which is always 1.
def get(self, symbol):
self._check_symbol(symbol)
return 1
# Returns the total of all symbol frequencies, which is
# always equal to the number of symbols in this table.
def get_total(self):
return self.numsymbols
# Returns the sum of the frequencies of all the symbols strictly below
# the given symbol value. The returned value is equal to 'symbol'.
def get_low(self, symbol):
self._check_symbol(symbol)
return symbol
# Returns the sum of the frequencies of the given symbol and all
# the symbols below. The returned value is equal to 'symbol' + 1.
def get_high(self, symbol):
self._check_symbol(symbol)
return symbol + 1
# Returns silently if 0 <= symbol < numsymbols, otherwise raises an exception.
def _check_symbol(self, symbol):
if 0 <= symbol < self.numsymbols:
return
else:
raise ValueError("Symbol out of range")
# Returns a string representation of this frequency table. The format is subject to change.
def __str__(self):
return "FlatFrequencyTable={}".format(self.numsymbols)
# Unsupported operation, because this frequency table is immutable.
def set(self, symbol, freq):
raise NotImplementedError()
# Unsupported operation, because this frequency table is immutable.
def increment(self, symbol):
raise NotImplementedError()
# A mutable table of symbol frequencies. The number of symbols cannot be changed
# after construction. The current algorithm for calculating cumulative frequencies
# takes linear time, but there exist faster algorithms such as Fenwick trees.
class SimpleFrequencyTable(FrequencyTable):
# Constructs a simple frequency table in one of two ways:
# - SimpleFrequencyTable(sequence):
# Builds a frequency table from the given sequence of symbol frequencies.
# There must be at least 1 symbol, and no symbol has a negative frequency.
# - SimpleFrequencyTable(freqtable):
# Builds a frequency table by copying the given frequency table.
def __init__(self, freqs):
if isinstance(freqs, FrequencyTable):
numsym = freqs.get_symbol_limit()
self.frequencies = [freqs.get(i) for i in range(numsym)]
else: # Assume it is a sequence type
self.frequencies = list(freqs) # Make copy
# 'frequencies' is a list of the frequency for each symbol.
# Its length is at least 1, and each element is non-negative.
if len(self.frequencies) < 1:
raise ValueError("At least 1 symbol needed")
for freq in self.frequencies:
if freq < 0:
raise ValueError("Negative frequency")
# Always equal to the sum of 'frequencies'
self.total = sum(self.frequencies)
# cumulative[i] is the sum of 'frequencies' from 0 (inclusive) to i (exclusive).
# Initialized lazily. When it is not None, the data is valid.
self.cumulative = None
# Returns the number of symbols in this frequency table, which is at least 1.
def get_symbol_limit(self):
return len(self.frequencies)
# Returns the frequency of the given symbol. The returned value is at least 0.
def get(self, symbol):
self._check_symbol(symbol)
return self.frequencies[symbol]
# Sets the frequency of the given symbol to the given value. The frequency value
# must be at least 0. If an exception is raised, then the state is left unchanged.
def set(self, symbol, freq):
self._check_symbol(symbol)
if freq < 0:
raise ValueError("Negative frequency")
temp = self.total - self.frequencies[symbol]
assert temp >= 0
self.total = temp + freq
self.frequencies[symbol] = freq
self.cumulative = None
# Increments the frequency of the given symbol.
def increment(self, symbol):
self._check_symbol(symbol)
self.total += 1
self.frequencies[symbol] += 1
self.cumulative = None
# Returns the total of all symbol frequencies. The returned value is at
# least 0 and is always equal to get_high(get_symbol_limit() - 1).
def get_total(self):
return self.total
# Returns the sum of the frequencies of all the symbols strictly
# below the given symbol value. The returned value is at least 0.
def get_low(self, symbol):
self._check_symbol(symbol)
if self.cumulative is None:
self._init_cumulative()
return self.cumulative[symbol]
# Returns the sum of the frequencies of the given symbol
# and all the symbols below. The returned value is at least 0.
def get_high(self, symbol):
self._check_symbol(symbol)
if self.cumulative is None:
self._init_cumulative()
return self.cumulative[symbol + 1]
# Recomputes the array of cumulative symbol frequencies.
def _init_cumulative(self):
cumul = [0]
sum = 0
for freq in self.frequencies:
sum += freq
cumul.append(sum)
assert sum == self.total
self.cumulative = cumul
# Returns silently if 0 <= symbol < len(frequencies), otherwise raises an exception.
def _check_symbol(self, symbol):
if 0 <= symbol < len(self.frequencies):
return
else:
raise ValueError("Symbol out of range")
# Returns a string representation of this frequency table,
# useful for debugging only, and the format is subject to change.
def __str__(self):
result = ""
for (i, freq) in enumerate(self.frequencies):
result += "{}\t{}\n".format(i, freq)
return result
# A wrapper that checks the preconditions (arguments) and postconditions (return value) of all
# the frequency table methods. Useful for finding faults in a frequency table implementation.
class CheckedFrequencyTable(FrequencyTable):
def __init__(self, freqtab):
# The underlying frequency table that holds the data
self.freqtable = freqtab
def get_symbol_limit(self):
result = self.freqtable.get_symbol_limit()
if result <= 0:
raise AssertionError("Non-positive symbol limit")
return result
def get(self, symbol):
result = self.freqtable.get(symbol)
if not self._is_symbol_in_range(symbol):
raise AssertionError("ValueError expected")
if result < 0:
raise AssertionError("Negative symbol frequency")
return result
def get_total(self):
result = self.freqtable.get_total()
if result < 0:
raise AssertionError("Negative total frequency")
return result
def get_low(self, symbol):
if self._is_symbol_in_range(symbol):
low = self.freqtable.get_low (symbol)
high = self.freqtable.get_high(symbol)
if not (0 <= low <= high <= self.freqtable.get_total()):
raise AssertionError("Symbol low cumulative frequency out of range")
return low
else:
self.freqtable.get_low(symbol)
raise AssertionError("ValueError expected")
def get_high(self, symbol):
if self._is_symbol_in_range(symbol):
low = self.freqtable.get_low (symbol)
high = self.freqtable.get_high(symbol)
if not (0 <= low <= high <= self.freqtable.get_total()):
raise AssertionError("Symbol high cumulative frequency out of range")
return high
else:
self.freqtable.get_high(symbol)
raise AssertionError("ValueError expected")
def __str__(self):
return "CheckFrequencyTable (" + str(self.freqtable) + ")"
def set(self, symbol, freq):
self.freqtable.set(symbol, freq)
if not self._is_symbol_in_range(symbol) or freq < 0:
raise AssertionError("ValueError expected")
def increment(self, symbol):
self.freqtable.increment(symbol)
if not self._is_symbol_in_range(symbol):
raise AssertionError("ValueError expected")
def _is_symbol_in_range(self, symbol):
return 0 <= symbol < self.get_symbol_limit()
# ---- Bit-oriented I/O streams ----
# A stream of bits that can be read. Because they come from an underlying byte stream,
# the total number of bits is always a multiple of 8. The bits are read in big endian.
class BitInputStream(object):
# Constructs a bit input stream based on the given byte input stream.
def __init__(self, inp):
# The underlying byte stream to read from
self.input = inp
# Either in the range [0x00, 0xFF] if bits are available, or -1 if end of stream is reached
self.currentbyte = 0
# Number of remaining bits in the current byte, always between 0 and 7 (inclusive)
self.numbitsremaining = 0
# Reads a bit from this stream. Returns 0 or 1 if a bit is available, or -1 if
# the end of stream is reached. The end of stream always occurs on a byte boundary.
def read(self):
if self.currentbyte == -1:
return -1
if self.numbitsremaining == 0:
temp = self.input.read(1)
if len(temp) == 0:
self.currentbyte = -1
return -1
self.currentbyte = temp[0] if python3 else ord(temp)
self.numbitsremaining = 8
assert self.numbitsremaining > 0
self.numbitsremaining -= 1
return (self.currentbyte >> self.numbitsremaining) & 1
# Reads a bit from this stream. Returns 0 or 1 if a bit is available, or raises an EOFError
# if the end of stream is reached. The end of stream always occurs on a byte boundary.
def read_no_eof(self):
result = self.read()
if result != -1:
return result
else:
raise EOFError()
# Closes this stream and the underlying input stream.
def close(self):
self.input.close()
self.currentbyte = -1
self.numbitsremaining = 0
# A stream where bits can be written to. Because they are written to an underlying
# byte stream, the end of the stream is padded with 0's up to a multiple of 8 bits.
# The bits are written in big endian.
class BitOutputStream(object):
# Constructs a bit output stream based on the given byte output stream.
def __init__(self, out):
self.output = out # The underlying byte stream to write to
self.currentbyte = 0 # The accumulated bits for the current byte, always in the range [0x00, 0xFF]
self.numbitsfilled = 0 # Number of accumulated bits in the current byte, always between 0 and 7 (inclusive)
# Writes a bit to the stream. The given bit must be 0 or 1.
def write(self, b):
if b not in (0, 1):
raise ValueError("Argument must be 0 or 1")
self.currentbyte = (self.currentbyte << 1) | b
self.numbitsfilled += 1
if self.numbitsfilled == 8:
towrite = bytes((self.currentbyte,)) if python3 else chr(self.currentbyte)
self.output.write(towrite)
self.currentbyte = 0
self.numbitsfilled = 0
# Closes this stream and the underlying output stream. If called when this
# bit stream is not at a byte boundary, then the minimum number of "0" bits
# (between 0 and 7 of them) are written as padding to reach the next byte boundary.
def close(self):
while self.numbitsfilled != 0:
self.write(0)
self.output.close()
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -272,7 +272,7 @@ ...@@ -272,7 +272,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.8.11" "version": "3.9.1"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 11,
"id": "dbef8759", "id": "dbef8759",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 44, "execution_count": 12,
"id": "b7a550e0", "id": "b7a550e0",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 51, "execution_count": 13,
"id": "9ed20f84", "id": "9ed20f84",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
...@@ -102,7 +102,7 @@ ...@@ -102,7 +102,7 @@
" y2 = np.ravel(-z0-z1-z2-z3)\n", " y2 = np.ravel(-z0-z1-z2-z3)\n",
" y = np.vstack((y0,y1,y2))\n", " y = np.vstack((y0,y1,y2))\n",
" # use numpy solver to solve the system of equations all at once\n", " # use numpy solver to solve the system of equations all at once\n",
" predict = np.linalg.solve(A,y)[-1]\n", " predict = np.floor(np.linalg.solve(A,y)[-1])\n",
" # flatten the neighbor pixlels and stack them together\n", " # flatten the neighbor pixlels and stack them together\n",
" z0 = np.ravel(z0)\n", " z0 = np.ravel(z0)\n",
" z1 = np.ravel(z1)\n", " z1 = np.ravel(z1)\n",
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 49, "execution_count": 14,
"id": "8e3ef654", "id": "8e3ef654",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
...@@ -152,7 +152,7 @@ ...@@ -152,7 +152,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 52, "execution_count": 15,
"id": "fa65dcd6", "id": "fa65dcd6",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
...@@ -160,10 +160,10 @@ ...@@ -160,10 +160,10 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Average Error First and Second Added: 20.017164930235474\n", "Average Error First and Second Added: 20.017415790767718\n",
"Standard Deviaiton of Mean Errors: 0.16101183692475135\n", "Standard Deviaiton of Mean Errors: 0.1611803882535028\n",
"Average Difference: 53.678648426455226\n", "Average Difference: 53.678648426455226\n",
"Average Time per Image for First: 0.04535740613937378\n" "Average Time per Image for First: 0.07302114367485046\n"
] ]
} }
], ],
...@@ -176,9 +176,114 @@ ...@@ -176,9 +176,114 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 18,
"id": "b7e88aab", "id": "b7e88aab",
"metadata": {}, "metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([3.8620e+03, 2.0014e+04, 4.1788e+04, 4.4365e+04, 4.6890e+04,\n",
" 3.4932e+04, 3.0758e+04, 2.1131e+04, 1.8305e+04, 1.2642e+04,\n",
" 1.0859e+04, 7.4890e+03, 5.9740e+03, 5.3350e+03, 3.8500e+03,\n",
" 3.3960e+03, 2.3890e+03, 2.2130e+03, 1.5640e+03, 1.3960e+03,\n",
" 1.0520e+03, 9.5300e+02, 7.2300e+02, 6.6400e+02, 4.8700e+02,\n",
" 3.8800e+02, 3.5700e+02, 3.1300e+02, 2.5000e+02, 2.0000e+02,\n",
" 1.6800e+02, 1.2700e+02, 1.3000e+02, 6.9000e+01, 8.0000e+01,\n",
" 6.1000e+01, 6.2000e+01, 3.6000e+01, 2.4000e+01, 2.0000e+01,\n",
" 1.3000e+01, 1.3000e+01, 1.4000e+01, 1.0000e+01, 4.0000e+00,\n",
" 3.0000e+00, 3.0000e+00, 2.0000e+00, 0.0000e+00, 2.0000e+00]),\n",
" array([ 0. , 8.46, 16.92, 25.38, 33.84, 42.3 , 50.76, 59.22,\n",
" 67.68, 76.14, 84.6 , 93.06, 101.52, 109.98, 118.44, 126.9 ,\n",
" 135.36, 143.82, 152.28, 160.74, 169.2 , 177.66, 186.12, 194.58,\n",
" 203.04, 211.5 , 219.96, 228.42, 236.88, 245.34, 253.8 , 262.26,\n",
" 270.72, 279.18, 287.64, 296.1 , 304.56, 313.02, 321.48, 329.94,\n",
" 338.4 , 346.86, 355.32, 363.78, 372.24, 380.7 , 389.16, 397.62,\n",
" 406.08, 414.54, 423. ]),\n",
" <BarContainer object of 50 artists>)"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.hist(difference,bins=50)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "aaf16d98",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.collections.PathCollection at 0x7fcf7a43fb80>"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"error = np.abs(image-predict)\n",
"plt.scatter(error,np.sqrt(difference),alpha =0.2)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "3b78c8d4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"numpy.ndarray"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(error)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2a081505",
"metadata": {},
"outputs": [], "outputs": [],
"source": [] "source": []
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment