Commit 88251d36 authored by Kelly Chang's avatar Kelly Chang

take out kelly's

parent 60919e6c
{
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"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": 9,
"id": "76317b02",
"metadata": {},
"outputs": [],
"source": [
"def file_extractor(dirname=\"images\"):\n",
" files = os.listdir(dirname)\n",
" scenes = []\n",
" for file in files:\n",
" if file == '.DS_Store':\n",
" continue\n",
" else:\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",
"\n",
"def image_extractor(scenes):\n",
" image_folder = []\n",
" for scene in scenes:\n",
" files = os.listdir(scene)\n",
" for file in files:\n",
" #if file[-4:] == \".jp4\" or file[-7:] == \"_6.tiff\":\n",
" if file[-5:] != \".tiff\" or file[-7:] == \"_6.tiff\":\n",
" print(file)\n",
" continue\n",
" else:\n",
" image_folder.append(os.path.join(scene, file))\n",
" return image_folder\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": 5,
"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": 6,
"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": "markdown",
"id": "c7104fbf",
"metadata": {},
"source": [
"### Huffman without dividing into bins"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "a43f3f1c",
"metadata": {},
"outputs": [],
"source": [
"def huffman_nb(image):\n",
" origin, predict, diff, error, A = plot_hist(image)\n",
" image = Image.open(image)\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",
" 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",
" \n",
" \n",
" \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.astype(int)]\n",
" freq = dict(Counter(string))\n",
" \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",
" \n",
" # return the huffman dictionary\n",
" return encoding, new_error, image.reshape(-1)\n",
" \n",
" \n",
"def compress_rate_nb(image, error, encoding):\n",
" original = image.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(int(error[i]))])\n",
"\n",
" return c_len/o_len\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "eac2f456",
"metadata": {},
"source": [
"### Huffman with dividing into non-uniform bins"
]
},
{
"cell_type": "code",
"execution_count": 407,
"id": "207b0bd2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.44205322265625"
]
},
"execution_count": 407,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def huffman(image):\n",
" origin, predict, diff, error, A = plot_hist(image)\n",
" image = Image.open(image)\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",
" \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",
" \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",
" new_error = np.ravel(new_error)\n",
" \n",
" # return the huffman dictionary\n",
" return encode1, encode2, encode3, encode4, encode5, np.ravel(image), error, diff, boundary\n",
"\n",
"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] <= 25:\n",
" c_len += len(encode2[str(int(error[i]))])\n",
"\n",
" if diff[i] <= 40 and diff[i] > 25:\n",
" c_len += len(encode3[str(int(error[i]))])\n",
" \n",
" if diff[i] <= 70 and diff[i] > 40:\n",
" c_len += len(encode4[str(int(error[i]))])\n",
" \n",
" if diff[i] > 70:\n",
" c_len += len(encode5[str(int(error[i]))])\n",
" \n",
" return c_len/o_len\n",
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"encode1, encode2, encode3, encode4, encode5, image, error, diff, boundary = huffman(images[0])\n",
"compress_rate(image, error, diff, boundary, encode1, encode2, encode3, encode4, encode5)\n"
]
},
{
"cell_type": "markdown",
"id": "3a3f06a5",
"metadata": {},
"source": [
"### Huffman with dividing into uniform bins"
]
},
{
"cell_type": "code",
"execution_count": 415,
"id": "14075c94",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.4432273356119792"
]
},
"execution_count": 415,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def huffman_u(image):\n",
" origin, predict, diff, error, A = plot_hist(image)\n",
" image = Image.open(image)\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",
" bins = np.linspace(min(diff),max(diff),5)[1:-1]\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 <= bins[0]\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 > bins[0]\n",
" new_error = error[mask]\n",
" mask2 = diff[mask] <= bins[1]\n",
" string = [str(i) for i in new_error[mask2].astype(int)]\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",
" encode3 = huffman_code_tree(node)\n",
" \n",
"\n",
" mask = diff > bins[1]\n",
" new_error = error[mask]\n",
" mask2 = diff[mask] <= bins[2]\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 > bins[2]\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",
" \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",
" new_error = np.ravel(new_error)\n",
" \n",
" # return the huffman dictionary\n",
" #return encode1, encode2, encode3, encode4, encode5, np.ravel(image), error, diff, boundary\n",
" return [encode1, encode2, encode3, encode4, encode5], np.ravel(image), error, diff, boundary, bins\n",
"\n",
"#def compress_rate_u(image, error, diff, bound, encode1, encode2, encode3, encode4, encode5):\n",
"def compress_rate_u(image, error, diff, bound, list_dic, bins):\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(list_dic[0][str(bound[i])])\n",
" \n",
" for i in range(0, len(original)):\n",
" o_len += len(bin(original[i])[2:])\n",
" if diff[i] <= bins[0]:\n",
" c_len += len(list_dic[1][str(int(error[i]))])\n",
" \n",
" if diff[i] <= bins[1] and diff[i] > bins[0]:\n",
" c_len += len(list_dic[2][str(int(error[i]))])\n",
" \n",
" if diff[i] <= bins[2] and diff[i] > bins[1]:\n",
" c_len += len(list_dic[3][str(int(error[i]))])\n",
" \n",
" if diff[i] > bins[2]:\n",
" c_len += len(list_dic[4][str(int(error[i]))])\n",
" \n",
" return c_len/o_len\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f8b93cc5",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 417,
"id": "6abed5da",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Compression rate of huffman with different bins: 0.44946919759114584\n",
"Compression rate of huffman without bins: 0.4513634314749933\n",
"Compression rate of huffman with uniform bins: 0.44956921895345053\n"
]
}
],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"num_images = im_distribution(images, \"_9\")\n",
"rate = []\n",
"rate_nb = []\n",
"rate_u = []\n",
"for i in range(len(num_images)):\n",
" encode1, encode2, encode3, encode4, encode5, image, error, diff, bound = huffman(num_images[i])\n",
" r = compress_rate(image, error, diff, bound, encode1, encode2, encode3, encode4, encode5)\n",
" rate.append(r)\n",
" encoding, error, image = huffman_nb(num_images[i])\n",
" r = compress_rate_nb(image, error, encoding)\n",
" rate_nb.append(r)\n",
" encode1, encode2, encode3, image, error, diff, bound = huffman_u(num_images[i])\n",
" r = compress_rate_u(image, error, diff, bound, encode1, encode2, encode3)\n",
" rate_u.append(r)\n",
" \n",
"print(f\"Compression rate of huffman with different bins: {np.mean(rate)}\")\n",
"print(f\"Compression rate of huffman without bins: {np.mean(rate_nb)}\")\n",
"print(f\"Compression rate of huffman with uniform bins: {np.mean(rate_u)}\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "15eecad3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.4427516682942708"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def huffman(image):\n",
" origin, predict, diff, error, A = plot_hist(image)\n",
" image = Image.open(image)\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 <= 10\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 > 10\n",
" new_error = error[mask]\n",
" mask2 = diff[mask] <= 25\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 > 25\n",
" new_error = error[mask]\n",
" mask2 = diff[mask] <= 45\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 > 45\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",
" \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",
" new_error = np.ravel(new_error)\n",
" \n",
" # return the huffman dictionary\n",
" return encode1, encode2, encode3, encode4, encode5, np.ravel(image), error, diff, boundary\n",
"\n",
"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",
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"encode1, encode2, encode3, encode4, encode5, image, error, diff, boundary = huffman(images[0])\n",
"compress_rate(image, error, diff, boundary, encode1, encode2, encode3, encode4, encode5)\n"
]
},
{
"cell_type": "code",
"execution_count": 428,
"id": "f8a8c717",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Compression rate of huffman with different bins: 0.4488415273030599\n"
]
}
],
"source": [
"scenes = file_extractor()\n",
"images = image_extractor(scenes)\n",
"num_images = im_distribution(images, \"_9\")\n",
"rate = []\n",
"\n",
"for i in range(len(num_images)):\n",
" encode1, encode2, encode3, encode4, encode5, image, error, diff, bound = huffman(num_images[i])\n",
" r = compress_rate(image, error, diff, bound, encode1, encode2, encode3, encode4, encode5)\n",
" rate.append(r)\n",
" \n",
" \n",
"print(f\"Compression rate of huffman with different bins: {np.mean(rate)}\")\n"
]
},
{
"cell_type": "code",
"execution_count": 238,
"id": "992dd8bb",
"metadata": {},
"outputs": [],
"source": [
"origin, predict, diff, error, A = plot_hist(images[0])"
]
},
{
"cell_type": "code",
"execution_count": 418,
"id": "904ba7b1",
"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"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.hist(error,bins=50)\n",
"plt.show()\n",
"mask = diff <= 20\n",
"plt.hist(error[mask],bins=50)\n",
"plt.show()\n",
"\n",
"mask = diff > 20\n",
"new_error = error[mask]\n",
"mask2 = diff[mask] <= 35\n",
"plt.hist(new_error[mask2],bins=50)\n",
"plt.show()\n",
"\n",
"mask = diff > 35\n",
"new_error = error[mask]\n",
"mask2 = diff[mask] <= 50\n",
"plt.hist(new_error[mask2],bins=50)\n",
"plt.show()\n",
"\n",
"mask = diff > 50\n",
"#new_error = error[mask]\n",
"#mask2 = diff[mask] <= 400\n",
"plt.hist(error[mask],bins=50)\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 236,
"id": "2f5ef010",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(512, 640)\n"
]
}
],
"source": [
"image = Image.open(images[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",
"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",
"print(image.shape)"
]
},
{
"cell_type": "code",
"execution_count": 228,
"id": "4860903b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[22554 -2 -35 ... -16 40 19]\n"
]
}
],
"source": [
"print(boundary)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f145c221",
"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
}
......@@ -430,8 +430,8 @@
" c_len = 0\n",
" # initializing the varible \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",
" real_b = np.hstack((image[0,:],image[-1,:],image[1:-1,0],image[1:-1,-1]))\n",
" original = image[1:-1,1:-1].reshape(-1)\n",
" diff = diff.reshape(-1)\n",
" \n",
" # calculate the bit for boundary\n",
......
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