A friend of mine built this Python script, I'm sure he doesn't mind ;)


#!/usr/bin/env python
# by Andre Bocchini

import sys
import os
import string
import getopt
import Image
import ImageFilter
import ImageStat

def usage():
   """ Displays information on how to use the program. """

   print
   print "Usage : mosaic.py [options]"
   print "Required:"
   print "  -i <input-img>   Source image for the mosaic"
   print "  -s <img-dir>     Directory where other images are located"
   print "  -o <output-img>  Final mosaic image"
   print "  -b <blocks>      Number of blocks per row in the mosaic"
   print "  -w <width>       Final mosaic width"
   print "  -h <height>      Final mosaic height"
   print "  -t <threshold>   Sensitivity of the image analyzer"
   print "Optional:"
   print "  --help           Displays this help information"
   print


def calculate_block_means(filename, blocks_in_row):
   """" Breaks an image into a matrix that has blocks_in_row x blocks_in_row
        number of blocks, takes a mean of the RGB values of each block, and
        stores this mean into a list that is returned to the caller. """

   block_mean_list = []

   image = Image.open(filename)
   size = image.size
   block_width = size[0] / blocks_in_row
   block_height = size[1] / blocks_in_row

   curr_block = 0
   slice = Image.new("RGB", (block_width, block_height))
   for i in range(0, blocks_in_row):
       for j in range(0, blocks_in_row):
           for y_offset in range(0, block_height):
               for x_offset in range(0, block_width):
                   startx = j * block_width
                   starty = i * block_height
                   slice.putpixel((x_offset, y_offset),\
                        image.getpixel((startx + x_offset, starty + y_offset)))

           slice_stat = ImageStat.Stat(slice)
           slice_mean = slice_stat.mean
           slice_r_mean = slice_mean[0]
           slice_g_mean = slice_mean[1]
           slice_b_mean = slice_mean[2]
           final_slice_mean = (slice_r_mean + slice_g_mean + slice_b_mean) / 3

           block_mean_list.append(final_slice_mean)
           curr_block = curr_block + 1
           #print ">>> Block mean for block %d: %d" % (i+j, final_slice_mean)

   return block_mean_list


def build_mean_list(image_directory):
   """ Scans a directory for image files, takes the mean of the RGB values
       in each image file, and stores these mean values into a list.  Each
       element in this list contains a pair of image file name and mean RGB
       value.  The list is returned to the caller. """

   image_mean_list = []
   # In order to avoid some repetition in the images used for flat dark areas,
   # we keep a "least recently used" flag for every image.
   lru_list = []
   images = os.listdir(image_directory)

   for filename in images:
       try:
           # This is the next image in the list
           image = Image.open(image_directory + "/" + filename)

           # Getting mean values for the current image
           img_stat = ImageStat.Stat(image)
           img_mean = img_stat.mean
           img_r_mean = img_mean[0]
           img_g_mean = img_mean[1]
           img_b_mean = img_mean[2]
           final_img_mean = (img_r_mean + img_g_mean + img_b_mean) / 3

           image_mean_list.append((image_directory + "/" + filename,\
                                   final_img_mean))
           lru_list.append(0)
       except IOError:
           pass
       except:
           print "+++ Unknown error encountered while building mean list"

   return image_mean_list, lru_list


