image operations copyright © software carpentry 2010 this work is licensed under the creative...
DESCRIPTION
Multimedia ProgrammingImage Operations Most operations built into the library import sys from PIL import Image, ImageFilter filename = sys.argv[1] p = Image.open(filename) p.filter(ImageFilter.BLUR).save('blur-' + filename) p.filter(ImageFilter.CONTOUR).save('contour-' + filename) p.filter(ImageFilter.EMBOSS).save('emboss-' + filename) p.transpose(Image.FLIP_LEFT_RIGHT).save('flip-' + filename)TRANSCRIPT
![Page 1: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/1.jpg)
Image Operations
Copyright © Software Carpentry 2010This work is licensed under the Creative Commons Attribution LicenseSee http://software-carpentry.org/license.html for more information.
Multimedia Programming
![Page 2: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/2.jpg)
Multimedia Programming Image Operations
Most operations built into the library
![Page 3: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/3.jpg)
Multimedia Programming Image Operations
Most operations built into the libraryimport sysfrom PIL import Image, ImageFilter
filename = sys.argv[1]p = Image.open(filename)
p.filter(ImageFilter.BLUR).save('blur-' + filename)p.filter(ImageFilter.CONTOUR).save('contour-' + filename)p.filter(ImageFilter.EMBOSS).save('emboss-' + filename)
p.transpose(Image.FLIP_LEFT_RIGHT).save('flip-' + filename)
![Page 4: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/4.jpg)
Multimedia Programming Image Operations
blur
emboss
contour
flip
![Page 5: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/5.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinates
![Page 6: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/6.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinatesoriginal = Image.open(sys.argv[1])x_size, y_size = original.sizex_half, y_half = x_size / 2, y_size / 2half = original.resize((x_half, y_half))x_double, y_double = x_size * 2, y_size * 2double = Image.new('RGB', (x_double, y_double))for x in range(4): for y in range(4): box = (x * x_half, y * y_half, (x+1) * x_half, (y+1) * y_half) double.paste(half, box)double.save(sys.argv[2])
![Page 7: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/7.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinatesoriginal = Image.open(sys.argv[1])x_size, y_size = original.sizex_half, y_half = x_size / 2, y_size / 2half = original.resize((x_half, y_half))x_double, y_double = x_size * 2, y_size * 2double = Image.new('RGB', (x_double, y_double))for x in range(4): for y in range(4): box = (x * x_half, y * y_half, (x+1) * x_half, (y+1) * y_half) double.paste(half, box)double.save(sys.argv[2])
![Page 8: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/8.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinatesoriginal = Image.open(sys.argv[1])x_size, y_size = original.sizex_half, y_half = x_size / 2, y_size / 2half = original.resize((x_half, y_half))x_double, y_double = x_size * 2, y_size * 2double = Image.new('RGB', (x_double, y_double))for x in range(4): for y in range(4): box = (x * x_half, y * y_half, (x+1) * x_half, (y+1) * y_half) double.paste(half, box)double.save(sys.argv[2])
![Page 9: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/9.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinatesoriginal = Image.open(sys.argv[1])x_size, y_size = original.sizex_half, y_half = x_size / 2, y_size / 2half = original.resize((x_half, y_half))x_double, y_double = x_size * 2, y_size * 2double = Image.new('RGB', (x_double, y_double))for x in range(4): for y in range(4): box = (x * x_half, y * y_half, (x+1) * x_half, (y+1) * y_half) double.paste(half, box)double.save(sys.argv[2])
![Page 10: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/10.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinatesoriginal = Image.open(sys.argv[1])x_size, y_size = original.sizex_half, y_half = x_size / 2, y_size / 2half = original.resize((x_half, y_half))x_double, y_double = x_size * 2, y_size * 2double = Image.new('RGB', (x_double, y_double))for x in range(4): for y in range(4): box = (x * x_half, y * y_half, (x+1) * x_half, (y+1) * y_half) double.paste(half, box)double.save(sys.argv[2])
![Page 11: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/11.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinatesoriginal = Image.open(sys.argv[1])x_size, y_size = original.sizex_half, y_half = x_size / 2, y_size / 2half = original.resize((x_half, y_half))x_double, y_double = x_size * 2, y_size * 2double = Image.new('RGB', (x_double, y_double))for x in range(4): for y in range(4): box = (x * x_half, y * y_half, (x+1) * x_half, (y+1) * y_half) double.paste(half, box)double.save(sys.argv[2])
![Page 12: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/12.jpg)
Multimedia Programming Image Operations
Basic image editing is mostly about coordinatesoriginal = Image.open(sys.argv[1])x_size, y_size = original.sizex_half, y_half = x_size / 2, y_size / 2half = original.resize((x_half, y_half))x_double, y_double = x_size * 2, y_size * 2double = Image.new('RGB', (x_double, y_double))for x in range(4): for y in range(4): box = (x * x_half, y * y_half, (x+1) * x_half, (y+1) * y_half) double.paste(half, box)double.save(sys.argv[2])
![Page 13: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/13.jpg)
Multimedia Programming Image Operations
![Page 14: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/14.jpg)
Multimedia Programming Image Operations
Draw on imagesimport sysfrom PIL import Image, ImageDrawBORDER = 10GRAY = (128, 128, 128)pic = Image.open(sys.argv[1])xsize, ysize = pic.sizedraw = ImageDraw.Draw(pic)draw.rectangle((0, 0, xsize, BORDER), fill=GRAY)draw.rectangle((0, 0, BORDER, ysize), fill=GRAY)draw.rectangle((0, ysize-BORDER, xsize, ysize), fill=GRAY)draw.rectangle((xsize-BORDER, 0, xsize, ysize), fill=GRAY)pic.save('border-' + sys.argv[1])
![Page 15: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/15.jpg)
Multimedia Programming Image Operations
Draw on imagesimport sysfrom PIL import Image, ImageDrawBORDER = 10GRAY = (128, 128, 128)pic = Image.open(sys.argv[1])xsize, ysize = pic.sizedraw = ImageDraw.Draw(pic)draw.rectangle((0, 0, xsize, BORDER), fill=GRAY)draw.rectangle((0, 0, BORDER, ysize), fill=GRAY)draw.rectangle((0, ysize-BORDER, xsize, ysize), fill=GRAY)draw.rectangle((xsize-BORDER, 0, xsize, ysize), fill=GRAY)pic.save('border-' + sys.argv[1])
![Page 16: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/16.jpg)
Multimedia Programming Image Operations
Draw on imagesimport sysfrom PIL import Image, ImageDrawBORDER = 10GRAY = (128, 128, 128)pic = Image.open(sys.argv[1])xsize, ysize = pic.sizedraw = ImageDraw.Draw(pic)draw.rectangle((0, 0, xsize, BORDER), fill=GRAY)draw.rectangle((0, 0, BORDER, ysize), fill=GRAY)draw.rectangle((0, ysize-BORDER, xsize, ysize), fill=GRAY)draw.rectangle((xsize-BORDER, 0, xsize, ysize), fill=GRAY)pic.save('border-' + sys.argv[1])
![Page 17: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/17.jpg)
Multimedia Programming Image Operations
Draw on images
Exercise: put frame around entire image
![Page 18: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/18.jpg)
Multimedia Programming Image Operations
Work with color bandsimport sysfrom PIL import Image
filename = sys.argv[1]pic = Image.open(filename)pic.load()bands = pic.split()for (i, name) in enumerate('rgb'): bands[i].save(filename.replace('.', '-%s.' % name))
![Page 19: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/19.jpg)
Multimedia Programming Image Operations
Work with color bandsimport sysfrom PIL import Image
filename = sys.argv[1]pic = Image.open(filename)pic.load()bands = pic.split()for (i, name) in enumerate('rgb'): bands[i].save(filename.replace('.', '-%s.' % name))
(red[], green[], blue[])
![Page 20: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/20.jpg)
Multimedia Programming Image Operations
Work with color bandsimport sysfrom PIL import Image
filename = sys.argv[1]pic = Image.open(filename)pic.load()bands = pic.split()for (i, name) in enumerate('rgb'): bands[i].save(filename.replace('.', '-%s.' % name))
workaround
![Page 21: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/21.jpg)
Multimedia Programming Image Operations
Work with color bands
red green blue
![Page 22: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/22.jpg)
Multimedia Programming Image Operations
Use point functions to manipulate pixel valuesR, G, B = 0, 1, 2SCALE = 0.5
def decrease(x): return x * SCALE
pic = Image.open(sys.argv[1])pic.load() bands = pic.split()bands = (bands[R].point(decrease), bands[G], bands[B])more_red = Image.merge('RGB', bands)more_red.save('bluegreen-' + sys.argv[1])
![Page 23: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/23.jpg)
Multimedia Programming Image Operations
Work with color bands and point functionsR, G, B = 0, 1, 2SCALE = 0.5
def decrease(x): return x * SCALE
pic = Image.open(sys.argv[1])pic.load()bands = pic.split()bands = (bands[R].point(decrease), bands[G], bands[B])more_red = Image.merge('RGB', bands)more_red.save('bluegreen-' + sys.argv[1])
![Page 24: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/24.jpg)
Multimedia Programming Image Operations
Work with color bands and point functionsR, G, B = 0, 1, 2SCALE = 0.5
def decrease(x): return x * SCALE
pic = Image.open(sys.argv[1])pic.load()bands = pic.split()bands = (bands[R].point(decrease), bands[G], bands[B])more_red = Image.merge('RGB', bands)more_red.save('bluegreen-' + sys.argv[1])
![Page 25: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/25.jpg)
Multimedia Programming Image Operations
Work with color bands and point functionsR, G, B = 0, 1, 2SCALE = 0.5
def decrease(x): return x * SCALE
pic = Image.open(sys.argv[1])pic.load()bands = pic.split()bands = (bands[R].point(decrease), bands[G], bands[B])less_red = Image.merge('RGB', bands)less_red.save('bluegreen-' + sys.argv[1])
![Page 26: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/26.jpg)
Multimedia Programming Image Operations
Less red makes the image look more blue/green
![Page 27: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/27.jpg)
Multimedia Programming Image Operations
Less red makes the image look more blue/green
What happens if you increase blue and green instead?
![Page 28: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/28.jpg)
Multimedia Programming Image Operations
Highlight a region in an image
![Page 29: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/29.jpg)
Multimedia Programming Image Operations
Highlight a region in an image
Option 1: recolor the pixels
![Page 30: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/30.jpg)
Multimedia Programming Image Operations
Highlight a region in an image
Option 1: recolor the pixelsOption 2: blend with a square of desired size– New pixel = (left pixel + right pixel) / 2
![Page 31: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/31.jpg)
Multimedia Programming Image Operations
Figure out the coordinates
major_x
majo
r_y
highlight_xhigh
ligh
t_y
Low x = (major_x / 2) – (highlight_x / 2)= (major_x – highlight_x) / 2
High x = (major_x / 2) + (highlight_x / 2)= (major_x + highlight_x) / 2
![Page 32: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/32.jpg)
Multimedia Programming Image Operations
BLEND = 0.5
major_name, highlight_name = sys.argv[1:3]major, major_x, major_y = get(major_name)highlight, highlight_x, highlight_y = get(highlight_name)
box = ((major_x - hl_x) / 2, (major_y - hl_y) / 2, (major_x + hl_x) / 2, (major_y + hl_y) / 2)
middle = major.crop(box)middle = Image.blend(middle, highlight, BLEND)major.paste(middle, box)major.save('higlight-' + major_name)
![Page 33: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/33.jpg)
Multimedia Programming Image Operations
BLEND = 0.5
major_name, highlight_name = sys.argv[1:3]major, major_x, major_y = get(major_name)highlight, highlight_x, highlight_y = get(highlight_name)
box = ((major_x - hl_x) / 2, (major_y - hl_y) / 2, (major_x + hl_x) / 2, (major_y + hl_y) / 2)
middle = major.crop(box)middle = Image.blend(middle, highlight, BLEND)major.paste(middle, box)major.save('higlight-' + major_name)
![Page 34: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/34.jpg)
Multimedia Programming Image Operations
BLEND = 0.5
major_name, highlight_name = sys.argv[1:3]major, major_x, major_y = get(major_name)highlight, highlight_x, highlight_y = get(highlight_name)
box = ((major_x - hl_x) / 2, (major_y - hl_y) / 2, (major_x + hl_x) / 2, (major_y + hl_y) / 2)
middle = major.crop(box)middle = Image.blend(middle, highlight, BLEND)major.paste(middle, box)major.save('higlight-' + major_name)
![Page 35: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/35.jpg)
Multimedia Programming Image Operations
BLEND = 0.5
major_name, highlight_name = sys.argv[1:3]major, major_x, major_y = get(major_name)highlight, highlight_x, highlight_y = get(highlight_name)
box = ((major_x - hl_x) / 2, (major_y - hl_y) / 2, (major_x + hl_x) / 2, (major_y + hl_y) / 2)
middle = major.crop(box)middle = Image.blend(middle, highlight, BLEND)major.paste(middle, box)major.save('higlight-' + major_name)
![Page 36: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/36.jpg)
Multimedia Programming Image Operations
BLEND = 0.5
major_name, highlight_name = sys.argv[1:3]major, major_x, major_y = get(major_name)highlight, highlight_x, highlight_y = get(highlight_name)
box = ((major_x - hl_x) / 2, (major_y - hl_y) / 2, (major_x + hl_x) / 2, (major_y + hl_y) / 2)
middle = major.crop(box)middle = Image.blend(middle, highlight, BLEND)major.paste(middle, box)major.save('higlight-' + major_name)
![Page 37: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/37.jpg)
Multimedia Programming Image Operations
BLEND = 0.5
major_name, highlight_name = sys.argv[1:3]major, major_x, major_y = get(major_name)highlight, highlight_x, highlight_y = get(highlight_name)
box = ((major_x - hl_x) / 2, (major_y - hl_y) / 2, (major_x + hl_x) / 2, (major_y + hl_y) / 2)
middle = major.crop(box)middle = Image.blend(middle, highlight, BLEND)major.paste(middle, box)major.save('higlight-' + major_name)
![Page 38: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/38.jpg)
Multimedia Programming Image Operations
PIL provides basic image processing
![Page 39: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/39.jpg)
Multimedia Programming Image Operations
PIL provides basic image processingOpenCV (http://opencv.willowgarage.com) is acomplete image processing library
![Page 40: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/40.jpg)
Multimedia Programming Image Operations
PIL provides basic image processingOpenCV (http://opencv.willowgarage.com) is acomplete image processing libraryHave to convert images…
![Page 41: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/41.jpg)
Multimedia Programming Image Operations
PIL provides basic image processingOpenCV (http://opencv.willowgarage.com) is acomplete image processing libraryHave to convert images……but it's worth it
![Page 42: Image Operations Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See](https://reader033.vdocuments.net/reader033/viewer/2022051123/5a4d1b427f8b9ab0599a17ed/html5/thumbnails/42.jpg)
November 2010
created by
Greg Wilson
Copyright © Software Carpentry 2010This work is licensed under the Creative Commons Attribution LicenseSee http://software-carpentry.org/license.html for more information.