Commit fced29e2 authored by Kelly Chang's avatar Kelly Chang

Merge branch 'master' of https://git.elphel.com/Elphel/master

parents 2659c0f6 ae2efe0a
{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"id": "8868bc30",
"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_minor": 5
}
{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"id": "dbef8759",
"metadata": {
"id": "dbef8759"
},
"outputs": [],
"source": [
"import numpy as np\n",
"from prediction_MSE_Scout import file_extractor, image_extractor, im_distribution\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\n",
"from time import time\n",
"from numpy import linalg as la\n",
"from scipy.stats import gaussian_kde\n",
"import seaborn as sns\n",
"from collections import Counter\n",
"import pandas as pd\n",
"import scipy as sp"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "9ed20f84",
"metadata": {
"id": "9ed20f84"
},
"outputs": [],
"source": [
"def predict(tiff_list, i=0):\n",
" \"\"\"\n",
" This function predicts the pixel values based on a linear combination\n",
" of the MSE from the three pixels above it and the one to the left. It\n",
" uses a system of equations to fit the plane ax + by + c and takes c\n",
" as the prediction for the unknown pixel. It does this all at once\n",
" by constructing vectors and matrices of the surrounding pixels and solving each system simultaneously\n",
" so as not to iterate through each one.\n",
" \n",
" Parameters:\n",
" tiff_list: list, list of names of image file paths to access. These should be strings\n",
" in the form of a path to the image\n",
" \n",
" i: int, which index in the tiff_list of images we want to predict on\n",
" \n",
" Returns:\n",
" prediction: matrix (ndarray), the matrix of predicted values\n",
" for the image using the previous four piexels\n",
" \n",
" diff: matrix (ndarray), the difference between the highest and lowest valued surrounding four pixels\n",
" \n",
" image_int: matrix (ndarray), the original image, changed into integers\n",
" \n",
" error: matrix (ndarray), a matrix of errors, so each entry is the \n",
" difference between the integer predicted value and the actual value. Should\n",
" be all integers\n",
" \n",
" A: matrix (3,3 ndarray), the matrix used to solve the MSE system\n",
" \"\"\"\n",
" \n",
" image = tiff_list[i]\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_int = image.astype(int)\n",
" \n",
" A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation\n",
" \n",
" z0 = image_int[0:-2,0:-2] # get all the first pixel for the entire image\n",
" z1 = image_int[0:-2,1:-1] # get all the second pixel for the entire image\n",
" z2 = image_int[0:-2,2::] # get all the third pixel for the entire image\n",
" z3 = image_int[1:-1,0:-2] # get all the fourth pixel for the entire image\n",
" \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",
" \n",
" # use numpy solver to solve the system of equations all at once\n",
" #predict = np.linalg.solve(A,y)[-1]\n",
" prediction = np.floor(np.linalg.solve(A,y)[-1]).astype(int)\n",
" #predict = []\n",
" \n",
" # flatten the neighbor pixels 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",
" # calculate the difference\n",
" diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1)\n",
" #diff = np.pad(diff.reshape(510,638), pad_width=1)\n",
" \n",
" # flatten the image to a vector\n",
" small_image = image_int[1:-1,1:-1]\n",
" \n",
" #Reshape the predictions to be a 2D array\n",
" prediction = np.pad(prediction.reshape(510,638), pad_width=1)\n",
" \n",
" \n",
" #Calculate the error between the original image and our predictions\n",
" #Note that we only predicted on the inside square of the original image, excluding\n",
" #The first row, column and last row, column\n",
" #error = (image_int - predict).astype(int) #Experiment\n",
" \n",
" #this one works\n",
" error = image_int - prediction\n",
"\n",
" \n",
" return prediction, diff, image_int, error[1:-1,1:-1], A"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "ba2881d9",
"metadata": {},
"outputs": [],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"num_images = im_distribution(images, \"11\")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "11e95c34",
"metadata": {},
"outputs": [],
"source": [
"prediction, diff, im, err, A = predict(images, 2)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "434e4d2f",
"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): #Iterate through the inside square of the error matrix\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] #Grab the four nearest pixels\n",
" y = np.vstack((-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3)) #Create a vector of the linear combinations for the\n",
" #solution to be solved\n",
" \n",
" new_e[r][c] = np.round(new_e[r][c] + np.linalg.solve(A,y)[-1], 1) #Add the error to the solved system solution\n",
" #rounding the result because np.linalg.solve(A,y)\n",
" #can be a float. Since we did np.floor on it in\n",
" #prediction, we round to the nearest integer here\n",
" return new_e.astype(int)\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "3cc609dc",
"metadata": {},
"outputs": [],
"source": [
"new_error = reconstruct(err, A)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "5d290a0c",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\calle\\AppData\\Local\\Temp/ipykernel_23384/389333.py:1: DeprecationWarning: elementwise comparison failed; this will raise an error in the future.\n",
" im == new_error\n"
]
},
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"im == new_error"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "bb11dcd0",
"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": 9,
"id": "c01fda28",
"metadata": {},
"outputs": [],
"source": [
"def encoder(images, i, plot=True):\n",
" \"\"\"\n",
" Function that creates Huffman encodings out of the error values\n",
" for a given image. The encodings are more efficient ways to store \n",
" large integer values that the original image contains.\n",
" \n",
" Parameters:\n",
" images (list): list of file paths to the images that\n",
" will be encoded.\n",
" \n",
" i (int): which index of the images list to grab and\n",
" then encode.\n",
" \n",
" plot (bool): if true, this plots the error matrix to \n",
" show the distribution of values.\n",
" \"\"\"\n",
" \n",
" prediction, diff, original, error, A = predict(images, i) #Predict the values and return the error for the specified image\n",
" image = original \n",
" new_error = np.copy(image) #Create a new matrix that is a copy of the original image, this is the matrix we will\n",
" #update on throughout\n",
" #new_error[1:-1,1:-1] = np.reshape(error[1:-1,1:-1],(510, 638))\n",
" new_error[1:-1, 1:-1] = error[1:-1, 1:-1] #Set the inside of the updating matrix to be the same as the \n",
" #error matrix retreived from predicting\n",
" keep = new_error[0,0] #The top left entry stays the same\n",
" new_error[0,:] = new_error[0,:] - keep #All edge pixels are set to be the difference between themselves and\n",
" new_error[-1,:] = new_error[-1,:] - keep #the top left entry named \"keep\". This reduces their size to a more\n",
" new_error[1:-1,0] = new_error[1:-1,0] - keep #manageable integer and makes them encodeable with the other error values\n",
" new_error[1:-1,-1] = new_error[1:-1,-1] - keep\n",
" new_error[0,0] = keep\n",
" \n",
" new_error = np.ravel(new_error) #Unravel it to plot it\n",
" if plot:\n",
" plt.hist(new_error[1:],bins=100)\n",
" plt.show()\n",
" \n",
"\n",
" string = [str(i) for i in new_error] #Create strings out of the integers in the new_error matrix\n",
" \n",
" freq = dict(Counter(string)) #Initialize a dictionary that maps integers to the string values\n",
" freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) #Create a frequency mapping of how often the string\n",
" #values occur in the dictionary\n",
" node = make_tree(freq) #Use the Huffman code given above to make a Huffman tree\n",
" \n",
" encoding_dict = huffman_code_tree(node) #Create the Huffman dictionary\n",
" \n",
" #encoded = [\"1\"+encoding[str(-i)] if i < 0 else \"0\"+encoding[str(i)] for i in error]\n",
"\n",
" encoded = new_error.reshape((512,640)).copy().astype(str).astype(object) #Reshape the error matrix and make a copy that\n",
" #that is all strings so we can call the \n",
" #dictionary on its entries\n",
" for i in range(encoded.shape[0]): #Iterate through the string valued error dictionary\n",
" for j in range(encoded.shape[1]):\n",
" if i == 0 and j == 0:\n",
" encoded[i][j] = encoded[i][j] #Replace each value in the dictionary with its encoding from the dictionary\n",
" else:\n",
" encoded[i][j] = encoding_dict[encoded[i][j]]\n",
" \n",
" return encoding_dict, encoded, new_error.reshape((512,640)), image\n",
" #print(encoding)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "ffa858e8",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "could not broadcast input array from shape (508,636) into shape (510,638)",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_2620/384786850.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mencode_dict\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencoding\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merror\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0morig_image\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mencoder\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mimages\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mplot\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_2620/3253315524.py\u001b[0m in \u001b[0;36mencoder\u001b[1;34m(images, i, plot)\u001b[0m\n\u001b[0;32m 21\u001b[0m \u001b[1;31m#update on throughout\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 22\u001b[0m \u001b[1;31m#new_error[1:-1,1:-1] = np.reshape(error[1:-1,1:-1],(510, 638))\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 23\u001b[1;33m \u001b[0mnew_error\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0merror\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;31m#Set the inside of the updating matrix to be the same as the\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 24\u001b[0m \u001b[1;31m#error matrix retreived from predicting\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 25\u001b[0m \u001b[0mkeep\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnew_error\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;31m#The top left entry stays the same\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mValueError\u001b[0m: could not broadcast input array from shape (508,636) into shape (510,638)"
]
}
],
"source": [
"encode_dict, encoding, error, orig_image = encoder(images, 2, plot=False)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "825cc48c",
"metadata": {},
"outputs": [],
"source": [
"def decoder(A, encoded_matrix, encoding_dict):\n",
" \"\"\"\n",
" Function that accecpts the prediction matrix A for the linear system,\n",
" the encoded matrix of error values, and the encoding dicitonary.\n",
" \"\"\"\n",
" the_keys = list(encoding_dict.keys())\n",
" the_values = list(encoding_dict.values())\n",
" error_matrix = encoded_matrix.copy()\n",
" \n",
" for i in range(error_matrix.shape[0]):\n",
" for j in range(error_matrix.shape[1]):\n",
" if i == 0 and j == 0:\n",
" error_matrix[i][j] = int(encoded_matrix[i][j])\n",
" \n",
" elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1:\n",
" error_matrix[i][j] = int(the_keys[the_values.index(error_matrix[i,j])]) + error_matrix[0][0]\n",
" else:\n",
" \"\"\"z0, z1, z2, z3 = error_matrix[i-1][j-1], error_matrix[i-1][j], \\\n",
" error_matrix[i-1][j+1], error_matrix[i][j-1]\n",
" y = np.vstack((-z0+z2-z3, z0+z1+z2, -z0-z1-z2-z3))\"\"\"\n",
" \n",
" error_matrix[i][j] = int(the_keys[the_values.index(error_matrix[i,j])])\n",
" \n",
" return error_matrix.astype(int)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "ba1d2c2c",
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'encoding' is not defined",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_23384/3979147550.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mem\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdecoder\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mA\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencoding\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode_dict\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;31mNameError\u001b[0m: name 'encoding' is not defined"
]
}
],
"source": [
"em = decoder(A, encoding, encode_dict)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "b2cdce6d",
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'em' is not defined",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_23384/2268978435.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mhopefully\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mreconstruct\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mem\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mA\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;31m#22487 22483 22521 22464\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mNameError\u001b[0m: name 'em' is not defined"
]
}
],
"source": [
"hopefully = reconstruct(em, A)\n",
"#22487 22483 22521 22464"
]
},
{
"cell_type": "code",
"execution_count": 124,
"id": "285efcf0",
"metadata": {},
"outputs": [],
"source": [
"def test_decoder():\n",
" n = len(images)//12\n",
" fails = 0\n",
" for i in range(n):\n",
" encode_dict1, encoding1, error1, orig_image1 = encoder(images, i, plot=False)\n",
" new_error = decoder(A, encoding1, encode_dict1)\n",
" reconstructed_image = reconstruct(new_error, A)\n",
" if False in np.ravel(reconstructed_image == orig_image):\n",
" fails += 0\n",
" return fails/n\n",
"f = test_decoder()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "30b1c87e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6.7830123821108295\n"
]
}
],
"source": [
"def entropy_func(images):\n",
" \"\"\"\n",
" Computes the entropy for all pictures (tiff files) in the images list.\n",
" This gives an idea of how many bits it would take on average to encode the\n",
" given image. The output is a list of entropies, one per image.\n",
" \"\"\"\n",
" entr = []\n",
" for i in range(len(images)):\n",
" prediction, diff, im, err, A = predict(images, i)\n",
" panda_im = pd.Series(np.ravel(im))\n",
" counts = panda_im.value_counts()\n",
" entr.append(sp.stats.entropy(counts))\n",
" return entr\n",
"\n",
"e = entropy_func(images)\n",
"print(np.mean(e))"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "4c268907",
"metadata": {},
"outputs": [
{
"ename": "IndexError",
"evalue": "boolean index did not match indexed array along dimension 0; dimension is 510 but corresponding boolean dimension is 512",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mIndexError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_2620/1618652474.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 72\u001b[0m \u001b[0mscenes\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mfile_extractor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 73\u001b[0m \u001b[0mimages\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mimage_extractor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mscenes\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 74\u001b[1;33m \u001b[0mencode1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode3\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode4\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode5\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mimage\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merror\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnew_error\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdiff\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mboundary\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mbins\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mhuffman\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mimages\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_2620/1618652474.py\u001b[0m in \u001b[0;36mhuffman\u001b[1;34m(image)\u001b[0m\n\u001b[0;32m 18\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 19\u001b[0m \u001b[0mmask\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdiff\u001b[0m \u001b[1;33m<=\u001b[0m \u001b[1;36m25\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 20\u001b[1;33m \u001b[0mstring\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mstr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0merror\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mmask\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mint\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 21\u001b[0m \u001b[0mfreq\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mCounter\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstring\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 22\u001b[0m \u001b[0mfreq\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msorted\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfreq\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mreverse\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mIndexError\u001b[0m: boolean index did not match indexed array along dimension 0; dimension is 510 but corresponding boolean dimension is 512"
]
}
],
"source": [
"def huffman(image):\n",
" origin, predicty, diff, error, A = predict(image,0)\n",
" \n",
" image = Image.open(image[0])\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",
" \n",
" boundary = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1]))\n",
" boundary = boundary - image[0,0]\n",
" boundary[0] = image[0,0]\n",
"\n",
" string = [str(i) for i in boundary]\n",
" freq = dict(Counter(string))\n",
" freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)\n",
" node = make_tree(freq)\n",
" encode1 = huffman_code_tree(node)\n",
" \n",
" \n",
" mask = diff <= 25\n",
" string = [str(i) for i in error[mask].astype(int)]\n",
" freq = dict(Counter(string))\n",
" freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)\n",
" node = make_tree(freq)\n",
" encode2 = huffman_code_tree(node)\n",
"\n",
" \n",
" mask = diff > 25\n",
" new_error = error[mask]\n",
" mask2 = diff[mask] <= 40\n",
" string = [str(i) for i in new_error[mask2].astype(int)]\n",
" freq = dict(Counter(string))\n",
" freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)\n",
" node = make_tree(freq)\n",
" encode3 = huffman_code_tree(node)\n",
" \n",
"\n",
" mask = diff > 40\n",
" new_error = error[mask]\n",
" mask2 = diff[mask] <= 70\n",
" string = [str(i) for i in new_error[mask2].astype(int)]\n",
" freq = dict(Counter(string))\n",
" freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)\n",
" node = make_tree(freq)\n",
" encode4 = huffman_code_tree(node)\n",
" \n",
" \n",
" mask = diff > 70\n",
" string = [str(i) for i in error[mask].astype(int)]\n",
" freq = dict(Counter(string))\n",
" freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)\n",
" node = make_tree(freq)\n",
" encode5 = huffman_code_tree(node)\n",
"\n",
"\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",
" \n",
" \n",
" #new_error = np.ravel(new_error)\n",
" \n",
" bins = [25,40,70]\n",
" \n",
" # return the huffman dictionary\n",
" return encode1, encode2, encode3, encode4, encode5, np.ravel(image), error, new_error, diff, boundary, bins\n",
" \n",
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"encode1, encode2, encode3, encode4, encode5, image, error, new_error, diff, boundary, bins = huffman(images)"
]
},
{
"cell_type": "code",
"execution_count": 159,
"id": "e98fc3cf",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[22541 -10 14 ... 62 151 208]\n"
]
}
],
"source": [
"print(boundary)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f5e71acc",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 127,
"id": "642b95a3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.4427516682942708"
]
},
"execution_count": 127,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def compress_rate(image, error, diff, bound, encode1, encode2, encode3, encode4, encode5):\n",
" #original = original.reshape(-1)\n",
" #error = error.reshape(-1)\n",
" o_len = 0\n",
" c_len = 0\n",
" im = np.reshape(image,(512, 640))\n",
" real_b = np.hstack((im[0,:],im[-1,:],im[1:-1,0],im[1:-1,-1]))\n",
" original = im[1:-1,1:-1].reshape(-1)\n",
"\n",
" for i in range(0,len(bound)):\n",
" o_len += len(bin(real_b[i])[2:])\n",
" c_len += len(encode1[str(bound[i])])\n",
" \n",
" for i in range(0, len(original)):\n",
" o_len += len(bin(original[i])[2:])\n",
" if diff[i] <= 10:\n",
" c_len += len(encode2[str(int(error[i]))])\n",
"\n",
" if diff[i] <= 25 and diff[i] > 10:\n",
" c_len += len(encode3[str(int(error[i]))])\n",
" \n",
" if diff[i] <= 45 and diff[i] > 25:\n",
" c_len += len(encode4[str(int(error[i]))])\n",
" \n",
" if diff[i] > 45:\n",
" c_len += len(encode5[str(int(error[i]))])\n",
" \n",
" return c_len/o_len\n",
"compress_rate(origin, error, diff, boundary, encode1, encode2, encode3, encode4, encode5)\n"
]
},
{
"cell_type": "code",
"execution_count": 209,
"id": "7d507cfb",
"metadata": {},
"outputs": [],
"source": [
"def encode_multiple(error, diff, bound, encode1, encode2, encode3, encode4, encode5):\n",
" #original = original.reshape(-1)\n",
" #error = error.reshape(-1)\n",
" original = len(np.ravel(error))\n",
" error = np.ravel(error)\n",
" encode_error = error.astype(str).astype(object).copy()\n",
" bound_error = bound.astype(str).astype(object).copy()\n",
" \n",
" \n",
" for i in range(0,len(bound_error)):\n",
" bound_error[i] = encode1[bound_error[i]] \n",
" \n",
" for i in range(0, original):\n",
" if diff[i] <= 10:\n",
" encode_error[i] = encode2[encode_error[i]]\n",
"\n",
" if diff[i] <= 25 and diff[i] > 10:\n",
" encode_error[i] = encode3[encode_error[i]]\n",
" \n",
" if diff[i] <= 45 and diff[i] > 25:\n",
" encode_error[i] = encode4[encode_error[i]]\n",
" \n",
" if diff[i] > 45:\n",
" encode_error[i] = encode5[encode_error[i]]\n",
" \n",
" encode_error = np.pad(encode_error.reshape(510,638), pad_width=1)\n",
" encode_error[0] = bound_error[:640]\n",
" encode_error[-1] = bound_error[640:640*2]\n",
" encode_error[1:-1,0] = bound_error[640*2:(640*2)+510]\n",
" encode_error[1:-1,-1] = bound_error[(640*2)+510:]\n",
" \n",
" return encode_error, bound_error\n",
"enc_mat, bound_e = encode_multiple(error, diff, boundary, encode1, encode2, encode3, encode4, encode5)"
]
},
{
"cell_type": "code",
"execution_count": 211,
"id": "2faf5cd9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 1\n"
]
},
{
"ename": "ValueError",
"evalue": "'101011' is not in list",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_1700/1235154671.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 42\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0merror_matrix\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mint\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 43\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 44\u001b[1;33m \u001b[0mdec\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdecode_multi\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mA\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0menc_mat\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode3\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode4\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mencode5\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdiff\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_1700/1235154671.py\u001b[0m in \u001b[0;36mdecode_multi\u001b[1;34m(A, encoded_matrix, encode1, encode2, encode3, encode4, encode5, diff)\u001b[0m\n\u001b[0;32m 35\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0merror_matrix\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m'101011'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 36\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mj\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 37\u001b[1;33m \u001b[0merror_matrix\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mthe_keys4\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthe_values4\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0merror_matrix\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 38\u001b[0m \u001b[1;32melif\u001b[0m \u001b[0mdiff\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m*\u001b[0m\u001b[1;36m640\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m>\u001b[0m \u001b[1;36m45\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 39\u001b[0m \u001b[0merror_matrix\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mthe_keys5\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mthe_values5\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0merror_matrix\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mValueError\u001b[0m: '101011' is not in list"
]
}
],
"source": [
"def decode_multi(A, encoded_matrix, encode1, encode2, encode3, encode4, encode5, diff):\n",
" \"\"\"\n",
" Function that accecpts the prediction matrix A for the linear system,\n",
" the encoded matrix of error values, and the encoding dicitonary.\n",
" \"\"\"\n",
" \n",
" \n",
" the_keys1 = list(encode1.keys())\n",
" the_values1 = list(encode1.values())\n",
" the_keys2 = list(encode2.keys())\n",
" the_values2 = list(encode2.values())\n",
" the_keys3 = list(encode3.keys())\n",
" the_values3 = list(encode3.values())\n",
" the_keys4 = list(encode4.keys())\n",
" the_values4 = list(encode4.values())\n",
" the_keys5 = list(encode5.keys())\n",
" the_values5 = list(encode5.values())\n",
" \n",
" error_matrix = encoded_matrix.copy()\n",
" \n",
" for i in range(error_matrix.shape[0]):\n",
" for j in range(error_matrix.shape[1]):\n",
" if i == 0 and j == 0:\n",
" error_matrix[i][j] = int(the_keys1[the_values1.index(encoded_matrix[i,j])])\n",
" \n",
" \n",
" elif i == 0 or i == error_matrix.shape[0]-1 or j == 0 or j == error_matrix.shape[1]-1:\n",
" error_matrix[i][j] = int(the_keys1[the_values1.index(error_matrix[i,j])]) + int(error_matrix[0][0])\n",
" else:\n",
" if diff[i*640 + j] <= 10:\n",
" error_matrix[i][j] = int(the_keys2[the_values2.index(error_matrix[i,j])])\n",
" elif diff[i*640 + j] > 10 and diff[i*640 + j] <= 25:\n",
" error_matrix[i,j] = int(the_keys3[the_values3.index(error_matrix[i,j])])\n",
" elif diff[i*640 + j] > 25 and diff[i*640 + j] <= 45:\n",
" if error_matrix[i,j] == '101011':\n",
" print(i,j)\n",
" \n",
" error_matrix[i,j] = int(the_keys4[the_values4.index(error_matrix[i,j])])\n",
" elif diff[i*640 + j] > 45:\n",
" error_matrix[i,j] = int(the_keys5[the_values5.index(error_matrix[i,j])])\n",
" \n",
" \n",
" return error_matrix.astype(int)\n",
"\n",
"dec = decode_multi(A, enc_mat, encode1, encode2, encode3, encode4, encode5, diff)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "64832ca7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[58 38 13 ... 65 97 32]\n"
]
},
{
"ename": "NameError",
"evalue": "name 'o' is not defined",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_2620/2795330121.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[0mfreqs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcount\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m/\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mvalue\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 8\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mfreqs\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 9\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstats\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mentropy\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrel_freq\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mravel\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mo\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 10\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mentropy_check\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mNameError\u001b[0m: name 'o' is not defined"
]
}
],
"source": [
"\n",
"\"\"\"plt.hexbin(x,y,cmap=\"rocket\")\n",
"plt.colorbar()\n",
"plt.xlim(0,50)\n",
"plt.ylim(0,100)\"\"\"\n",
"\n",
"def rel_freq(x):\n",
" freqs = [x.count(value) / len(x) for value in set(x)] \n",
" return freqs\n",
"print(sp.stats.entropy(rel_freq(list(np.ravel(image)))))\n",
"\n",
"def entropy_check(x, y):\n",
" #freq = rel_freq(list(np.ravel(o)))\n",
" means = []\n",
" for i in range(len(images)):\n",
" p, d, o, e, A = predict(images,0)\n",
" d = d.reshape((510,638))\n",
" x = np.abs(np.ravel(e))\n",
" y = np.ravel(d)\n",
" \n",
" mask1 = y <= 25\n",
" x_masked1 = x[mask1]\n",
"\n",
" mask2 = y > 25\n",
" x_masked2 = x[mask2]\n",
" mask2 = y[mask2] <= 40\n",
" x_masked2 = x_masked2[mask2]\n",
"\n",
" mask3 = y > 40\n",
" x_masked3 = x[mask3]\n",
" mask3 = y[mask3] <= 75\n",
" x_masked3 = x_masked3[mask3]\n",
" \n",
" mask4 = y > 75\n",
" x_masked4 = x[mask4]\n",
"\n",
"\n",
" e_m1 = sp.stats.entropy(rel_freq(list(x_masked1)))\n",
" e_m2 = sp.stats.entropy(rel_freq(list(x_masked2)))\n",
" e_m3 = sp.stats.entropy(rel_freq(list(x_masked3)))\n",
" e_m4 = sp.stats.entropy(rel_freq(list(x_masked4)))\n",
" means.append([e_m1, e_m2, e_m3, e_m4])\n",
" return np.mean(np.array(means).reshape(len(images),4), axis=0)\n",
" \n",
"#print(entropy_check(x, y))"
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"name": "Wavelet_Huffman.ipynb",
"provenance": []
},
"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.8.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "dbef8759",
"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\n",
"from time import time\n",
"from numpy import linalg as la\n",
"from scipy.stats import gaussian_kde, entropy\n",
"import seaborn as sns\n",
"import pywt\n",
"import math\n",
"#import cv2"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "b7a550e0",
"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:-5] == num:\n",
" tiff.append(im)\n",
" return tiff"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "9ed20f84",
"metadata": {},
"outputs": [],
"source": [
"def plot_hist(tiff_list, i):\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[i]\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.linalg.solve(A,y)[-1]\n",
" #predict = []\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",
" \"\"\"for i in range(len(neighbor)):\n",
" if neighbor[i][0] >= max(neighbor[i][3], neighbor[i][1]):\n",
" predict.append(min(neighbor[i][3], neighbor[i][1]))\n",
" elif neighbor[i][0] < min(neighbor[i][3], neighbor[i][1]):\n",
" predict.append(max(neighbor[i][3], neighbor[i][1]))\n",
" else:\n",
" predict.append(neighbor[i][3] + neighbor[i][1] - neighbor[i][0])\"\"\"\n",
" \n",
" # flatten the image to a vector\n",
" image_ravel = np.ravel(image[1:-1,1:-1])\n",
" return image_ravel, predict, diff, image"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "8e3ef654",
"metadata": {},
"outputs": [],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"num_images = im_distribution(images, \"_1\")\n",
"error_mean = []\n",
"error_mean1 = []\n",
"diff_mean = []\n",
"times = []\n",
"times1 = []\n",
"all_error = []\n",
"for i in range(len(num_images)):\n",
" \"\"\"start1 = time()\n",
" image_1, predict_1, difference_1, x_s_1 = plot_hist(num_images, i, \"second\")\n",
" stop1 = time()\n",
" times1.append(stop1-start1)\n",
" error1 = np.abs(image_1-predict_1)\n",
" error_mean1.append(np.mean(np.ravel(error1)))\"\"\"\n",
" start = time()\n",
" image, predict, difference, non_ravel = plot_hist(num_images, i)\n",
" stop = time()\n",
" times.append(stop-start)\n",
" error = np.abs(image-predict)\n",
" all_error.append(np.ravel(error))\n",
" error_mean.append(np.mean(np.ravel(error)))\n",
" diff_mean.append(np.mean(np.ravel(difference)))\n",
" \n",
"#image, predict, difference = plot_hist(images, 0)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "fa65dcd6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Average Error: 19.44221679267325\n",
"Standard Deviaiton of Mean Errors: 0.17734010606906342\n",
"Average Difference: 51.95430150900486\n",
"Average Time per Image for First: 0.050624340772628784\n"
]
}
],
"source": [
"print(f\"Average Error: {np.mean(error_mean)}\")\n",
"print(f\"Standard Deviaiton of Mean Errors: {np.sqrt(np.var(error_mean))}\")\n",
"print(f\"Average Difference: {np.mean(diff_mean)}\")\n",
"print(f\"Average Time per Image for First: {np.mean(times)}\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "4c05b947",
"metadata": {},
"outputs": [],
"source": [
"new_image, new_pred, new_diff, no_ravel = plot_hist(images, 10)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "dda442ae",
"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"
}
],
"source": [
"new_error = (new_image-new_pred).astype(np.int32)\n",
"plt.hist(new_error, bins=20, density=True)\n",
"sns.kdeplot(new_error)\n",
"plt.xlabel(\"error\")\n",
"plt.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "58da6063",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 0. , 0. , 0. , ..., 0. , 0. , 0. ],\n",
" [ 0. , 22327. , 22323. , ..., 22406.5, 22446. , 0. ],\n",
" [ 0. , 22350.5, 22335.5, ..., 22429. , 22390. , 0. ],\n",
" ...,\n",
" [ 0. , 22099. , 22125. , ..., 22823.5, 22817. , 0. ],\n",
" [ 0. , 22140. , 22172.5, ..., 22774. , 22771. , 0. ],\n",
" [ 0. , 0. , 0. , ..., 0. , 0. , 0. ]])"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prediction = new_pred.reshape((510,638))\n",
"prediction = np.pad(prediction, pad_width=1)"
]
}
],
"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.8.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "dbef8759",
"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\n",
"from time import time"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "b7a550e0",
"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:-5] == num:\n",
" tiff.append(im)\n",
" return tiff"
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "9ed20f84",
"metadata": {},
"outputs": [],
"source": [
"def plot_hist(tiff_list,i):\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",
"\n",
" image = tiff_list[i]\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.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",
" # flatten the image to a vector\n",
" image = np.ravel(image[1:-1,1:-1])\n",
" return image, predict, diff\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "8e3ef654",
"metadata": {},
"outputs": [],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"num_images = im_distribution(images, \"_9\")\n",
"error_mean = []\n",
"error_mean1 = []\n",
"diff_mean = []\n",
"times = []\n",
"times1 = []\n",
"all_error = []\n",
"for i in range(len(num_images)):\n",
" \"\"\"start1 = time()\n",
" image_1, predict_1, difference_1, x_s_1 = plot_hist(num_images, i, \"second\")\n",
" stop1 = time()\n",
" times1.append(stop1-start1)\n",
" error1 = np.abs(image_1-predict_1)\n",
" error_mean1.append(np.mean(np.ravel(error1)))\"\"\"\n",
" start = time()\n",
" image, predict, difference = plot_hist(num_images, i)\n",
" stop = time()\n",
" times.append(stop-start)\n",
" error = np.abs(image-predict)\n",
" all_error.append(np.ravel(error))\n",
" error_mean.append(np.mean(np.ravel(error)))\n",
" diff_mean.append(np.mean(np.ravel(difference)))"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "fa65dcd6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Average Error First and Second Added: 20.017164930235474\n",
"Standard Deviaiton of Mean Errors: 0.16101183692475135\n",
"Average Difference: 53.678648426455226\n",
"Average Time per Image for First: 0.04535740613937378\n"
]
}
],
"source": [
"print(f\"Average Error First and Second Added: {np.mean(error_mean)}\")\n",
"print(f\"Standard Deviaiton of Mean Errors: {np.sqrt(np.var(error_mean))}\")\n",
"print(f\"Average Difference: {np.mean(diff_mean)}\")\n",
"print(f\"Average Time per Image for First: {np.mean(times)}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b7e88aab",
"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_minor": 5
}
......@@ -567,7 +567,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
"version": "3.8.11"
}
},
"nbformat": 4,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
'''
Created on Jan 11, 2022
@author: nathanielc
python file located in the Image Compression project
folder under nathanielc user. This python file is for
exploring possible image compression techniques and is by
no means a final product. Goal is to learn how to download
images and extract important statistics from them.
'''
import numpy as np
from matplotlib import pyplot as plt
from itertools import product
import os
import sys
from PIL import Image
def file_extractor(dirname="images"):
files = os.listdir(dirname)
scenes = []
for file in files:
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:
image_folder.append(os.path.join(scene, file))
images = []
for folder in image_folder:
ims = os.listdir(folder)
for im in ims:
if im[-4:] == ".jp4" or im[-7:] == "_6.tiff":
continue
else:
images.append(os.path.join(folder, im))
return images #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:-6] == num:
tiff.append(im)
return tiff
def plot_hist(tiff_list):
"""
This function is the leftovers from the first attempt to plot histograms.
As it stands it needs some work in order to function again. We will
fix this later. 1/25/22
"""
'''jj = 0
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(15,12))
for cam, ax in zip(cameras, axs.ravel()):
diff = []
for ii in range(len(cam)):
image = Image.open(cam[ii]) #Open the image and read it as an Image object
image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data
ar1, ar2 = image.shape
ind1, ind2 = np.random.randint(1,ar1-1), np.random.randint(1,ar2-1) #ind1 randomly selects a row, ind2 randomly selects a column,
#this is now a random pixel selection within the image
surrounding = [] #initialize a list to be filled the 8 surrounding pixels
for i,j in product(np.arange(-1,2), repeat=2): #Iterate through the combinations of surrounding pixel indices
if i == 0 and j == 0: #Avoid the target pixel
continue
else:
surrounding.append(image[ind1+i, ind1+j]) #Add the other 8 pixels to the list
diff.append(np.max(surrounding)-np.min(surrounding))
ax.hist(diff)
ax.set_title(f"tiff {jj}")
jj += 1
plt.tight_layout()
plt.show()
return '''
image = tiff_list[0]
image = Image.open(image) #Open the image and read it as an Image object
image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data
row, col = image.shape
predict = np.empty([row-1,col-1]) # create a empty matrix to update prediction
temp = image.copy
diff = np.empty([row-1,col-1])
for r in range(1,row-1): # loop through the rth row
for c in range(1,col-1): # loop through the cth column
surrounding = np.array([temp[r-1,c-1], temp[r-1,c], temp[r-1,c+1], temp[r,c-1]])
predict[r,c] = np.mean(surrounding) # take the mean of the previous 4 pixels
temp[r,c] = np.mean(surrounding)
diff[r,c] = (np.max(surrounding)-np.min(surrounding))
predict = np.ravel(predict)
diff = np.ravel(diff)
n = len(predict)
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
z3 = np.zeros(n)
dx = np.ones(n)
dy = np.ones(n)
dz = np.arange(n)
ax1.bar3d(predict, diff, z3, dx, dy, dz, color="red")
ax1.axis('off')
plt.show()
return image, predict, diff
if __name__ == '__main__':
"""For boundary cases: Start by grabbing the shape of the images and saving those
as variables. Then, if statements for if row == 0 or row == maximum and if
col == 0 or col == maximum. Then grab corresponding open pixels. Then proceed to do
an and statement that handles the corners"""
scenes = file_extractor()
images = image_extractor(scenes)
#image, predict, difference = plot_hist(images)
#error = np.abs(image-predict)
plot_hist(images)
\ No newline at end of file
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "dbef8759",
"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\n",
"from time import time\n",
"from numpy import linalg as la\n",
"from scipy.stats import gaussian_kde, entropy\n",
"import seaborn as sns\n",
"import pywt\n",
"import math\n",
"#import cv2"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "b7a550e0",
"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:-5] == num:\n",
" tiff.append(im)\n",
" return tiff"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "9ed20f84",
"metadata": {},
"outputs": [],
"source": [
"def plot_hist(tiff_list, i):\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[i]\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.linalg.solve(A,y)[-1]\n",
" #predict = []\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",
" \"\"\"for i in range(len(neighbor)):\n",
" if neighbor[i][0] >= max(neighbor[i][3], neighbor[i][1]):\n",
" predict.append(min(neighbor[i][3], neighbor[i][1]))\n",
" elif neighbor[i][0] < min(neighbor[i][3], neighbor[i][1]):\n",
" predict.append(max(neighbor[i][3], neighbor[i][1]))\n",
" else:\n",
" predict.append(neighbor[i][3] + neighbor[i][1] - neighbor[i][0])\"\"\"\n",
" \n",
" # flatten the image to a vector\n",
" image_ravel = np.ravel(image[1:-1,1:-1])\n",
" return image_ravel, predict, diff, image"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "8e3ef654",
"metadata": {},
"outputs": [],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"num_images = im_distribution(images, \"_1\")\n",
"error_mean = []\n",
"error_mean1 = []\n",
"diff_mean = []\n",
"times = []\n",
"times1 = []\n",
"all_error = []\n",
"for i in range(len(num_images)):\n",
" \"\"\"start1 = time()\n",
" image_1, predict_1, difference_1, x_s_1 = plot_hist(num_images, i, \"second\")\n",
" stop1 = time()\n",
" times1.append(stop1-start1)\n",
" error1 = np.abs(image_1-predict_1)\n",
" error_mean1.append(np.mean(np.ravel(error1)))\"\"\"\n",
" start = time()\n",
" image, predict, difference, non_ravel = plot_hist(num_images, i)\n",
" stop = time()\n",
" times.append(stop-start)\n",
" error = np.abs(image-predict)\n",
" all_error.append(np.ravel(error))\n",
" error_mean.append(np.mean(np.ravel(error)))\n",
" diff_mean.append(np.mean(np.ravel(difference)))\n",
" \n",
"#image, predict, difference = plot_hist(images, 0)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "fa65dcd6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Average Error: 19.44221679267325\n",
"Standard Deviaiton of Mean Errors: 0.17734010606906342\n",
"Average Difference: 51.95430150900486\n",
"Average Time per Image for First: 0.050624340772628784\n"
]
}
],
"source": [
"print(f\"Average Error: {np.mean(error_mean)}\")\n",
"print(f\"Standard Deviaiton of Mean Errors: {np.sqrt(np.var(error_mean))}\")\n",
"print(f\"Average Difference: {np.mean(diff_mean)}\")\n",
"print(f\"Average Time per Image for First: {np.mean(times)}\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "4c05b947",
"metadata": {},
"outputs": [],
"source": [
"new_image, new_pred, new_diff, no_ravel = plot_hist(images, 10)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "dda442ae",
"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"
}
],
"source": [
"new_error = (new_image-new_pred).astype(np.int32)\n",
"plt.hist(new_error, bins=20, density=True)\n",
"sns.kdeplot(new_error)\n",
"plt.xlabel(\"error\")\n",
"plt.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "58da6063",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 0. , 0. , 0. , ..., 0. , 0. , 0. ],\n",
" [ 0. , 22327. , 22323. , ..., 22406.5, 22446. , 0. ],\n",
" [ 0. , 22350.5, 22335.5, ..., 22429. , 22390. , 0. ],\n",
" ...,\n",
" [ 0. , 22099. , 22125. , ..., 22823.5, 22817. , 0. ],\n",
" [ 0. , 22140. , 22172.5, ..., 22774. , 22771. , 0. ],\n",
" [ 0. , 0. , 0. , ..., 0. , 0. , 0. ]])"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prediction = new_pred.reshape((510,638))\n",
"prediction = np.pad(prediction, pad_width=1)"
]
}
],
"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_minor": 5
}
#!/usr/bin/env python
# coding: utf-8
# In[72]:
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
from time import time
from numpy import linalg as la
from scipy.stats import gaussian_kde, entropy
import seaborn as sns
import pywt
import math
#import cv2
# In[15]:
def file_extractor(dirname="images"):
files = os.listdir(dirname)
scenes = []
for file in files:
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[-4:] == ".jp4" 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
# In[16]:
def plot_hist(tiff_list, i):
"""
This function is the leftovers from the first attempt to plot histograms.
As it stands it needs some work in order to function again. We will
fix this later. 1/25/22
"""
image = tiff_list[i]
image = Image.open(image) #Open the image and read it as an Image object
image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data
image = image.astype(int)
A = np.array([[3,0,-1],[0,3,3],[1,-3,-4]]) # the matrix for system of equation
z0 = image[0:-2,0:-2] # get all the first pixel for the entire image
z1 = image[0:-2,1:-1] # get all the second pixel for the entire image
z2 = image[0:-2,2::] # get all the third pixel for the entire image
z3 = image[1:-1,0:-2] # get all the forth pixel for the entire image
# calculate the out put of the system of equation
y0 = np.ravel(-z0+z2-z3)
y1 = np.ravel(z0+z1+z2)
y2 = np.ravel(-z0-z1-z2-z3)
y = np.vstack((y0,y1,y2))
# use numpy solver to solve the system of equations all at once
predict = np.linalg.solve(A,y)[-1]
#predict = []
# 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
# calculate the difference
diff = np.max(neighbor,axis = 1) - np.min(neighbor, axis=1)
"""for i in range(len(neighbor)):
if neighbor[i][0] >= max(neighbor[i][3], neighbor[i][1]):
predict.append(min(neighbor[i][3], neighbor[i][1]))
elif neighbor[i][0] < min(neighbor[i][3], neighbor[i][1]):
predict.append(max(neighbor[i][3], neighbor[i][1]))
else:
predict.append(neighbor[i][3] + neighbor[i][1] - neighbor[i][0])"""
# flatten the image to a vector
image_ravel = np.ravel(image[1:-1,1:-1])
return image_ravel, predict, diff, image
# In[17]:
scenes = file_extractor()
images = image_extractor(scenes)
num_images = im_distribution(images, "_1")
error_mean = []
error_mean1 = []
diff_mean = []
times = []
times1 = []
all_error = []
for i in range(len(num_images)):
"""start1 = time()
image_1, predict_1, difference_1, x_s_1 = plot_hist(num_images, i, "second")
stop1 = time()
times1.append(stop1-start1)
error1 = np.abs(image_1-predict_1)
error_mean1.append(np.mean(np.ravel(error1)))"""
start = time()
image, predict, difference, non_ravel = plot_hist(num_images, i)
stop = time()
times.append(stop-start)
error = np.abs(image-predict)
all_error.append(np.ravel(error))
error_mean.append(np.mean(np.ravel(error)))
diff_mean.append(np.mean(np.ravel(difference)))
#image, predict, difference = plot_hist(images, 0)
# In[18]:
print(f"Average Error: {np.mean(error_mean)}")
print(f"Standard Deviaiton of Mean Errors: {np.sqrt(np.var(error_mean))}")
print(f"Average Difference: {np.mean(diff_mean)}")
print(f"Average Time per Image for First: {np.mean(times)}")
# In[19]:
new_image, new_pred, new_diff, no_ravel = plot_hist(images, 10)
# In[21]:
new_error = new_image-new_pred
plt.hist(new_error, bins=20, density=True)
sns.kdeplot(new_error)
plt.xlabel("error")
plt.show()
# In[41]:
image = Image.open(images[0]) #Open the image and read it as an Image object
image = np.array(image)[1:,:] #Convert to an array, leaving out the first row because the first row is just housekeeping data
image = image.astype(np.int64)
print("Std Deviation of E: ", np.std(new_error))
print("Normal bits: ", int(image[0][0]).bit_length())
H = np.log2(np.std(new_error)) + 1.943
print("Encoded Bits: ", H)
# In[47]:
# In[9]:
pred = new_pred.reshape((510,638))
real_pred = no_ravel.copy()
real_pred[1:-1, 1:-1] = pred
# In[10]:
coeffs = pywt.dwt2(no_ravel, 'bior1.3')
LL, (LH, HL, HH) = coeffs
print(HH.shape)
decompress = pywt.idwt2(coeffs, 'bior1.3')
"""print(decompress)
print(np.mean(np.abs(decompress-no_ravel)))"""
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