if __name__ == "__main__":
   # Parse command line
   try:
       opts, args = getopt.getopt(sys.argv[1:], "i:s:o:b:w:t:h:", ["help"])
   except getopt.GetoptError:
       usage()
       sys.exit(-1)

   in_image_name = None
   src_image_dir = None
   out_image_name = None
   out_image_width = -1
   out_image_height = -1
   blocks_in_row = -1
   threshold = 10

   for option, value in opts:
       if option == "--help":
           usage()
           sys.exit(0)
       if option == "-i":
           in_image_name = value
       if option == "-o":
           out_image_name = value
       if option == "-s":
           src_image_dir = value
       if option == "-t":
           threshold = string.atoi(value)
       if option == "-w":
           out_image_width = string.atoi(value)
       if option == "-h":
           out_image_height = string.atoi(value)
       if option == "-b":
           blocks_in_row = string.atoi(value)

   # Checking for invalid input
   error = False
   if in_image_name == None:
       print ">>> You must specify an input image"
       error = True
   if out_image_name == None:
       print ">>> You must specify an output image"
       error = True
   if src_image_dir == None:
       print ">>> You must specify an image src directory"
       error = True
   if blocks_in_row < 0:
       print ">>> You must specify a valid number of blocks in a row"
       error = True
   if error == True:
       usage()
       sys.exit(-1)

   # Display useful information
   print ">>> Sensitivity threshold is %d" % threshold
   print ">>> Matrix will be of size %d x %d blocks" % (blocks_in_row,\
                                                        blocks_in_row)

   # Calculating block sizes
   print ">>> Calculating block sizes"
   in_image = Image.open(in_image_name)
   if out_image_width < 0:
       out_image_width = in_image.size[0]
   if out_image_height < 0:
       out_image_height = in_image.size[1]
   block_width = out_image_width / blocks_in_row
   block_height = out_image_height / blocks_in_row
   print ">>> Blocks will be %d x %d in size" % (block_width, block_height)

   # Figuring out the mean of all the blocks in the sec image
   print ">>> Calculating means of the blocks in the src image"
   block_mean_list = calculate_block_means(in_image_name, blocks_in_row)
   print ">>> Calculated %d means" % len(block_mean_list)

   # Get a listing of the images in the source directory and build means
   print ">>> Calculating means for images in " + src_image_dir
   image_mean_list, lru_list = build_mean_list(src_image_dir)
   print ">>> Calculated %d means" % len(image_mean_list)

   # Initializing destination image
   out_image = Image.new("RGB", (out_image_width, out_image_width))

   # Building the final image
   print ">>> Building final image"

   # Go through every block in the image, figure the appropriate mean, and
   # retrieve the image necessary and put it on the output image
   for i in range(0, len(block_mean_list)):

       closest_match = 0
       block_mean = block_mean_list[i]
       match_found = False
       loop_count = -1 # Used to help determine whether or not
                       # we need to loop again with an increased threshold.
       adaptive_step = 2

       while match_found != True:

           loop_count += 1
           if loop_count > 0:
               # If we go through all the images and we don't find a
               # good match, we start adjusting the threshold
               threshold += adaptive_step
               print "+++ Increasing threshold to %d." % threshold

           for j in range(0, len(image_mean_list)):
               image_entry = image_mean_list[j]
               image_mean = image_entry[1]
               closest_match_entry = image_mean_list[closest_match]
               closest_mean_match = closest_match_entry[1]
               if abs(image_mean - block_mean) <= abs(threshold) and\
                  abs(image_mean - block_mean) <=\
                      abs(closest_mean_match - block_mean):
                   # Let's try to avoid repetition by seeing if we can find
                   # an alternate image that wasn't just used.
                   if lru_list[j] != 1:
                       closest_match = j
                       lru_list[j] = 1
                       match_found = True
                       if loop_count > 0:
                           threshold -= (loop_count * adaptive_step)
                           loop_count = -1
                           print "--- Restoring threshold to %d." % threshold
                   else:
                       lru_list[j] = 0

       match = image_mean_list[closest_match]
       image = Image.open(match[0])
       tmp = image.resize((block_width, block_height))
       for y_offset in range(0, block_height):
           for x_offset in range(0, block_width):
              starty = (i / blocks_in_row) * block_height
              startx = (i % blocks_in_row) * block_width
              out_image.putpixel((startx + x_offset, starty + y_offset),\
                                 tmp.getpixel((x_offset, y_offset)))

       print ">>> Built block %d of %d" % (i, len(block_mean_list))

# We're done.  Let's save our Mosaic
print ">>> Cropping and saving final image"
out_image = out_image.crop((0, 0, block_width * blocks_in_row,
block_height * blocks_in_row))
out_image.save(out_image_name)








On 12/14/06, Arnau Bria <[EMAIL PROTECTED]> wrote:
On Thu, 14 Dec 2006 14:30:17 +0000
Redouane Boumghar wrote:

> Hello Arnau
Hi,

> I'm sorry I didn't understand what you were looking for.
It's ok, I must improve my English!

> I proposed Image Magick and it sure can do it but with a little
> head-scratch.
>
> So if i may resume u need :
> - A parent picture
> - A list of other pictures to fill the mosaic

that's it!

> With Image Magick you can extract a portion (according to you
> discretization parameters) from the parent picture and then compare
> it with the list of pictures you have by comparing metrics like RMSE
> and then compose your mosaic with most revelant pictures at each
> portion of the parent one.
>
> I'll post a shell script for this if I have time.
> This could be fun,
That would be nice!

> Have a good day and tell me if you find a program that does it,
at this point I have only found metapixel :-( it's nice, but i'm
looking for something better.

> Red.
Thanks!
--
Arnau Bria
http://blog.emergetux.net
Wiggum: Dispara a las ruedas Lou.
Lou: eee, es un tanque jefe.
Wiggum: Me tienes hartito con todas tus excusas.
--
[email protected] mailing list




--
"If you have an apple and I have an apple and we exchange apples then
you and I will still each have one apple. But if you have an idea and
I have one idea and we exchange these ideas, then each of us will have
two ideas." - George Bernard Shaw
--
[email protected] mailing list

Reply via email to