The following is a gallery of images generated from my version of imagmanip.py, available here on github. On the one hand this assignment might seem like it sucks, but on the other hand working on a project with poor documentation is even worse...so I appreciate what is going on here. This is a nice way to document a library with example photos and the source code, but it would be nicer if there was a way to dynamically link the snippets to the functions in the github files in case the comments etc change. Or maybe just automatically generate the whole page with test code, test image set, and something like doxygen. Today though, we follow along with assignment!
As a side note it's important that setMediaPath() be called before using any of my functions that require several pictures so that you don't have to use absolute file names. Then I can call getMediaPath() to open that folder and grab pictures. Friends don't let friends use absolute file paths
Better black and white (lab #3)
Bottom-to-top mirror (lab #4)
There were a variety of mirroring functions in this project. This one, mirror vertical, lets you select if you want to mirror top to bottom or bottom to top(with a pyramid top to bottom looks better!). Then it traces from left to right copying the top row to the bottom row until it hits the middle of the picture. There were no real problems with this but it doesn't seem super fast.
# Function: Vertical image mirroring
# Params: 1) an image, 2) bool value for True mirrors top to bottom, False mirrors bottom to top
# Returns: mirrored image
def mirrorVertical(sourcePic, topBottom):
width = getWidth(sourcePic)
height = getHeight(sourcePic)
retPic = duplicatePicture(sourcePic)
yEnd = height / 2
# mirror top to bottom side of image
if topBottom == True:
for x in range(0, width):
for y in range(0, yEnd):
sourcePixel = getPixel(sourcePic, x, y)
destPixel = getPixel(retPic, x, height - y - 1)
sourceColor = getColor(sourcePixel)
setColor(destPixel, sourceColor)
#mirror bottom to top side of image
else:
for x in range(0, width):
for y in range(0, yEnd):
sourcePixel = getPixel(sourcePic, x, height - y - 1)
destPixel = getPixel(retPic, x, y)
sourceColor = getColor(sourcePixel)
setColor(destPixel, sourceColor)
return retPic
Shrink (lab #4)
Collage (lab #5)
Red-eye Reduction (lab #6)
Color Art-i-fy (lab #6)
Artify is a filter that basically bins an image. It has cutoff points which apply equally to each color. If you are inbetween certain thresholds then you get a fixed value. My real problem with this one was trying to index across an array of the rgb values and running the filter on them that way. Calling an extra function that does the binning of the colors worked fine though.
Here is the code I had a problem with before switching to a chunkier version.
for p in pixels:
r = getRed(p)
b = getBlue(p)
g = getGreen(p)
for color in [r, b, g]:
if color < 64:
color = 31
elif color < 128:
color = 95
elif color < 192:
color = 159
else:
color = 223
setRed(p, r)
setBlue(p, b)
setGreen(p, g)
So here we go with some functions and before/after photos.
Rose-colored glasses (lab #3)
This filter shows a bit of color modification. I decided to throw in an inversion at the end to really make it pop. Why invert? It makes it even more red. Like these blue glasses would end up being purple without the invert to really flip it. Also after completing all labs I went back through and changed them so that they never modify the original picture. I don't want things to get messy so it is nice to return the modified picture instead of changing the original. This comes at a cost of having 2 copies of the picture in memory but RAM is basically free these days and computers are really fast, which is why things like python are so popular I think.
# Function: reduce green to 30% and make everything pink inversely porportional to it's original pinkness
# Params: source pic
# Returns: rose colorized picture
def roseColoredGlasses(sourcePic):
retPic = duplicatePicture(sourcePic)
pixels = getPixels(retPic)
for p in pixels:
r = getRed(p)
b = getBlue(p)
g = getGreen(p)
setGreen(p, g * 0.3)
setRed(p, 255 - r)
setBlue(p, 255 - b)
return retPic
Negative (lab #3)
Don't be negative, unless you're working on lab 3 or talking about the CIA which is a group you should not trust. This function is pretty straight forward, grab the pixels and make them inversely porportional to their current brightness. 255 is the max so I just subtract the current value.
# Function: makes a photo it's negative
# Params: source picture to invert
# Returns: negative photo
#invert image
def makeNegative(sourcePic):
retPic = duplicatePicture(sourcePic)
pixels = getPixels(retPic)
for p in pixels:
r = getRed(p)
b = getBlue(p)
g = getGreen(p)
setRed(p, 255 - r)
setBlue(p, 255 - b)
setGreen(p, 255 - g)
return retPic
Better black and white (lab #3)
Let's face it, when it comes to Mr Rogers...he's a classic man. You can be mean when you look that clean, because he's a classic man. This function was a big of a gimme because we got the multiplier values given to us. It's still cool though.
# Function: better black and white photo
# Params: source picture to convert
# Returns: black and white photo
def betterBnW(sourcePic):
retPic = duplicatePicture(sourcePic)
pixels = getPixels(retPic)
for p in pixels:
r = getRed(p)
b = getBlue(p)
g = getGreen(p)
average = (r * 0.299) + (b * 0.114) + (g * 0.587)
setRed(p, average)
setBlue(p, average)
setGreen(p, average)
return retPic
Bottom-to-top mirror (lab #4)
There were a variety of mirroring functions in this project. This one, mirror vertical, lets you select if you want to mirror top to bottom or bottom to top(with a pyramid top to bottom looks better!). Then it traces from left to right copying the top row to the bottom row until it hits the middle of the picture. There were no real problems with this but it doesn't seem super fast.
# Function: Vertical image mirroring
# Params: 1) an image, 2) bool value for True mirrors top to bottom, False mirrors bottom to top
# Returns: mirrored image
def mirrorVertical(sourcePic, topBottom):
width = getWidth(sourcePic)
height = getHeight(sourcePic)
retPic = duplicatePicture(sourcePic)
yEnd = height / 2
# mirror top to bottom side of image
if topBottom == True:
for x in range(0, width):
for y in range(0, yEnd):
sourcePixel = getPixel(sourcePic, x, y)
destPixel = getPixel(retPic, x, height - y - 1)
sourceColor = getColor(sourcePixel)
setColor(destPixel, sourceColor)
#mirror bottom to top side of image
else:
for x in range(0, width):
for y in range(0, yEnd):
sourcePixel = getPixel(sourcePic, x, height - y - 1)
destPixel = getPixel(retPic, x, y)
sourceColor = getColor(sourcePixel)
setColor(destPixel, sourceColor)
return retPic
Shrink (lab #4)
Shrink is critical if you want to make a few copies of an object to make it seem like there is more variety in your picture when in fact you just used the same picture over and over. Using it to resize a picture one time is an absolute waste though because you should do that in pre-processing with a paint program. But if you mix and match shrink and color filters you could give some good variety to a scene by having a few different kinds of dragons for example or other things like trees. So maybe with 5 base trees and some resize and recolor you could give yourself some real variety in a forest!
# Function: Shrink an image by 50%
# Params: Picture to scale
# Returns: Resized picture
def shrink(sourcePic):
sourceHeight = sourcePic.getHeight()
sourceWidth = sourcePic.getWidth()
retPic = makeEmptyPicture(sourceWidth/2, sourceHeight/2)
destX = 0
destY = 0
destWidth = retPic.getWidth()
destHeight = retPic.getHeight()
for sourceY in range(0, sourceHeight, 2):
destX = 0
for sourceX in range(0, sourceWidth, 2):
if(destX < destWidth) and (destY < destHeight):
sourcePixel = getPixel(sourcePic, sourceX, sourceY)
destPixel = getPixel(retPic, destX , destY)
setColor(destPixel, getColor(sourcePixel))
destX += 1
destY += 1
return retPic
Collage (lab #5)
For my collage lab I was kind of tripping out without an alpha channel to make things look nice. So I upgraded the copy function to accept parameters for red, green, and blue values along with a precision so that you could pick what color should be transparent. It's a green screen for any color with adjustable match precision that lets you put pictures out of bounds to make a great collage! The main thing that I learned from this is that working with images this way really starts to slow things down.
Here is the code below for the collage, along with critical support functions (rotate, shrink, pyCopyA [copy with alpha])
# Function: Shrink an image by 50%
# Params: Picture to scale
# Returns: Resized picture
def shrink(sourcePic):
sourceHeight = sourcePic.getHeight()
sourceWidth = sourcePic.getWidth()
retPic = makeEmptyPicture(sourceWidth/2, sourceHeight/2)
destX = 0
destY = 0
destWidth = retPic.getWidth()
destHeight = retPic.getHeight()
for sourceY in range(0, sourceHeight, 2):
destX = 0
for sourceX in range(0, sourceWidth, 2):
if(destX < destWidth) and (destY < destHeight):
sourcePixel = getPixel(sourcePic, sourceX, sourceY)
destPixel = getPixel(retPic, destX , destY)
setColor(destPixel, getColor(sourcePixel))
destX += 1
destY += 1
return retPic
# Function: Rotate image 90 degrees CCW or CW
# Params: picture to rotate, [CCW == True] rotates CCW, [CCW == Talse] rorates CW
# Returns: rotated picture
def rotatePic(sourcePic, CCW):
sourceHeight = sourcePic.getHeight()
sourceWidth = sourcePic.getWidth()
retPic = makeEmptyPicture (sourceHeight, sourceWidth)
#Work from top to bottom of source picture moving one row at a time left to right
#Copy to source picture working from bottom left corner up one column at a time left to right
if CCW == True:
for sourceY in range(0, sourceHeight):
for sourceX in range(0, sourceWidth):
sourcePixel = getPixel(sourcePic, sourceX, sourceY)
destPixel = getPixel(retPic, sourceY, sourceWidth - sourceX - 1)
setColor(destPixel, getColor(sourcePixel))
#Work from top to bottom of source picture moving one row at a time left to right
#Copy to source picture working from bottom right corner up one column at a time right to left
else:
for sourceY in range(0, sourceHeight):
for sourceX in range(0, sourceWidth):
sourcePixel = getPixel(sourcePic, sourceX, sourceY)
destPixel = getPixel(retPic, sourceHeight - sourceY - 1, sourceX)
setColor(destPixel, getColor(sourcePixel))
return retPic
# Function: python copy with alpha, copy source image to target image and remove transparent pixels
# Params: source image, target image, target x for 0, target y for 0
# Returns: Resized picture
def pyCopyA(source, target, targetX, targetY, alphaR, alphaG, alphaB, precision):
targetWidth = target.getWidth()
targetHeight = target.getHeight()
for y in range( 0, source.getHeight() ): # work from top to bottom
if (y + targetY < targetHeight) and (y + targetY > 0): #Y range check so we can go crazy and not worry
for x in range( 0, source.getWidth() ):
if (x + targetX < targetWidth) and (x + targetX > 0): #X range check so we can go crazy and not worry
sourcePixel = getPixel(source, x, y)
sourceColor = getColor(sourcePixel)
if ( abs(sourceColor.getRed() - alphaR) + abs(sourceColor.getBlue() - alphaB) + abs(sourceColor.getGreen() - alphaG) ) > precision:
destPixel = getPixel(target, x + targetX, y + targetY)
destPixel.setColor(sourceColor)
# Function: Make a collage with dragons, fire balls, and a drone
# Params: none, you can't negotiate with dragons
# Returns: final image
def makeCollage():
finalImage = makeEmptyPicture(1256, 712)
greenScreen = [16, 223, 13] # R G B values for green screen
colorPrecision = 150 # how close the colors has to be to remove the alpha
# Load up all images before we start the party
background = makePicture(getMediaPath("background.jpg"))
title = makePicture(getMediaPath("title.jpg"))
moon = makePicture(getMediaPath("moon.jpg"))
dinosaur = makePicture(getMediaPath("dinosaur.jpg"))
fireballA = makePicture(getMediaPath("fireball.jpg"))
treeA = makePicture(getMediaPath("tree1.jpg"))
treeB = makePicture(getMediaPath("tree2.jpg"))
treeC = makePicture(getMediaPath("tree3.jpg"))
# Do secondary processing to images to generate additional assets
smallDinoA = shrink(dinosaur)
smallDinoB = rotatePic(smallDinoA, True)
smallDinoC = rotatePic(smallDinoB, True)
fireballB = rotatePic(fireballA, True)
fireballB = rotatePic(fireballB, True)
treeC = shrink(treeC)
# Paint the scene
pyCopy(background, finalImage, 0, 0)
pyCopyA(title, finalImage, 350, 50, greenScreen[0], greenScreen[1], greenScreen[2], 200)
pyCopyA(moon, finalImage, -20, -20, greenScreen[0], greenScreen[1], greenScreen[2], 200)
pyCopyA(treeB, finalImage, 0, 0, greenScreen[0], greenScreen[1], greenScreen[2], 200)
pyCopyA(treeC, finalImage, 0, 450, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
pyCopyA(treeC, finalImage, 900, 450, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
pyCopyA(treeA, finalImage, 900, 400, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
# Warning, impending dinosaur attack
pyCopyA(fireballA, finalImage, 800, 50, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
pyCopyA(fireballB, finalImage, 300, 200, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
pyCopyA(smallDinoA, finalImage, -30, 200, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
pyCopyA(smallDinoB, finalImage, 600, 400, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
pyCopyA(smallDinoC, finalImage, 900, -20, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
return finalImage
Red-eye Reduction (lab #6)
Color Art-i-fy (lab #6)
Artify is a filter that basically bins an image. It has cutoff points which apply equally to each color. If you are inbetween certain thresholds then you get a fixed value. My real problem with this one was trying to index across an array of the rgb values and running the filter on them that way. Calling an extra function that does the binning of the colors worked fine though.
Here is the code I had a problem with before switching to a chunkier version.
for p in pixels:
r = getRed(p)
b = getBlue(p)
g = getGreen(p)
for color in [r, b, g]:
if color < 64:
color = 31
elif color < 128:
color = 95
elif color < 192:
color = 159
else:
color = 223
setRed(p, r)
setBlue(p, b)
setGreen(p, g)
# Function: Artify colorize
# Params: Source image
# Returns: Artify picture
def artify(sourcePic):
retPic = duplicatePicture(sourcePic)
pixels = getPixels(retPic)
for p in pixels:
setRed(p, artifyChk(getRed(p)))
setBlue(p, artifyChk(getBlue(p)))
setGreen(p, artifyChk(getGreen(p)))
return retPic
def artifyChk(color):
if color < 64:
color = 31
elif color < 128:
color = 95
elif color < 192:
color = 159
else:
color = 223
return color
Green screen (lab #6) - I used green screen just about everywhere because it's the only way to make a cool collage without transparency. But here is one I liked inspired by the green fields of the show Teletubbies. This used the pyCopyA function above so there is not much new to show here. I did make a new simplified chromakey function for this though based on the course requirements.
# Function: Green screen foreground onto background
# Params: background picture, foreground picture
# Returns: combined photo
def chromaKey(foreground, background):
greenScreen = [16, 223, 13] # R G B values for green screen
colorPrecision = 150 # how close the colors has to be to remove the alpha
retPic = duplicatePicture(background)
pyCopyA(foreground, retPic, 0, 0, greenScreen[0], greenScreen[1], greenScreen[2], colorPrecision)
return retPic
Home made Thanksgiving (lab #7)
Objective: Make a cool thanksgiving card
Everybody seems to want to skip passed thanksgiving and move right on to Christmas. This card should straighten things out. This lab was a bit of a rehash of old functions so the main thing to learn was about text with styles and then because we were going to share this software I had to find setMediaPath() and getMediaPath(). Those seem nice but a teammate was saying it didn't pop up the dialog on her computer. I looked at the traditional ways of getting your working directory in Python but those didn't seem to work well with JES.
The only non-standard function used for my thanksgiving card was pyCopyA shown above from my collage. But here is the christmas card code:
# Function: Make thanksgiving card
# Params: none, you can't negotiate with dragons
# Returns: final image
def makeCardThanksgiving():
greenScreen = [50, 255, 50] # R G B values for green screen
colorPrecision = 100 # how close the colors has to be to remove the alpha
background = makePicture(getMediaPath("fatTurkey.jpg"))
santas = makePicture(getMediaPath("santa.jpg"))
dragon = makePicture(getMediaPath("dinosaur.jpg"))
flamethrower = makePicture(getMediaPath("flamethrower.jpg"))
textA = "Happy Thanksgiving! No, it's not Christmas yet."
textB = "-Matt"
pyCopyA(santas, background, 0, 290, greenScreen[0], greenScreen[1], greenScreen[2], 200)
pyCopyA(flamethrower, background, 140, 510, greenScreen[0], greenScreen[1], greenScreen[2], 200)
pyCopyA(dragon, background, -500, 400, greenScreen[0], greenScreen[1], greenScreen[2], 200)
addTextWithStyle(background, 60, 381, textA, makeStyle(serif, bold, 24))
addTextWithStyle(background, 371, 420, textB, makeStyle(serif, bold, 24))
return background
Line Tracing
It's line tracing time! This one was another gimme where the algorithm is handed to you but you tweak the main control variable("dif" in this case). I like a luminance difference(dif) of 50 for my glasses. Lowering the value seems to give you a fuzzier border where there are more black dots. By comparing the pixel below and to the right of the current pixel as you move across the whole image you can find transition zones. As you move from the outside white border into the blue interior of the glasses there will be a large change in color that will be indicated by the black pixels. Once inside the glasses however there is only a small change through the lenses as they are mostly blue. On the nose piece for example the polycarbonate lense gets thicker around the nose piece (or maybe there is a squishy pad for the nose?) but in either case the large change in material thickness allows less light through so you have a darker section. That leads to a nice outline around the nose section. I really like this effect and finding lines like this simplifies an object a lot so you could do easier tricks like tracking an object I bet.
# Function: Line trace an image based on luminescence of bottom and right pixel
# Params: source pic to trace and minimum difference between abs(core - bot) and abs(core-right)
# Returns: black and white line traced pic
def lineTrace(sourcePic, dif):
width = sourcePic.getWidth()
height = sourcePic.getHeight()
retPic = makeEmptyPicture(width, height)
#white = makeColor(255,255,255)
#black = makeColor(0,0,0)
xMax = width - 1
yMax = height - 1
for x in range(0, xMax):
for y in range(0, yMax):
if (y + 1 < yMax) and (x + 1 < xMax):
corePixel = sourcePic.getPixel(x, y).getColor()
botPixel = sourcePic.getPixel(x, y + 1 ).getColor()
rightPixel = sourcePic.getPixel(x + 1, y).getColor()
coreLum = corePixel.red + corePixel.blue + corePixel.green
botLum = botPixel.red + botPixel.blue + botPixel.green
rightLum = rightPixel.red + rightPixel.blue + rightPixel.green
if (abs(coreLum - botLum) < dif) and (abs(coreLum - rightLum) < dif) :
setColor(retPic.getPixel(x,y), white)
else:
setColor(retPic.getPixel(x,y), black)
else:
setColor(retPic.getPixel(x, y), white) # just make it white if we hit the end, no big deal
return retPic








No comments:
Post a Comment