Chapter 9 Inage Processing and Perception
-----------------------------------------

What is an image?

pic = takePicture()
show(pic)

pixel = picture element

Scribbler's camera has a resolution of 256x192
i.e. 256 pixels width and 192 pixels height

For a color picture, each pixel needs 3 bytes of data:
(byte = 8 bits; bit can store a 0 or a 1)
R: 0..255, G: 0..255, B: 0..255

For a gray scale picture, each pixel needs only 1 byte of data:
0..255 with 0 representing BLACK and 255 representing WHITE

A good digital camera has much higher resolutions.
e.g. 12 Mega Pixels (4000x3000)

Scribbler's camera: 0.049 Mega Pixels!!

Compression Techniques: data in an image can be compressed to
use up less storage.

JPEG: one of the better formats with excellent compression.

Myro Image Basics
-----------------

picWidth = getWidth(pic)
picHeight = getHeight(pic)

savePicture(pic, "OfficeScene.jpg")
or
savePicture(pic, "OfficeScene.gif")

p = makePicture("photo1.jpg")
show(p)

pickAFile()

p = makePicture(pickAFile())
show(p,"Lotus Temple")

Robot explorer
--------------
joyStick()
for i in range(25):
  pic = takePicture("gray")
  show(pic)

The above program activates the joystick device and then takes 
25 pictures showing each one of them. As the pictures are taken and 
shown, the user can use the joystick device to move the robot
around... Mars explorer...

Animated GIF movies
-------------------

pictureList = []
for i in range(15):
  pic = takePicture()
  pictureList = pictureList + [pic]  # another way to append!
  turnLeft(0.5,0.1)
savePicture(pictureList,"rotatingMovie.gif")

Making Pictures
---------------

The makePicture() function can be used to make pictures as well.

W = 100
H = 100
newPic = makePicture(W,H,black)

## black is a predefined color object

This creates a 100x100 image with black pixels throught the image.

for x in range(W):
  for y in range(H):
    pix = getPixel(newPic,x,y)
    setColor(pix,white)
repaint(newPic)

This code sets all pixels to White color.
The repaint() function refreshes the image - so that you can view the
changes.
By moving the repaint() function call inside for-loop:

for x in range(W):
  for y in range(H):
    pix = getPixel(newPic,x,y)
    setColor(pix,white)
    repaint(newPic)

we will see the pixels changing from black to white bit by bit!
like watching paint drip!

color1 = makeColor(255,0,0)

This creates red color.

color2 = pickAColor()

This brings up a color palette for you to choose a color!

Setting and Getting color values for pixels:

setRGB(pixel, (255,0,0))

r, g, b = getRGB(pixel)

for-loop on all pixels of a picture:

for pix in getPixels(newPic):
  setColor(pix,gray)
repaint(newPic)

Shades of Gray
--------------
In JPG format, gray shades are coded as (v,v,v)

def gray(v):
  return makeColor(v,v,v)

Lets write a program that colors pixel at (x,y) using
gray(x+y)

MAX = 255
W = 100
H = 100
pic = makePicture(W,H)
for x in range(W):
    for y in range(H):
        setPixel(pic,x,y,gray((x+y)%(MAX+1)))
show(pic)

Try this with W=500 and H=500

Next change MAX to 50 and use the following gray() function:

def gray(v):
    #return makeColor(v,v,v)
    brightness = v*255/MAX
    return makeColor(brightness,brightness,brightness)

Next try x*y instead of x+y

Image Processing
----------------

Manipulating existing image files.

Shrinking and Enlarging:

Shrinking by a factor of F:
  new pixel at (x,y) is old pixel at (x*F,y*F)

Enlarging by a factor of F:
  new pixel at (x,y) is old pixel at (x/F,y/F)


############
from myro import *

def main():

    # read an image and display it
    oldPic = makePicture(pickAFile())
    show(oldPic, "Before")
    X = getWidth(oldPic)
    Y = getHeight(oldPic)
    
    # Input the shrink factor and computer size of new image
    F = int(ask("Enter the shrink factor."))
    newx = X/F
    newy = Y/F
    
    # create the new image
    newPic = makePicture(newx, newy)
    for x in range(1, newx):
        for y in range(1, newy):
            setPixel(newPic, x, y, getPixel(oldPic, x*F, y*F))
            # To enlarge comment above line and uncomment line below
            #setPixel(newPic, x, y, getPixel(oldPic, x/F, y/F))
    show(newPic, "After")

main()
############

Enlarging picture: creating data that was not present in old picture!
Blurred.

