comparison tools/image_transforms.py @ 0:64374d852e36

Uploaded
author tomasz-bednarz
date Mon, 25 Nov 2013 21:32:12 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:64374d852e36
1 """Transformations on images"""
2 from numpy import random
3 from numpy import array
4 from PIL import Image
5 from PIL import ImageDraw
6 from PIL import ImageOps
7
8 def tileify(image_data, num_blocks, max_shift):
9 """
10 Breaks image up into rectangles and shifts them a random distance
11 Areas not covered by the moved rectangles are the negative of
12 the original image
13 """
14 width = image_data.size[0]
15 height = image_data.size[1]
16 row_block_size = round(height / num_blocks)
17 col_block_size = round(width / num_blocks)
18 negative_image = ImageOps.invert(image_data)
19 pixels = array(image_data)
20 for row in xrange(num_blocks):
21 inner_row_val = int(row_block_size * row)
22 outer_row_val = int(row_block_size * row + row_block_size)
23 for col in xrange(num_blocks):
24 inner_col_val = int(col_block_size * col)
25 outer_col_val = int(col_block_size * col + col_block_size)
26 block = pixels[
27 inner_row_val:outer_row_val,
28 inner_col_val:outer_col_val
29 ]
30 location = calculate_random_location(
31 inner_row_val,
32 inner_col_val,
33 max_shift
34 )
35 negative_image.paste(Image.fromarray(block), location)
36 return negative_image
37
38 def calculate_random_location(x, y, max_shift):
39 """
40 Calculates random location near some starting point
41 Inputs
42 x - coordinate point where 0,0 is upper left corner
43 y - coordinate point where 0,0 is upper left corner
44 max_shift - the furthest distance from the point to shift
45 """
46 x_offset = random.random_integers(-max_shift, max_shift)
47 y_offset = random.random_integers(-max_shift, max_shift)
48 location = (
49 y + y_offset,
50 x + x_offset
51 )
52 return location
53
54 def filmify_image(image_data):
55 """
56 Makes the image look like 35mm film
57 Inputs:
58 PIL Image
59 Returns:
60 Modified image data
61 """
62 # print 'Filming'
63 # Size of photo in side the film
64 film_size = (400, 300)
65 border_size = 30
66 film_hole_size = (8, 10)
67
68 filmed_image = modify_photo(image_data, film_size)
69 filmed_image = add_film_border(filmed_image, film_size, border_size)
70
71 # Center strip in the border space
72 strip_upper_offset = int(round((border_size - film_hole_size[1])/2))
73 strip_lower_offset = film_size[1] + border_size + strip_upper_offset
74 # Bring strip in towards the photo
75 offset = int(round(film_hole_size[1]/2))
76 strip_upper_offset = strip_upper_offset + offset
77 strip_lower_offset = strip_lower_offset - offset
78
79 place_film_strip(
80 filmed_image,
81 strip_upper_offset,
82 strip_lower_offset,
83 film_hole_size
84 )
85
86 return filmed_image
87
88 def add_film_border(image_data, film_size, border_size):
89 """
90 Creates a black border around the image
91 Inputs
92 image_data - image to be manipulated
93 film_size - size of the internal picture
94 border_size - how wide you want the border on the top and bottom to be
95 Output
96 image with border
97 """
98 image_data = ImageOps.expand(
99 image_data,
100 border=border_size,
101 fill='black'
102 )
103 # Crop to cut half of border from right and left of image
104 crop_box = (
105 int(round(border_size/2)),
106 0,
107 film_size[0] + int(round(border_size * 1.5)),
108 film_size[1] + border_size * 2
109 )
110 image_data = image_data.crop(crop_box)
111 return image_data
112
113 def place_film_strip(image_data, y_offset_upper, y_offset_lower, film_hole_size):
114 """
115 Create strip of film_holes at y_offset
116 """
117 hole_distance = 15
118 left_film_buffer = 2
119 for x_offset in range(left_film_buffer, image_data.size[0], hole_distance):
120 place_film_hole(image_data, (x_offset, y_offset_upper), film_hole_size)
121 place_film_hole(image_data, (x_offset, y_offset_lower), film_hole_size)
122
123 def place_film_hole(image_data, offset, film_hole_size):
124 """
125 Puts film hole at offset into the image provided
126 Inputs:
127 image_data - image file to have film hole pasted
128 offset - 2 tuple with x and y of the top left corner of film hole
129 film_hole_size - size of the rectangle to be made
130 Outputs
131 Original image with rectangle in location based on the offset
132 """
133 corner_radius = 2
134 film_hole_color = 'white'
135 film_hole = round_rectangle(film_hole_size, corner_radius, film_hole_color)
136 image_data.paste(film_hole, offset)
137
138 def round_corner(radius, fill):
139 """
140 Draw a round corner
141 This code came from http://nadiana.com/pil-tutorial-basic-advanced-drawing
142 """
143 corner = Image.new('RGBA', (radius, radius), (0, 0, 0, 0))
144 draw = ImageDraw.Draw(corner)
145 draw.pieslice((0, 0, radius * 2, radius * 2), 180, 270, fill=fill)
146 return corner
147
148 def round_rectangle(size, radius, fill):
149 """
150 Draw a rounded rectangle
151 This code came from http://nadiana.com/pil-tutorial-basic-advanced-drawing
152 """
153 width, height = size
154 rectangle = Image.new('RGBA', size, fill)
155 corner = round_corner(radius, fill)
156 rectangle.paste(corner, (0, 0))
157 # Rotate the corner and paste it
158 rectangle.paste(corner.rotate(90), (0, height - radius))
159 rectangle.paste(corner.rotate(180), (width - radius, height - radius))
160 rectangle.paste(corner.rotate(270), (width - radius, 0))
161 return rectangle
162
163 def modify_photo(image_data, film_size):
164 """
165 Make the image grayscale and invert the colors
166 All manipulations for the original photo go here
167 """
168 modified_image = ImageOps.grayscale(image_data)
169 # Image.ANTIALIAS is best for down sizing
170 modified_image = modified_image.resize(film_size, Image.ANTIALIAS)
171 modified_image = ImageOps.invert(modified_image)
172 modified_image = ImageOps.flip(modified_image)
173 return modified_image