def build_file_segments(directory): """ Builds a dict mapping all filepaths in @param directory to Segments with a 1D list for its right col and left col @param directory: path to directory containing slices @return: dict of filepath -> Segment """ files_names = imageutils.files_in_directory(directory) files = {} for file_name in files_names: img_arr = imageutils.load_image(file_name) files[file_name] = Segment(tuple(img_arr[0]), tuple(img_arr[-1])) return files
first_index = first_slice_index second_index = second_slice_index if left_overlap_score <= right_overlap_score: best_overlap_score = left_overlap_score first_on_left = True else: best_overlap_score = right_overlap_score first_on_left = False if first_on_left: slices[first_index] += slices[second_index] slices.pop(second_index) else: slices[second_index] += slices[first_index] slices.pop(first_index) return slices[0] if __name__ == '__main__': """ Constructs and opens the image formed by the slices in DATA_LOCATION. """ DATA_LOCATION = 'shredded/destination' slices = [] for file in imageutils.files_in_directory(DATA_LOCATION): image_slice = imageutils.load_image(file) slices.append(image_slice) final_image = reconstruct_slices(slices) imageutils.show_image(final_image)
images.remove(curr_slice) min_sim = 2000000000 index = 0 for i in range(len(images)): next_slice = images[i] x = min(slice_similarity(curr_slice, next_slice), slice_similarity(next_slice, curr_slice)) if x < min_sim: min_sim = x index = i next_slice = images[index] if slice_similarity(curr_slice, next_slice) < slice_similarity(next_slice, curr_slice): images[index] = curr_slice + images[index] else: images[index] = images[index] + curr_slice if __name__ == '__main__': """ Opens file and reads it using a list comprehension into a list called images. After reconstructing the image, this method then displays the image and saves it to the hard drive. """ IMGS_DIR = 'shredded/destination' images = [imageutils.load_image(filename) for filename in imageutils.files_in_directory(IMGS_DIR)] reconstruct_image(images) imageutils.show_all_images(*images) imageutils.save_image(images[0], 'final-destination')
if first_overlap_score <= second_overlap_score: best_overlap_score = first_overlap_score first_slice_on_left = True else: best_overlap_score = second_overlap_score first_slice_on_left = False first_slice_index = first_slice_index if first_slice_on_left: slices[first_index] += slices[second_index] slices.pop(second_index) else: slices[second_index] += slices[first_index] slices.pop(first_index) return slices[0] """ TA Grading Comment: Yeesh. A little messy. I get it was the last one and you wanted to knock it out. """ if __name__ == '__main__': DATA_FILES = 'shredded/destination' slices = list() for f in imageutils.files_in_directory(DATA_FILES): piece = imageutils.load_image(f) slices.append(piece) imageutils.show_image(reconstruct_slices(slices))
''' ***** beautiful. glad you took advantage of the fact that pixels are simply tuples ''' def pixel_similarity(p1, p2): """ Determine how similar two input pixels by summing the squares of the absolute difference for each color component @param: tuple of 4 representing 2 color components @return: float representing the sum """ return sum(map(lambda component: (component[0] - component[1])**2, zip(p1, p2))) if __name__ == '__main__': DESTINATION = "grail4" img_name_list = imageutils.files_in_directory(DESTINATION) #get all the image file names in the destination folder complete_list = [] #list of all 2Darrays representing slices for img_name in img_name_list: pixel_list = load_image(img_name) complete_list.append(pixel_list) current_piece = complete_list.pop(0) #take out the first data list while len(complete_list)>0: #repeat the process there is no more image pieces in the list to look at min_diff = 1000000000000000 #some really large number next_piece = current_piece #look for the next_piece that matches the current piece the best for compared_piece in complete_list: #check both cases when current_piece is on either the left or the right of the compared_piece if min(slice_similarity(current_piece, compared_piece), slice_similarity(compared_piece, current_piece)) < min_diff: next_piece = compared_piece #determine the left-right order of current_piece and next_piece. Merge the two pieces together and update the current_piece
""" Returns the image array for the given filename, using imageutils. """ return imageutils.load_image(filename) def stitch_images(img1, img2): """ Appends the columns of img2 to the right of img1's existing columns. """ img1 += img2 return img1 if __name__ == '__main__': DIRNAME = "./shredded/destination" all_image_slices = [] print("Loading images...") for filename in imageutils.files_in_directory(DIRNAME): next_image = get_image_array(filename) if not next_image: print("Error while loading image!") all_image_slices.append(next_image) print("done!") INITIAL_SLICE_COUNT = len(all_image_slices) # Let's build a distance matrix for the slices distances = [[INFINITY for i in range(INITIAL_SLICE_COUNT)] for j in range(INITIAL_SLICE_COUNT)] for i in range(INITIAL_SLICE_COUNT): for j in range(i + 1, INITIAL_SLICE_COUNT): distances[i][j] = left_distance(all_image_slices[i], all_image_slices[j]) distances[j][i] = left_distance(all_image_slices[j], all_image_slices[i])
# Computes the difference between all the components of two pixels. # sqrts it to value matches with most very close and a few far away # over those that are somewhat close across the board. # Both args are imageutils pixels. Returns a float. def pixDiff(pix1, pix2): return sqrt(sum([abs(com[0]-com[1]) for com in zip(pix1, pix2)])) # Computes the sum of the differences amonst all the pixels in the # rightmost edge of lhs and leftmost edge of rhs. Both args are # tuples of imageutils pixels. Returns a float. @lru_cache(maxsize=None) def colDiff(lhs, rhs): return sum([pixDiff(pixs[0], pixs[1]) for pixs in zip(lhs, rhs)]) if __name__ == '__main__': strips = [list(map(tuple, imageutils.load_image(file))) for file in imageutils.files_in_directory(dir)] """ TA Grading Comment: file is a keyword watch out True = False """ while len(strips) > 1: besti, bestj, bestDiff = 0, 0, -1 for i in range(len(strips)): for j in range(len(strips)): if i == j: continue diff = colDiff(strips[i][-1], strips[j][0]) if bestDiff == -1 or diff < bestDiff: bestDiff, besti, bestj = diff, i, j strips[besti] += strips[bestj]
for p1, p2 in zip(col1, col2): sim_score += pixel_sim(p1, p2) return sim_score def pixel_sim(pixel1, pixel2): """ Helper function that compares two Pixel objects by computing the sum of the square of each of the pixel differences, between red, green, blue, and alpha. This value is returned and used in column_sim. """ return sum([(pixel1.red - pixel2.red)**2, (pixel1.green - pixel2.green)**2, (pixel1.blue - pixel2.blue)**2, (pixel1.alpha - pixel2.alpha)**2]) if __name__ == '__main__': pass dirname = "shredded/grail20/" #reads in all the vertical slice image files and put them into a list files_list = imageutils.files_in_directory(dirname) image_files = [imageutils.load_image(file) for file in files_list] #reassembles the list of slices and renders the image reassemble_slices(image_files) imageutils.show_all_images(*image_files, buffer_width=0)
def get_all_images(): ''' Gets all the images from the named file (relative path) and places them in a dict with an number key for each picture array. I'll use that key throughout to track the proper reordering of the slices. Returns dict. ''' pic_map = {} pic_files = imageutils.files_in_directory("shredded/destination") pic_key = 0 for pic in pic_files: pic_col_array = imageutils.load_image(pic) pic_map[pic_key] = pic_col_array pic_key += 1 return pic_map def pixel_similarity(base_pixel, cmp_pixel): ''' Basic helper that computes the similarity score between two pixels by finding the square of the absolute value of the difference between each Pixel field (RGBA) and suming those diffs The larger the return value, the less similar ''' diffs = [] diffs.append(abs(base_pixel.red - cmp_pixel.red)**2) diffs.append(abs(base_pixel.green - cmp_pixel.green)**2) diffs.append(abs(base_pixel.blue - cmp_pixel.blue)**2) diffs.append(abs(base_pixel.alpha - cmp_pixel.alpha)**2) return sum(diffs) def column_similarity(rightmost_piece, leftmost_piece): ''' Takes two pieces, which are one-column slices from the larger slice and computes their similarity. Run a for loop over over each pixel down the two columns, passing each pixel pair to pixel_similarity. Returns similarity score for the columns, which is equivalent to simiarlity score for two slices, because the columns represent rightmost and leftmost column of two slices, respectively. ''' sim_score_list = [] for n in range(len(rightmost_piece)): sim_score_list.append(pixel_similarity(rightmost_piece[n], leftmost_piece[n])) return sum(sim_score_list) def slice_similarity(this_slice, this_key, slice_map, master_repository): ''' Computes the similarity scores for one slice compared against every other slice from the picture. Grabs the rightmost column from base slice (since that's where we would glue it to another slice) and then grabs the leftmost column of every other slice, comparing each right-left pair for similarity. Places the similarity score into a dict, with the key being a tuple indicating which two slices (which pair) that similarity score represents. ''' #need to grab rightmost piece from this_slice and left_most from every other slice rightmost_piece = this_slice[-1] #compute similarity scores between this key and every other slice for key, other_slice in slice_map.items(): if(key != this_key): leftmost_piece = other_slice[0] pair_score = column_similarity(rightmost_piece, leftmost_piece) master_repository[tuple([this_key, key])] = pair_score def piece_image_together(master_repository, slice_map): ''' Takes the master_repo, which is the dictionary with all the similarity scores in it, and uses it to figure out which slices ought to be glued together. Does this by: - Sorting the repo such that the most similar slice pairing are first in the repo - Iterating through the sorted repo to grab the next-most-similar pair and gluing those two together. Builds a list that contains the tuples in the order in which they should be combined - Passes that list of tuples to the helper "stich_list", which turns the tuples into one ordered list without any repeating key numbers. The result lists the slices in the order in which they should be combined - Then combines those slices from the slice_map into one 2D array and calls show_image ''' already_combined_keys = list() final_order_list = [] sorted_repo = sorted(master_repository, key=(lambda k: master_repository[k])) counter = 0 for key in sorted_repo: #max_key = max(slice_map.keys(), key=(lambda k: len(slice_map[k]))) if(counter == (len(slice_map) - 1)): break if(key in already_combined_keys): continue final_order_list.append(key) key1, key2 = key already_combined_keys.append(tuple([key2, key1])) key2_list = list(filter(lambda key: key[1] == key2, master_repository)) for two_key in key2_list: already_combined_keys.append(two_key) counter += 1 init_start, init_end = final_order_list[0] sub_list = [] sub_list.append(init_start) sub_list.append(init_end) final_order = stitch_list(sub_list, init_start, init_end, final_order_list) build_final_pic_array(final_order, slice_map) def build_final_pic_array(final_order, slice_map): ''' Takes final_order array, which lists the slices in the order they should be combined (identifying each by its key number) and builds the final slice_map according. Passes that final slice array to show_image to get the picture ''' start = final_order[0] for n in final_order: if(n != start): slice_map[start] += slice_map[n] imageutils.show_image(slice_map[start]) def stitch_list(sub_list, start, end, final_order_list): ''' Recursive function that takes the list of tuples which shows the slice pairings that ought to be glued and turns all those pair tuples into one continuous list, from leftmost slice to rightmost. Basically, any tuple (key1, key2) would be added to the end of a tuple (keyX, key1) and to the front of a tuple (key2, keyY). Uses recursion to stitch the tuples together like this. Returns the final stitched list. ''' start_is_key2 = [key for key in final_order_list if key[1] == start] end_is_key1 = [key for key in final_order_list if key[0] == end] if(start_is_key2 == [] and end_is_key1 == []): return sub_list new_sub_list = [] if(start_is_key2 != []): new_start_tup = start_is_key2[0] new_start = new_start_tup[0] new_sub_list.append(new_start) else:ether(master_repository, slice_map) if __name__ == '__main__': slice_map = get_all_images() slice_similarity_control(slice_map)
You have a hand not only in the program implementation, but also in the program design. As such, take a moment to plan out your approach to this problem. How will you merge the image slices? You can import any builtin libraries you need (i.e. itertools, operator, etc), but do not use any 3rd party libraries (outside of Pillow, which we've provided through the imageutils module) Best of luck! Now go find that Holy Grail. """ import imageutils import itertools if __name__ == '__main__': images = [] for filename in imageutils.files_in_directory('shredded/grail4'): images.append(imageutils.load_image(filename)) imageutils.show_all_images(images) reassembled_image = reassemble(images) imageutils.show_image(reassembled_image) ''' ***** alternatively, for pixel_similarity1 you can use the fact that pixels are tuples: return sum([(component[0] - component[1])**2 for component in zip(p1, p2)]) ''' def pixel_similarity1(pixel1, pixel2): return (pixel1.red - pixel2.red)**2 + (pixel1.green - pixel2.greem)**2 + (pixel1.blue - pixel2.blue)**2 + (pixel1.alpha - pixel2.alpha)**2 '''
best_score = sim best_pair = (pair[0], pair[1]) return best_pair def stitch(imgs): """ FUNCTION: stitch Stitches together all the shreds specified in imgs by searching for the pairs with highest similarity and iteratively reassembling the image. @params: imgs: dict mapping a unique key to a 2D array representing an image slice. @return: reassembled image represented via 2D array. """ while len(imgs) > 1: pair = get_best_pair(imgs) stitched = imgs[pair[0]] + imgs[pair[1]] # Combine the pair of slices. del imgs[pair[0]] # Delete the slices we just used ... del imgs[pair[1]] # ...and create a unique key & store the new slice imgs["({})-({})".format(*pair)] = stitched return imgs.popitem()[1] if __name__ == '__main__': # Associate each 2D array with a unique key imgs = {i: imageutils.load_image(filename) for i, filename in enumerate( imageutils.files_in_directory("./shredded/grail20"))} imageutils.show_image(stitch(imgs))
return sum(similarities) / len(similarities) def compare_shreds(right_col_shred, left_col_shred, column_compare_func): """ Compares the right-most column of one shred to the left-most column of another using provided comparison function returns the similarity score for the two columns """ return column_compare_func(right_col_shred[-1], left_col_shred[0], cosine_similarity) if __name__ == "__main__": SHREDS_DIR = "shredded/destination/" shred_files = iu.files_in_directory(SHREDS_DIR)[1:] shreds = [] for filename in shred_files: shreds.append(iu.load_image(filename)) ##Note: in the future—make your code a bit more modular and decompose this main function a bit! # ordered_shreds will contain the shreds reassembled in the correct order ordered_shreds = [shreds.pop(0)] # while unordered shreds remain while len(shreds) > 0: max_right_to_left_sim = float("-Inf") candidate_insert_right_shred = None max_left_to_right_sim = float("-Inf") candidate_insert_left_shred = None # loop over all remaining shreds
highestOne.append(column) def mergeClosestSlices(slices): """ Gets the two closest slices and merges them together """ lowestSimilarity = 9999999999999 for left in slices: for right in slices: if left != right: currSim = sliceSimilarity(left, right) if currSim < lowestSimilarity: lowestSimilarity = currSim leftHigh = left rightHigh = right mergeSlices(leftHigh, rightHigh) slices.remove(rightHigh) if __name__ == '__main__': slices = [] for image in imageutils.files_in_directory("shredded/destination"): slices.append(imageutils.load_image(image)) while len(slices) > 1: mergeClosestSlices(slices) imageutils.show_image(slices[0])
while(num_slices > 1): highest = 442.0 for i_ind, i in enumerate(slices): for j_ind, j in enumerate(slices): if i != j: sim = slice_similarity(i, j) if sim < highest: highest = sim highest_ind[0] = i_ind highest_ind[1] = j_ind slices[highest_ind[0]] = slices[highest_ind[0]] + slices[highest_ind[1]] slices.remove(slices[highest_ind[1]]) num_slices -= 1 return slices[0] if __name__ == '__main__': """ Opens directory of image slices and translates into list pixel arrays, then stiches together original image and opens it """ file_names = imageutils.files_in_directory('shredded/destination') slices = [] for file in file_names: pixels = imageutils.load_image(file) slices.append(pixels) imageutils.show_image(stitch(slices)) #great functional programming on this one!
minSlice = slices.index((slices[s][0], slices[s][1])) answer.append(minSlice) remaining.remove(minSlice) return answer if __name__ == '__main__': """ Puts together the slices and store it as a file named 'map' Also prints the corresponding message on console. MESSAGES: 1) HOLY 2) YOU FOUND A MESSAGE! """ IMAGE_DIRECTORY = 'shredded/destination' files = iu.files_in_directory(IMAGE_DIRECTORY) # Stores tuple (filename, pixels) slices = [(fn, iu.load_image(fn)) for fn in files] answer = glue_together(slices) tm = [] kw = "" for a in answer: kw += slices[a][0][-5] tm += slices[a][1] iu.save_image(tm, 'map') print(kw) #great decomposition on this one! loved the functional programming of this one
# get closest slice match and combine best_combo = best_combos(slices) combined = best_combo[0] + best_combo[1] # also combine strings and update strings array i1 = slices.index(best_combo[0]) i2 = slices.index(best_combo[1]) result_string = combined_strings[i1] + combined_strings[i2] combined_strings.pop(i1) combined_strings.pop(i2 if i2 < i1 else i2 - 1) combined_strings.append(result_string) # remove individual slices and add combined slices.remove(best_combo[0]) slices.remove(best_combo[1]) slices.append(combined) # print the hidden message and return a single slice comtaining the whole image print (combined_strings[0]) return slices[0] def combine_images(image_list, filename): imageutils.save_image(combine_arrays([imageutils.load_image(i) for i in image_list]), filename) if __name__ == '__main__': image_list = imageutils.files_in_directory('shredded/grail20/') combine_images(image_list, 'result') #beautiful