Blurring and Sharpening:

Blurring can be done by taking the average color values of neighboring pixels.
Size of neighborhood determines amount of blurring.

################################################
## BLURRING
from myro import *

def main():

    # read an image and display it
    oldPic = makePicture(pickAFile())
    show(oldPic, "Before")
    X = getWidth(oldPic)
    Y = getHeight(oldPic)
    
    # create the new image
    newPic = makePicture(X, Y)
    for x in range(1, X-1):
        for y in range(1, Y-1):
            n1 = getPixel(oldPic, x, y)
            n2 = getPixel(oldPic, x, y-1)
            n3 = getPixel(oldPic, x-1, y)
            n4 = getPixel(oldPic, x+1, y)
            n5 = getPixel(oldPic, x, y+1)
            r = (getRed(n1)+getRed(n2)+getRed(n3)+
                 getRed(n4)+getRed(n5))/5
            g = (getGreen(n1)+getGreen(n2)+getGreen(n3)+
                 getGreen(n4)+getGreen(n5))/5
            b = (getBlue(n1)+getBlue(n2)+getBlue(n3)+
                 getBlue(n4)+getBlue(n5))/5
            setPixel(newPic, x, y, makeColor(r, g, b))
    show(newPic, "After")

main()
################################################

Sharpening an image can be done by subtracting the 
neighbor color values instead of averaging.

################################################
from myro import *
## SHARPENING

def main():

    # read an image and display it
    oldPic = makePicture(pickAFile())
    show(oldPic, "Before")
    X = getWidth(oldPic)
    Y = getHeight(oldPic)
    
    # create the new image
    newPic = makePicture(X, Y)
    for x in range(1, X-1):
        for y in range(1, Y-1):
            n1 = getPixel(oldPic, x, y)
            n2 = getPixel(oldPic, x, y-1)
            n3 = getPixel(oldPic, x-1, y)
            n4 = getPixel(oldPic, x+1, y)
            n5 = getPixel(oldPic, x, y+1)
            r = 5*getRed(n1) - (getRed(n2)+getRed(n3)+
                                getRed(n4)+getRed(n5))
            g = 5*getGreen(n1) - (getGreen(n2)+getGreen(n3)+
                                getGreen(n4)+getGreen(n5))
            b = 5*getBlue(n1) - (getBlue(n2)+getBlue(n3)+
                                getBlue(n4)+getBlue(n5))
            setPixel(newPic, x, y, makeColor(r, g, b))
    show(newPic, "After")

main()
#######################################

Negative and Embossing:

Creating a negative: invert the pixel value

for gray-scale pictures: 255-v
for color pictures: (255-r,255-g,255-b)

#######################
## NEGATIVE
from myro import *

MAX = 255

def main():

    # read an image and display it
    oldPic = makePicture(pickAFile())
    show(oldPic, "Before")
    X = getWidth(oldPic)
    Y = getHeight(oldPic)
    
    # create the new image
    newPic = makePicture(X, Y)
    for x in range(X):
        for y in range(Y):
            pixel = getPixel(oldPic, x, y)
            r = MAX - getRed(pixel)
            b = MAX - getBlue(pixel)
            g = MAX - getGreen(pixel)
            setPixel(newPic, x, y, makeColor(r, g, b))
    show(newPic, "After")

main()
#################################

Emboss effect: 
subtract from current pixel value the value (or fraction thereof)
of a pixel 2 pixels away

####################
## EMBOSSING
## Two versions - one version in comments
from myro import *

MAX = 255

def main():

    # read an image and display it
    oldPic = makePicture(pickAFile())
    show(oldPic, "Before")
    X = getWidth(oldPic)
    Y = getHeight(oldPic)
    
    # create the new image
    newPic = makePicture(X, Y)
    for x in range(0, X-2):
        for y in range(0, Y-2):
            pixel1 = getPixel(oldPic, x, y)
            pixel2 = getPixel(oldPic, x+2, y+2)
#            r = getRed(pixel1) - getRed(pixel2)
#            b = getBlue(pixel1) - getBlue(pixel2)
#            g = getGreen(pixel1) - getGreen(pixel2)
            r = getRed(pixel1) + (MAX/2 - getRed(pixel2))
            g = getBlue(pixel1) + (MAX/2 - getBlue(pixel2))
            b = getGreen(pixel1) + (MAX/2 - getGreen(pixel2))
            setPixel(newPic, x, y, makeColor(r, g, b))
    show(newPic, "After")

main()
####################