Advertisement
Guest User

Untitled

a guest
Sep 30th, 2016
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.82 KB | None | 0 0
  1. import math
  2. import string
  3. import random
  4. import time
  5. from PIL import Image
  6. from PIL import ImageDraw
  7. from operator import attrgetter
  8.  
  9. POSITION_MULTIPLIER = 1
  10. RADIUS_MULTIPLIER = 1
  11. two_pass = False
  12.  
  13. class Graph:
  14.     def __init__(self, width, height):
  15.         self.width = width
  16.         self.height = height
  17.         self.mse = []
  18.         self.max = 755**2
  19.         self.image = Image.new("RGB", (self.width,self.height), (255,255,255))
  20.  
  21.     def draw(self):
  22.         self.image = Image.new("RGB", (self.width,self.height),(255,255,255))
  23.         self.max = max(self.mse) + 20
  24.         draw = ImageDraw.Draw(self.image)
  25.         for i in range(len(self.mse)):
  26.             if i > 1:
  27.                 x1 = int(float(self.width)/(len(self.mse)-1)*(i))
  28.                 x2 = int(float(self.width)/(len(self.mse)-1)*(i-1))
  29.                 y1 = self.height - (int(float(self.height) / self.max * self.mse[i]))
  30.                 y2 = self.height - (int(float(self.height) / self.max * self.mse[i-1]))
  31.                 draw.line([(x1,y1),(x2,y2)],(0,0,0))
  32.  
  33.         self.image.save("/tmp/graph.png")
  34.         return
  35.  
  36.  
  37. class Stroke:
  38.     def __init__(self, x, y, r, c):
  39.         self.x = x
  40.         self.y = y
  41.         self.r = r
  42.         self.c = c
  43.  
  44.     def soft_mutate(self, magnitude):
  45.         if random.randint(0,1) == 1:
  46.             self.x += int(random.uniform( -magnitude, magnitude) * POSITION_MULTIPLIER)
  47.             self.y += int(random.uniform( -magnitude, magnitude) * POSITION_MULTIPLIER)
  48.             if self.x < 0:
  49.                 self.x = 0
  50.             if self.x > art.width - 1:
  51.                 self.x = art.width -1
  52.             if self.y < 0:
  53.                 self.y = 0
  54.             if self.y > art.height - 1:
  55.                 self.y = art.height - 1
  56.             self.c = art.getpixel((self.x, self.y))
  57.         if random.randint(0,1) == 1:
  58.             self.r += int(random.uniform( -magnitude, magnitude) * RADIUS_MULTIPLIER)
  59.             if self.r < MIN_RADIUS:
  60.                 self.r = MIN_RADIUS
  61.             if self.r > MAX_RADIUS:
  62.                 self.r = MAX_RADIUS
  63.         return
  64.  
  65.  
  66. class Painting:
  67.     def __init__(self, strokes, image):
  68.         self.strokes = strokes
  69.         self.image = image
  70.         self.error = 90000
  71.  
  72.     def mean_square_error( self ):
  73.         im1_pix = self.image.load() # get a pixelAccess object to read pixels faster
  74.         im2_pix = art.load()
  75.  
  76.         errorTotal = 0 # total error of the image - adding an int is faster than making a list
  77.         for y in range(1,art.height-1,1):
  78.             for x in range(1,art.width-1,1):
  79.                 ar,ag,ab = im1_pix[x,y] # unpack the pixel RGB
  80.                 br,bg,bb = im2_pix[x,y]
  81.                 errorTotal += (( ar - br ) ** 2)
  82.                 errorTotal += (( ag - bg ) ** 2)
  83.                 errorTotal += (( ab - bb ) ** 2)
  84.         mean_error = errorTotal/ ( art.width * art.height )
  85.         return mean_error
  86.  
  87.     def duplicate( self ):
  88.  
  89.         strokes = []
  90.         for stroke in self.strokes:
  91.             strokes.append(Stroke(stroke.x, stroke.y, stroke.r, stroke.c))
  92.         return Painting(strokes, Image.new("RGB", self.image.size, (255,255,255)))
  93.  
  94.     def create_image(self):
  95.         image = Image.new("RGB", self.image.size, (255,255,255))
  96.         draw = ImageDraw.Draw(image)
  97.         for stroke in self.strokes:
  98.             draw_circle( draw, stroke.x, stroke.y, stroke.r, stroke.c)
  99.         self.image = image
  100.         return image
  101.  
  102.  
  103. def draw_circle(draw, x, y, r, c):
  104.  
  105.     draw.ellipse([x-r,y-r,x+r,y+r],c,c)
  106.     return
  107.  
  108. def scale_painting( painting, factor ):
  109.     image = Image.new("RGB", (painting.image.width*factor,painting.image.height*factor),(255,255,255))
  110.     strokes = []
  111.     for stroke in painting.strokes:
  112.         strokes.append(Stroke(stroke.x*factor,stroke.y*factor,stroke.r*factor,stroke.c))
  113.     painting = Painting(strokes,image)
  114.     painting.create_image()
  115.     painting.image.save("./scaled_painting.png")
  116.     return painting
  117.  
  118. def paint( source, num_of_strokes, num_of_tries ):
  119.     global art, MIN_RADIUS, MAX_RADIUS
  120.     graph = Graph(600,400)
  121.     art = Image.open(source)
  122.     art.convert("RGB")
  123.     MIN_RADIUS = int(float(2 )/695*art.width)
  124.     if MIN_RADIUS < 1:
  125.         MIN_RADIUS = 1
  126.     MAX_RADIUS = int(float(66)/695*art.width)
  127.     layers = []
  128.     strokes = []
  129.     prev_error = 999999
  130.     painting = Painting(strokes, Image.new( "RGB", art.size, (255, 255,255)))
  131.     old_image = painting.image
  132.     for stroke in range(num_of_strokes):
  133.         print("STROKE #" + str(stroke))
  134.         error = painting.mean_square_error()
  135.         tmp_error = error + 1
  136.         while tmp_error >= error:
  137.             tmp_painting = painting.duplicate()
  138.             x = random.randint(0,art.width - 1)
  139.             y = random.randint(0,art.height- 1)
  140.             r = random.randint(MIN_RADIUS,MAX_RADIUS)
  141.             c = art.getpixel((x,y))
  142.             tmp_painting.strokes.append(Stroke(x,y,r,c))
  143.             tmp_painting.create_image()
  144.             tmp_error = tmp_painting.mean_square_error()
  145.         painting.strokes.append(Stroke(x,y,r,c))
  146.         prev_error = painting.mean_square_error()
  147.         loop_num = 0
  148.         while loop_num < num_of_tries:
  149.             old_painting = painting.duplicate()
  150.             painting.strokes[stroke].soft_mutate(5)
  151.             painting.create_image()
  152.             error = painting.mean_square_error()
  153.             graph.mse.append(error)
  154.             graph.draw()
  155.             print("MSE: " + str(error))
  156.             if error < prev_error:
  157.                 loop_num = 0
  158.                 painting.create_image()
  159.                 prev_error = error
  160.                 painting.image.save("./painting.png")
  161.             else:
  162.                 painting = old_painting
  163.                 loop_num += 1
  164.  
  165.  
  166. painting = paint('./src.jpg', 500, 50)
  167.  
  168. scale_painting(painting, 10)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement