Unit 2.2 Data Compression, Coding and Images Insights (notebook)
Lab will perform alterations on images, manipulate RGB values, and reduce the number of pixels. College Board requires you to learn about Lossy and Lossless compression.
- Image Files and Size Code and Notes
- Reading and Encoding Images (2 implementations follow) and Data Structures, Imperative Programming Style, and working with Images Code and Notes
- We shrink files in order to save speed and storage.
- Reduction of bits saves storage and saves transmision time
- Lossy data reduces data but the original is not recovered
- Lossless data lets you restore and recover
- Often when we work with files we use c: and cd to take us towards a certain directory
Questions
- Describe some of the meta data and considerations when managing Image files. Describe how these relate to Data Compression ...
- File Type, PNG and JPG are two types used in this lab
- It is important to know the file type of the image file, such as PNG or JPG, as different file types have different compression techniques and levels of compression
- Size, height and width, number of pixels
- Size, height and width, number of pixels: The size of an image file is measured in terms of the number of pixels it contains, which is determined by its height and width.
- The more pixels an image has, the larger its file size will be. It is important to consider the size of the image file as it can affect the loading time of the image.
- Visual perception, lossy compression
- When compressing image files, it is important to consider how the compression will affect the visual quality of the image. Lossy compression techniques, which reduce file size by discarding some of the image data, can result in a loss of visual quality that may be noticeable to the human eye.
- Data compression is the process of reducing the size of an image file by removing or compressing redundant information.
- This can be achieved through lossy or lossless compression techniques. Lossy compression techniques discard some of the image data, resulting in a smaller file size but reduced image quality, while lossless compression techniques maintain image quality but may not achieve as much compression.
- File Type, PNG and JPG are two types used in this lab
Displaying images in Python Jupyter notebook
Python Libraries and Concepts used for Jupyter and Files/Directories
IPython
Support visualization of data in Jupyter notebooks. Visualization is specific to View, for the web visualization needs to be converted to HTML.
pathlib
File paths are different on Windows versus Mac and Linux. This can cause problems in a project as you work and deploy on different Operating Systems (OS's), pathlib is a solution to this problem.
Questions
- What are commands you use in terminal to access files?
- ls - list the contents of the current directory
- cd - change directory to a specified location
- pwd - print the current working directory
- mkdir - create a new directory
- rm - remove a file or directory
- cp - copy a file or directory
- mv - move a file or directory
- What are the command you use in Windows terminal to access files?
- dir - list the contents of the current directory
- cd - change directory to a specified location
- cd.. - move up one directory level
- md - create a new directory
- rd - remove a directory
- copy - copy a file or directory
- move - move a file or directory
- What are some of the major differences?
- One of the major differences between the two sets of commands is the syntax used. In Linux/Unix, commands and file paths are typically separated by forward slashes, while in Windows, they are separated by backslashes.
- Additionally, Linux/Unix commands are often shorter and more concise, using single-letter flags to modify their behavior, while Windows commands are often longer and more descriptive, using full words and phrases to specify options and parameters.
- Another difference is that Windows commands are typically case-insensitive, while Linux/Unix commands are case-sensitive.
- Why is path a big deal when working with images?
- Path is a big deal when working with images because it allows the software or application to locate the image file on the computer or network. Without the correct path, the software or application will not be able to find and display the image. This is particularly important when working with images in programming, where the path is specified in code and needs to be accurate.
- How does the meta data source and label relate to Unit 5 topics?
- The metadata source and label are important in Unit 5 topics, particularly in the context of supervised learning. Metadata such as image dimensions, file type, and compression type can provide useful information about the image and help in preprocessing and feature extraction.
- Labels can also provide important information about the image, such as the object or category it belongs to, which can be used to train and test machine learning models.
- Look up IPython, describe why this is interesting in Jupyter Notebooks for both Pandas and Images?
- IPython is an interactive command-line shell for Python that provides enhanced functionality, such as tab completion, object introspection, and inline plotting. It is particularly useful in Jupyter Notebooks, where it allows for interactive exploration and analysis of data.
- In Jupyter Notebooks, IPython can be used with both Pandas and Images.
- With Pandas, IPython allows for interactive data exploration and manipulation, making it easier to analyze and clean data.
- With Images, IPython can be used to display and manipulate images inline, allowing for real-time visualization and preprocessing of images. This can be especially useful in computer vision tasks where image preprocessing and analysis is an important part of the workflow.
- In Jupyter Notebooks, IPython can be used with both Pandas and Images.
- IPython is an interactive command-line shell for Python that provides enhanced functionality, such as tab completion, object introspection, and inline plotting. It is particularly useful in Jupyter Notebooks, where it allows for interactive exploration and analysis of data.
from IPython.display import Image, display
from pathlib import Path # https://medium.com/@ageitgey/python-3-quick-tip-the-easy-way-to-deal-with-file-paths-on-windows-mac-and-linux-11a072b58d5f
# prepares a series of images
def image_data(path=Path("images/"), images=None): # path of static images is defaulted
if images is None: # default image
images = [
{'source': "Peter Carolin", 'label': "Clouds Impression", 'file': "clouds-impression.png"},
{'source': "Peter Carolin", 'label': "Lassen Volcano", 'file': "lassen-volcano.jpg"}
]
for image in images:
# File to open
image['filename'] = path / image['file'] # file with path
return images
def image_display(images):
for image in images:
display(Image(filename=image['filename']))
# Run this as standalone tester to see sample data printed in Jupyter terminal
if __name__ == "__main__":
# print parameter supplied image
green_square = image_data(images=[{'source': "Internet", 'label': "Green Square", 'file': "green-square-16.png"}])
image_display(green_square)
# display default images from image_data()
default_images = image_data()
image_display(default_images)
Reading and Encoding Images
- When we are now working on this data and images unit
Base 64
- converts binary encoded data into an encoded scheme of 24 bits and 6 base64 bits.
- It is used to transport and embed binary images into textual assets such as HTML and CSS
- First 3 letters of my name in Base64: TGlh ### Numpy
- an artificial intelligence data science tool
- Mort uses them to manipulate and grab images ### io, BytesIO
- Input and Output (I/O) is a fundamental of all Computer Programming. Input/output (I/O) buffering is a technique used to optimize I/O operations.
- In large quantities of data, how many frames of input the server currently has queued is the buffer. #### Questions
- Where have you been a consumer of buffering?
- As a consumer, buffering is a common issue that I often encounter. Buffering occurs when the playback of media content is interrupted due to slow internet connection, network congestion, or limited system resources. When buffering occurs, the media content will stop playing and a loading icon or message may be displayed while the content is being buffered. This is really annoying and a big part of my digital expirience.
- From your consumer experience, what effects have you experienced from buffering?
- Interruptions in media playback: Buffering can cause interruptions in media playback, which can be frustrating for the consumer, especially if the content is being streamed in real-time or contains important information.
- Delayed or slow playback: Buffering can cause delayed or slow playback, which can negatively affect the user's experience and perception of the quality of the media content.
- Reduced image quality: Buffering can cause the image quality of media content to be reduced due to compression and other techniques used to speed up buffering.
- How do these effects apply to images?
- In the context of images, buffering may occur when displaying large images or when loading images from a slow network or storage device.
- This can result in delayed or slow image loading, which can affect the user's experience and perception of the image quality.
- In addition, images that are compressed or resized for faster loading may lose some of their quality and detail, which can negatively impact the user's viewing experience.
Data Structures, Imperative Programming Style, and Working with Images
Most data structures classes require Object Oriented Programming (OOP). Since this class is lined up with a College Course, OOP will be talked about often. Functionality in remainder of this Blog is the same as the prior implementation
Imperative Programing
- a programming paradigm that emphasizes giving the computer a set of instructions to follow, which are executed sequentially.
- It is often compared to a list of steps that a person might take to complete a task.
- Imperative programming languages focus on the "how" of a task rather than the "what" or "why". Examples of imperative programming languages include C, Fortran, and Assembly
OOP
- a programming paradigm that focuses on objects as the fundamental unit of programming. OOP is based on the idea that objects are made up of data and behavior, and that objects interact with each other to perform tasks.
- The key features of OOP include encapsulation, inheritance, and polymorphism.
- Examples of OOP languages include Java, Python, and Ruby.
Differences
- Data and behavior:In imperative programming, data and behavior are often separate, and functions or procedures manipulate data. In OOP, data and behavior are encapsulated within objects.- Procedural vs. Object-Oriented: Imperative programming is often procedural, meaning that it relies on a series of procedures or functions to accomplish a task. OOP is based on objects that interact with each other to accomplish a task.
- Abstraction: OOP provides abstraction, meaning that objects can hide their internal workings and expose only a public interface. Imperative programming is less abstract, and typically exposes more of the internal workings of a program.
- Flexibility: OOP is generally more flexible and adaptable than imperative programming, due to its ability to encapsulate data and behavior within objects. Imperative programming can be more rigid, as it is often based on a series of procedures or functions that are executed sequentially.
from IPython.display import HTML, display
from pathlib import Path # https://medium.com/@ageitgey/python-3-quick-tip-the-easy-way-to-deal-with-file-paths-on-windows-mac-and-linux-11a072b58d5f
from PIL import Image as pilImage # as pilImage is used to avoid conflicts
from io import BytesIO
import base64
import numpy as np
# prepares a series of images
def image_data(path=Path("../images/"), images=None): # path of static images is defaulted
if images is None: # default image
images = [
{'source': "Internet", 'label': "Green Square", 'file': "green-square-16.png"},
{'source': "Peter Carolin", 'label': "Clouds Impression", 'file': "clouds-impression.png"},
{'source': "Peter Carolin", 'label': "Lassen Volcano", 'file': "lassen-volcano.jpg"},
{'source': "Liav Bar", 'label': "smiley face", 'file': "smiley2.png"}
]
for image in images:
# File to open
image['filename'] = path / image['file'] # file with path
return images
# Large image scaled to baseWidth of 320
def scale_image(img):
baseWidth = 320
scalePercent = (baseWidth/float(img.size[0]))
scaleHeight = int((float(img.size[1])*float(scalePercent)))
scale = (baseWidth, scaleHeight)
return img.resize(scale)
# PIL image converted to base64
def image_to_base64(img, format):
with BytesIO() as buffer:
img.save(buffer, format)
return base64.b64encode(buffer.getvalue()).decode()
# Set Properties of Image, Scale, and convert to Base64
def image_management(image): # path of static images is defaulted
# Image open return PIL image object
img = pilImage.open(image['filename'])
# Python Image Library operations
image['format'] = img.format
image['mode'] = img.mode
image['size'] = img.size
# Scale the Image
img = scale_image(img)
image['pil'] = img
image['scaled_size'] = img.size
# Scaled HTML
image['html'] = '<img src="data:image/png;base64,%s">' % image_to_base64(image['pil'], image['format'])
# Create Grey Scale Base64 representation of Image
def image_management_add_html_grey(image):
# Image open return PIL image object
img = image['pil']
format = image['format']
img_data = img.getdata() # Reference https://www.geeksforgeeks.org/python-pil-image-getdata/
image['data'] = np.array(img_data) # PIL image to numpy array
image['gray_data'] = [] # key/value for data converted to gray scale
# 'data' is a list of RGB data, the list is traversed and hex and binary lists are calculated and formatted
for pixel in image['data']:
# create gray scale of image, ref: https://www.geeksforgeeks.org/convert-a-numpy-array-to-an-image/
average = (pixel[0] + pixel[1] + pixel[2]) // 3 # average pixel values and use // for integer division
if len(pixel) > 3:
image['gray_data'].append((average, average, average, pixel[3])) # PNG format
else:
image['gray_data'].append((average, average, average))
# end for loop for pixels
img.putdata(image['gray_data'])
image['html_grey'] = '<img src="data:image/png;base64,%s">' % image_to_base64(img, format)
def image_management_add_html_red(image):
# Image open return PIL image object
img = image['pil']
format = image['format']
img_data = img.getdata() # Reference https://www.geeksforgeeks.org/python-pil-image-getdata/
image['data'] = np.array(img_data) # PIL image to numpy array
image['red_data'] = [] # key/value for data converted to gray scale
# 'data' is a list of RGB data, the list is traversed and hex and binary lists are calculated and formatted
for pixel in image['data']:
# create gray scale of image, ref: https://www.geeksforgeeks.org/convert-a-numpy-array-to-an-image/
redscale = 255 - (pixel[0])
average = (pixel[0] + pixel[1] + pixel[2]) // 3 # average pixel values and use // for integer division
if len(pixel) > 3:
image['red_data'].append((redscale, average, average, pixel[3])) # PNG format
else:
image['red_data'].append((redscale, average, average))
# end for loop for pixels
img.putdata(image['red_data'])
image['html_red'] = '<img src="data:image/png;base64,%s">' % image_to_base64(img, format)
# Jupyter Notebook Visualization of Images
if __name__ == "__main__":
# Use numpy to concatenate two arrays
images = image_data()
# Display meta data, scaled view, and grey scale for each image
for image in images:
image_management(image)
print("---- meta data -----")
print(image['label'])
print(image['source'])
print(image['format'])
print(image['mode'])
print("Original size: ", image['size'])
print("Scaled size: ", image['scaled_size'])
print("-- original image --")
display(HTML(image['html']))
print("--- grey image ----")
image_management_add_html_grey(image)
display(HTML(image['html_grey']))
image_management_add_html_red(image)
display(HTML(image['html_red']))
print()
Data Structures and OOP Code and Notes
Questions
- Does this code seem like a series of steps are being performed?
-
Describe Grey Scale algorithm in English or Pseudo code?
- A grayscale algorithm converts a color image into a black and white image by removing the color information and retaining only the luminance or brightness values of each pixel. The algorithm works as follows:
- Load the color image into memory.
- Iterate through each pixel of the image.
- For each pixel, calculate the grayscale value using the formula:
- grayscale = (0.299 red) + (0.587 green) + (0.114 * blue) where red, green, and blue are the color values of the pixel.
- Assign the calculated grayscale value to the pixel.
- Save the grayscale image to disk.
- A grayscale algorithm converts a color image into a black and white image by removing the color information and retaining only the luminance or brightness values of each pixel. The algorithm works as follows:
-
Describe scale image? What is before and after on pixels in three images?
- A scaled image is an image that has been resized to either be smaller or larger than its original size. Scaling an image involves changing the number of pixels that make up the image, which can affect its overall quality and clarity.
- In order to scale an image, a mathematical formula is used to determine how the pixels should be adjusted.
- When scaling an image to be larger, new pixels are added to the image to increase its size. Conversely, when scaling an image to be smaller, some of the original pixels are removed or combined to decrease its size.
-
Examples:
-
Image 1: Original size: 1000 x 1000 pixels Scaled size: 500 x 500 pixels (50% of original size)
-
Image 2: Original size: 1000 x 1000 pixels Scaled size: 2000 x 2000 pixels (200% of original size)
-
Image 3: Original size: 1000 x 1000 pixels Scaled size: 100 x 100 pixels (10% of original size)
-
- Is scale image a type of compression? If so, line it up with College Board terms described?
- Scaling an image is not considered a type of compression because it does not involve any reduction in the file size of the image. When an image is compressed, the file size is reduced by either removing some of the data or by encoding the data in a more efficient way.
- Compression is usually used to reduce the file size of an image to make it easier to store, transmit or load.
- On the other hand, scaling an image is simply a process of resizing the image to make it larger or smaller without reducing its file size or changing its format. Scaling an image can, however, impact the visual quality of the image.
- If the image is scaled down, the reduction in the number of pixels may lead to loss of details or blurriness. If the image is scaled up, it may result in pixelation or distortion.
- Scaling an image is not considered a type of compression because it does not involve any reduction in the file size of the image. When an image is compressed, the file size is reduced by either removing some of the data or by encoding the data in a more efficient way.
from IPython.display import HTML, display
from pathlib import Path # https://medium.com/@ageitgey/python-3-quick-tip-the-easy-way-to-deal-with-file-paths-on-windows-mac-and-linux-11a072b58d5f
from PIL import Image as pilImage # as pilImage is used to avoid conflicts
from io import BytesIO
import base64
import numpy as np
class Image_Data:
def __init__(self, source, label, file, path, baseWidth=320):
self._source = source # variables with self prefix become part of the object,
self._label = label
self._file = file
self._filename = path / file # file with path
self._baseWidth = baseWidth
# Open image and scale to needs
self._img = pilImage.open(self._filename)
self._format = self._img.format
self._mode = self._img.mode
self._originalSize = self.img.size
self.scale_image()
self._html = self.image_to_html(self._img)
self._html_grey = self.image_to_html_grey()
@property
def source(self):
return self._source
@property
def label(self):
return self._label
@property
def file(self):
return self._file
@property
def filename(self):
return self._filename
@property
def img(self):
return self._img
@property
def format(self):
return self._format
@property
def mode(self):
return self._mode
@property
def originalSize(self):
return self._originalSize
@property
def size(self):
return self._img.size
@property
def html(self):
return self._html
@property
def html_grey(self):
return self._html_grey
# Large image scaled to baseWidth of 320
def scale_image(self):
scalePercent = (self._baseWidth/float(self._img.size[0]))
scaleHeight = int((float(self._img.size[1])*float(scalePercent)))
scale = (self._baseWidth, scaleHeight)
self._img = self._img.resize(scale)
# PIL image converted to base64
def image_to_html(self, img):
with BytesIO() as buffer:
img.save(buffer, self._format)
return '<img src="data:image/png;base64,%s">' % base64.b64encode(buffer.getvalue()).decode()
# Create Grey Scale Base64 representation of Image
def image_to_html_grey(self):
img_grey = self._img
numpy = np.array(self._img.getdata()) # PIL image to numpy array
grey_data = [] # key/value for data converted to gray scale
# 'data' is a list of RGB data, the list is traversed and hex and binary lists are calculated and formatted
for pixel in numpy:
# create gray scale of image, ref: https://www.geeksforgeeks.org/convert-a-numpy-array-to-an-image/
average = (pixel[0] + pixel[1] + pixel[2]) // 3 # average pixel values and use // for integer division
if len(pixel) > 3:
grey_data.append((average, average, average, pixel[3])) # PNG format
else:
grey_data.append((average, average, average))
# end for loop for pixels
img_grey.putdata(grey_data)
return self.image_to_html(img_grey)
# prepares a series of images, provides expectation for required contents
def image_data(path=Path("../images/"), images=None): # path of static images is defaulted
if images is None: # default image
images = [
{'source': "Internet", 'label': "Green Square", 'file': "green-square-16.png"},
{'source': "Peter Carolin", 'label': "Clouds Impression", 'file': "clouds-impression.png"},
{'source': "Peter Carolin", 'label': "Lassen Volcano", 'file': "lassen-volcano.jpg"},
{'source': "Liav Bar", 'label': "smiley face", 'file': "smiley2.png"}
]
return path, images
# turns data into objects
def image_objects():
id_Objects = []
path, images = image_data()
for image in images:
id_Objects.append(Image_Data(source=image['source'],
label=image['label'],
file=image['file'],
path=path,
))
return id_Objects
# Jupyter Notebook Visualization of Images
if __name__ == "__main__":
for ido in image_objects(): # ido is an Imaged Data Object
print("---- meta data -----")
print(ido.label)
print(ido.source)
print(ido.file)
print(ido.format)
print(ido.mode)
print("Original size: ", ido.originalSize)
print("Scaled size: ", ido.size)
print("-- scaled image --")
display(HTML(ido.html))
print("--- grey image ---")
display(HTML(ido.html_grey))
print()
Hacks
Early Seed award
- Add this Blog to you own Blogging site.
- In the Blog add a Happy Face image.
- Have Happy Face Image open when Tech Talk starts, running on localhost. Don't tell anyone. Show to Teacher.
- See Above
AP Prep
- In the Blog add notes and observations on each code cell that request an answer.
- In blog add College Board practice problems for 2.3
- Choose 2 images, one that will more likely result in lossy data compression and one that is more likely to result in lossless data compression. Explain.
- Here are two sample images, one that is more likely to result in lossy compression and one that is more likely to result in lossless compression:
Lossy Compression:
- The image above is a photograph of a tree, which contains a lot of detail and varying colors. This type of image is more likely to result in lossy compression because lossy compression techniques work by removing some of the details and color information that the human eye may not perceive.
- In this image, lossy compression could reduce the number of colors, blur some edges, and remove some fine details, resulting in a smaller file size.
Lossless Compression:
- The image above is a landscape photograph of a desert, which contains large areas of the same color and fewer details than the tree photograph. This type of image is more likely to result in lossless compression because lossless compression techniques work by finding patterns and redundancies in the data and encoding them in a more efficient way.
- In this specific image, lossless compression could be achieved by encoding the areas of the same color using fewer bits and by finding patterns in the pixels that repeat. The result would be a smaller file size, but with no loss of detail or quality.
- In general, lossy compression is best suited for images with a lot of detail and color variation, such as photographs, while lossless compression is more suitable for images with large areas of the same color and fewer details, such as diagrams, charts, or graphs.
Project Addition
- If your project has images in it, try to implement an image change that has a purpose. (Ex. An item that has been sold out could become gray scale)
- My project has nothing to do with images and there are no images in it, so there is nothing I can do to it.
Pick a programming paradigm and solve some of the following ...
- Numpy, manipulating pixels. As opposed to Grey Scale treatment, pick a couple of other types like red scale, green scale, or blue scale. We want you to be manipulating pixels in the image.
- I picked this option, see the redscale images above
- Binary and Hexadecimal reports. Convert and produce pixels in binary and Hexadecimal and display.
- Compression and Sizing of images. Look for insights into compression Lossy and Lossless. Look at PIL library and see if there are other things that can be done.
- There are many effects you can do as well with PIL. Blur the image or write Meta Data on screen, aka Title, Author and Image size.