Python Libraries and Concepts used for Jupyter and Files/Directories

Introduction to displaying images in Jupyter notebook

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.

  • What are commands you use in terminal to access files?
  • What are the command you use in Windows terminal to access files?
  • What are some of the major differences?

Provide what you observed, struggled with, or leaned while playing with this code.

  • Why is path a big deal when working with images?
  • How does the meta data source and label relate to Unit 5 topics?
  • Look up IPython, describe why this is interesting in Jupyter Notebooks for both Pandas and Images?
from IPython.display import Image, display
from pathlib import Path  
def image_data(path=Path("../images"), images=None): 
    if images is None: 
        images = [
            {'source': "Peter Carolin", 'label': "Clouds Impression", 'file': "logo.png"},
        ]
    for image in images:
        image['filename'] = path / image['file']  
    return images

def image_display(images):
    for image in images:  
        display(Image(filename=image['filename']))


if __name__ == "__main__":
    default_images = image_data()
    image_display(default_images)
    
from IPython.display import HTML, display
from pathlib import Path 
from PIL import Image, ImageDraw
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 
        self._label = label
        self._file = file
        self._filename = path / file 
        self._baseWidth = baseWidth


        self._img = Image.open(self._filename)
        self._format = self._img.format
        self._mode = self._img.mode
        self._originalSize = self.img.size
        self.scale_image()

        self.write_metadata()
        
        self._html = self.image_to_html(self._img)
        self._html_grey = self.image_to_html_grey()
        self._html_dark = self.image_to_html_dark()

    @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
    
    @property
    def html_dark(self):
        return self._html_dark
        
    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)
    
    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()
    
    def write_metadata(self):

        draw_image = ImageDraw.Draw(self.img) 

        draw_image.text((10, 10), "Source: " + self.source, fill=(10, 10, 10, 128))
        draw_image.text((10, 20), "Label: " + self.label, fill=(10, 10, 10, 128))
        draw_image.text((10, 30), "Path: " + str(self.filename), fill=(10, 10, 10, 128))

    def image_to_html_grey(self):
        img_grey = self._img
        numpy = np.array(self._img.getdata()) 
        
        grey_data = [] 
        for pixel in numpy:
            average = (pixel[0] + pixel[1] + pixel[2]) // 3
            if len(pixel) > 3:
                grey_data.append((average, average, average, pixel[3]))
            else:
                grey_data.append((average, average, average))
            
        img_grey.putdata(grey_data)
        return self.image_to_html(img_grey)
    
    def image_to_html_dark(self):
        img_dark = self._img
        numpy = np.array(self._img.getdata()) 
        
        dark_data = [] 
        for pixel in numpy:
            average = (pixel[0] + pixel[1] + pixel[2]) // 9
            if len(pixel) > 3:
                dark_data.append((average, average, average, pixel[3]))
            else:
                dark_data.append((average, average, average))
            
        img_dark.putdata(dark_data)
        return self.image_to_html(img_dark)

class Draw_Image:
    def __init__(self, mode: str, size: tuple, color: tuple):
        self._new_image = Image.new(mode, size, color)
        self._img = ImageDraw.Draw(self.new_image)

    @property
    def img(self):
        return self._img
    
    @property
    def new_image(self):
        return self._new_image

    @property
    def html(self):
        return self._html
    
    def draw_rectangle(self, xy: list, fill: tuple, outline: tuple, width: int):
        self.img.rectangle(xy, fill, outline, width)
    
    def image_to_html(self):
        with BytesIO() as buffer:
            self.new_image.save(buffer, format='PNG')
            return '<img src="data:image/png;base64,%s">' % base64.b64encode(buffer.getvalue()).decode()
    
def image_data(path=Path("../images/"), images=None):
    if images is None:
        images = [
            {'source': "Jamal", 'label': "Smiley Face", 'file': "smiley-face.jpg"},
            {'source': "Jamal", 'label': "Jamal", 'file': "jamal.jpg"},
            {'source': "Jamal", 'label': "Mort", 'file': "mort.jpg"},
        ]
    return path, images

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

def drawn_image_objects():        
    drawn_objects = []

    drawn_image1 = Draw_Image("RGBA", (400, 400), (15, 252, 3))
    drawn_image1.draw_rectangle(xy=[50, 50, 150, 150], fill=(8, 8, 8), outline=1, width=1)
    drawn_image1.draw_rectangle(xy=[350, 50, 250, 150], fill=(235, 23, 34), outline=1, width=1)
    drawn_image1.draw_rectangle(xy=[50, 350, 350, 300], fill=(250, 245, 245), outline=1, width=1)

    drawn_image2 = Draw_Image("RGBA", (400, 400), (191, 10, 176))
    drawn_image2.draw_rectangle(xy=[50, 50, 150, 150], fill=(8, 8, 8), outline=1, width=1)
    drawn_image2.draw_rectangle(xy=[350, 50, 250, 150], fill=(235, 23, 34), outline=1, width=1)
    drawn_image2.draw_rectangle(xy=[50, 350, 350, 300], fill=(250, 245, 245), outline=1, width=1)

    drawn_objects.append(drawn_image1)
    drawn_objects.append(drawn_image2)

    return drawn_objects

if __name__ == "__main__":
    for ido in image_objects():
        
        print("-- original image --")
        display(HTML(ido.html))
        
        print("--- grey image ---")
        display(HTML(ido.html_grey))

        print("--- darkened image ---")
        display(HTML(ido.html_dark))


    for drawn_image in drawn_image_objects():

        print("--- drawn image ---")
        display(HTML(drawn_image.image_to_html()))
        
    print()
-- original image --
--- grey image ---
--- darkened image ---
-- original image --
--- grey image ---
--- darkened image ---
-- original image --
--- grey image ---
--- darkened image ---
--- drawn image ---
--- drawn image ---

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, don't tell anyone. Show to Teacher.

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.

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)

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, dark scale, or blue scale. We want you to be manipulating pixels in the image.
  • 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.