def test_green_screen_removal2(img): # parse through file list in the current directory start = timeit.default_timer() img = img.convert("RGBA") pixdata = img.load() green_offset = 39 # Replace all known green screen values for y in xrange(img.size[1]): for x in xrange(img.size[0]): r, g, b, a = img.getpixel((x, y)) non_green_max = r if r > b else b green_threshold = (non_green_max + green_offset) # if ((r <= 110) and (g > 112) and (b < 120) and (b < g)) \ # or (g - b > 50 and r <= 110 and g >= 100): if g > green_threshold: pixdata[x, y] = (255, 255, 255, 0) # Remove anti-aliasing outline of body. elif r == 0 and g == 0 and b == 0: pixdata[x, y] = (255, 255, 255, 0) img2 = img.filter(ImageFilter.GaussianBlur(radius=1)) img2.save(configuration.get("outbox", "test_outbox"), "PNG") stop = timeit.default_timer() configuration.log_debug_out(configuration.inspect.stack()[0][3], "It took {0} seconds".format(stop - start))
def add_image_height(img, height): # pixdata = img.load() # arr = [] # for x in range(img.size[0]): # row = [] # for y in range(img.size[1]): # p = pixdata[x, y] # row.append(p) # arr.append(row) # # for x in range(height): # arr.append([0] * len(arr[0])) # return Image.fromarray(np.array(arr)) if type(img) == type(str): i = Image.open(img) else: i = img img = i.convert('RGBA') configuration.log_debug_out(configuration.inspect.stack()[0][3], "img.size = {0}".format(i.size)) image_width, image_height = i.size new_image = Image.new('RGBA', (image_width + height, image_height)) configuration.log_debug_out(configuration.inspect.stack()[0][3], "new_image.size = {0}".format(new_image.size)) pixeldata = new_image.load() for x in range(image_width): for y in range(image_height): pixeldata[x, y] = (100, 255, 100, 1) new_image.paste(img, (height - 1, 0)) # new_image.save(os.path.expanduser("~/Desktop/bigger_image.jpg")) return new_image
def replace_background(img, replacement, green_offset=configuration.getint( "green_screen", "offset")): # Start internal function timer start = timeit.default_timer() # configuration.log_debug_out(configuration.inspect.stack()[0][3], "Opening {0}".format(filename)) if isinstance(img, str): image = Image.open(img) else: image = img image = image.convert("RGBA") if image.size[:2][0] > image.size[:2][1]: image = image.rotate(90, expand=True) # Open the image and load the pixels # img = Image.open(filename) # img = img.convert("RGBA") pixdata = image.load() # if len(gs.green_pixels) > 0: if False: for (x, y) in gs.green_pixels: try: pixdata[x, y] = replacement except: pass else: # Replace all known green screen values with transparent values (0, 0, 0) for y in xrange(image.size[1]): for x in xrange(image.size[0]): try: r, g, b, a = pixdata[x, y] except: r, g, b = pixdata[x, y] # This is based off of the 2015 green screen removal code from Joe Lester # Calculate the non green max and the threshold from the offset non_green_max = max(r, b) green_threshold = (non_green_max + green_offset) # If the green pixel is greater than the threshold we make it transparent (0, 0, 0, 0) if g > green_threshold: pixdata[x, y] = replacement # # Save the image # saved_path = Utilities.save_image(filename=filename, img=img, outbox=outbox, image_type=image_type) # Stop the internal function timer and log it stop = timeit.default_timer() configuration.log_debug_out( configuration.inspect.stack()[0][3], "It took {0} seconds to replace greenscreen".format(stop - start)) # Return the new image return image
def green_screen_removal_2015(image, background=Image.open(configuration.get_wd("green_screen", "background")), green_offset=int(configuration.get("green_screen", "offset"))): if not configuration.getboolean("green_screen", "remove_green_screen"): return image # Start the internal function timer start = timeit.default_timer() # Open the image and background image and get the pixel data from each img = image img = img.convert("RGBA") bg_img = background bg_img = bg_img.convert("RGBA") pixdata = img.load() bg_pixdata = bg_img.load() should_check_alpha = pixdata[0, 0][3] == 0 # if img.size[:2][0] > img.size[:2][1]: # img = img.rotate(90, expand=True) # pixdata = img.load() # Replace all known green screen values for y in xrange(img.size[1]): for x in xrange(img.size[0]): try: # Get the RGBA values from each pixel r, g, b, a = pixdata[x, y] # Calculate which value is highest non_green_max = max(r, b) # Determine the green threshold from the difference of the green offset from the non green max green_threshold = (non_green_max + green_offset) # If the green value in this pixel meets our conditions replace it with the background if should_check_alpha: if a == 0: pixdata[x, y] = bg_pixdata[x, y] green_pixels.append([x, y]) elif g > green_threshold: pixdata[x, y] = bg_pixdata[x, y] green_pixels.append([x, y]) except: configuration.log_debug_out(configuration.inspect.stack()[0][3], "(x,y) = {0}".format((x, y))) # Save the image # saved_path = Utilities.save_image(filename=filename, img=img, outbox=outbox, image_type=image_type) # Stop and log the internal function time stop = timeit.default_timer() configuration.log_debug_out(configuration.inspect.stack()[0][3], "It took {0} seconds to remove greenscreen".format(stop - start)) return img
def check_file_extension(filename, image_type): filetype = filename.lower().split('.')[-1] if image_type in ["guitar", "case"]: if filetype not in guitar_supported_filetypes: configuration.log_debug_out( configuration.inspect.stack()[0][3], "Rejecting bad guitar/case {0} with bad file extension".format( filename)) ErrorHandler.reject_image(filename=filename) ErrorHandler.sys_exit(configuration.EXIT_STATUS.BAD_FILE_EXTENSION) else: configuration.log_debug_out(configuration.inspect.stack()[0][3], "Unknown type") ErrorHandler.sys_exit(configuration.EXIT_STATUS.BAD_TYPE)
def get_background(image, background=None, background_landscape=None): # Default to guitar background if background is None: background = configuration.get_wd("green_screen", "background") if background_landscape is None: background_landscape = configuration.get_wd("green_screen", "background_land") oriimage = cv2.imread(image) bg_image = cv2.imread(background) # Determine if we need to resize im_height, im_width = oriimage.shape[:2] bg_height, bg_width = bg_image.shape[:2] configuration.log_debug_out(configuration.inspect.stack()[0][3], "Image Size") configuration.log_debug_out( configuration.inspect.stack()[0][3], "im_height = {0}, im_width = {1}".format(im_height, im_width)) # Resize to background size if bg_height > im_height: background = background_landscape bg_image = cv2.imread(background) bg_height, bg_width = bg_image.shape[:2] configuration.log_debug_out( configuration.inspect.stack()[0][3], "Using background image at {0}".format(background)) if bg_height != im_height or bg_width != im_width: bg_image = cv2.resize(bg_image, (im_width, im_height)) cv2.imwrite(background + "_sized.png", bg_image) background += "_sized.png" bg_height, bg_width = bg_image.shape[:2] configuration.log_debug_out(configuration.inspect.stack()[0][3], "Background Size") configuration.log_debug_out( configuration.inspect.stack()[0][3], "bg_height = {0}, bg_width = {1}".format(bg_height, bg_width)) return background
def test_green_screen_removal(img): # parse through file list in the current directory start = timeit.default_timer() img = img.convert("RGBA") pixdata = img.load() red_threshold = 110 green_threshold = 112 blue_threshold = 120 blue_green_diff_threshold = 50 red_green_diff_threshold = 50 # Replace all known green screen values for y in xrange(img.size[1]): for x in xrange(img.size[0]): # Initialize variables r1 = r2 = g1 = g2 = b1 = b2 = a1 = a2 = None # Get current pixel r, g, b, a = img.getpixel((x, y)) # Get next pixel if x < img.size[0] and y + 1 < img.size[1]: r2, g2, b2, a2 = img.getpixel((x, y+1)) # if ((r <= red_threshold) and (g > green_threshold) and (b < blue_threshold) and (b < g) and (r < g)) \ # or (g - b > blue_green_diff_threshold and r <= 150 and g >= 100): # if (g - b > blue_green_diff_threshold and r <= 150 and g >= 100): if ((g - b) > blue_green_diff_threshold and (g - r) > red_green_diff_threshold and g >= 100) or ((r <= red_threshold) and (g > green_threshold) and (b < blue_threshold)): set_pix_data = True if g2 is not None: if not (r2 <= red_threshold) and (g2 > green_threshold) and (b2 < blue_threshold) and (b2 < g2) and (r2 < g2): set_pix_data = False if set_pix_data: pixdata[x, y] = (255, 255, 255, 0) else: pixdata[x, y] = (r2, g2, b2, a2) # Remove anti-aliasing outline of body. elif r == 0 and g == 0 and b == 0: pixdata[x, y] = (255, 255, 255, 0) img2 = img.filter(ImageFilter.GaussianBlur(radius=1)) img2.save(configuration.get("outbox", "test_outbox"), "PNG") stop = timeit.default_timer() configuration.log_debug_out(configuration.inspect.stack()[0][3], "It took {0} seconds".format(stop - start))
def process_guitar(filename): try: img = Image.open(filename) except: configuration.log_debug_out( configuration.inspect.stack()[0][3], "Could not find image at path {0}".format(filename)) ErrorHandler.sys_exit(configuration.EXIT_STATUS.FILE_NOT_FOUND) # Fix rotation angle if we think it's landscape if img.size[:2][0] > img.size[:2][1]: img = img.rotate(90, expand=True) save_path = "{0}/{1}".format(configuration.get("guitar", "save_base_dir"), filename.split('/')[-1]) img.save(save_path) # Process the guitar configuration.log_debug_out(configuration.inspect.stack()[0][3], "Processing {0}".format(filename)) background = Utilities.get_background_from_image(img) image = gs.green_screen_removal_2015(image=img, background=background) watermark_image = add_watermark(image=image, image_type="guitar") make_guitar_images(image=watermark_image, filename=filename)
def get_case_height2(case): # gs.green_screen_y_cb_cr(case, background=Utilities.get_background(case)) # Open and conver to RGBA img = Image.open(case) img = img.convert("RGBA") # Replace the green screen in the case image case = gs.green_screen_removal_2015( img, background=Utilities.get_background_from_image(img), green_offset=30) configuration.log_debug_out( configuration.inspect.stack()[0][3], "Case size: x = {0}, y = {1}".format(img.size[0], img.size[1])) # Get the height and width of the image width = img.size[0] height = img.size[1] # Calculate the height based on one-third of the image height y = int(height * 0.333333) # Return the width of the image, the calculated height, and the cropped image return width, y, case.crop((0, y, width, height))
def make_guitar_images(image, filename, outbox=configuration.get("outbox", "outbox1")): # Log start time and start internal timer for this method configuration.logging.info( "Starting image thumbnails for {0}".format(image)) start = timeit.default_timer() try: guitar_model, guitar_serial, guitar_shot, color = filename.split( '/')[-1].split('--') except: guitar_model, guitar_serial, guitar_shot = filename.split( '/')[-1].split('--') file_type = filename.split('.')[-1] base_dir = "{0}/{1}/{2}/{3}".format(outbox, guitar_model[0], guitar_model, guitar_serial) if not os.path.exists(base_dir): os.makedirs(base_dir) image.save("{0}/{1}--{2}.{3}".format(base_dir, guitar_serial, guitar_shot, file_type)) # Loop through each size for s in sizes.keys(): si = sizes[s].split('x') size = (int(si[0]), int(si[1])) configuration.log_debug_out(configuration.inspect.stack()[0][3], "Resizing to {0}".format(size)) configuration.log_debug_out(configuration.inspect.stack()[0][3], "{0} = {1}".format(s, size)) img = image.copy() if s == "transparent" and guitar_shot in configuration.get( "transparent", 'transparent_shots').split(','): img = make_transparent(filename) elif s == "landscape": img = img.rotate(-90, expand=True) height = img.size[0] width = img.size[1] half_the_width = width / 2 half_the_height = height / 2 to_remove = -(height / 2 - width) img = img.crop((half_the_height - half_the_height, half_the_width - ((width - to_remove) / 2), half_the_height + half_the_height, half_the_width + ((width - to_remove) / 2))) # Thumbnail using antialias instead of bicubic img.thumbnail(size, Image.ANTIALIAS) # Save image with image previous image file type configuration.log_debug_out(configuration.inspect.stack()[0][3], "Uploading non-transparent shot") save_path = "{0}/{1}-{2}-{3}.{4}".format(base_dir, guitar_serial, guitar_shot, s, "jpg") configuration.log_debug_out(configuration.inspect.stack()[0][3], "Saving to {0}".format(save_path)) img.save(save_path) configuration.log_debug_out( configuration.inspect.stack()[0][3], "Uploading {0} with size {1}".format(filename, s)) # Stop the timer and log time taken for this method stop = timeit.default_timer() configuration.log_debug_out( configuration.inspect.stack()[0][3], "It took {0} seconds to thumbnail the image".format(stop - start))
def add_watermark(image, image_type, watermark=configuration.get("watermark", "basic_watermark_path")): # Open image and get height and width configuration.log_debug_out(configuration.inspect.stack()[0][3], "Image size = {0}".format(image.size)) # If this is a guitar we want it to be portrait if image_type == "guitar": # And it's length is greater than the width we add an EXIFTAG for rotation so that it shows with the correct orientation if image.size[:2][0] > image.size[:2][1]: configuration.log_debug_out(configuration.inspect.stack()[0][3], "Rotating image for watermark") image = image.rotate(90, expand=True) img_width, img_height = image.size configuration.log_debug_out(configuration.inspect.stack()[0][3], "Image size before = {0}".format(image.size)) # Get watermark info watermark_image = Image.open(watermark) watermark_width, watermark_height = watermark_image.size scale = configuration.getfloat("watermark", "watermark_scale") configuration.log_debug_out(configuration.inspect.stack()[0][3], "Resizing watermark for guitar gallery") new_size = int(scale * watermark_width), int(scale * watermark_height) configuration.log_debug_out(configuration.inspect.stack()[0][3], "new_size = {0}".format(new_size)) watermark_image = watermark_image.resize(new_size, Image.ANTIALIAS) watermark_height, watermark_width = watermark_image.size configuration.log_debug_out( configuration.inspect.stack()[0][3], "watermark_image.size = {0}".format(watermark_image.size)) configuration.log_debug_out( configuration.inspect.stack()[0][3], "Watermark height = {0}, nWatermark Width = {1}".format( watermark_height, watermark_width)) # Paste the watermark at the y value # The x value comes from half the watermark width being subtracted from half the width of the image # This centers the watermark on the image # image.paste(watermark_image, (int((img_height / 2) - (watermark_width / 2)), int(img_width - int(watermark_height / 3.0))), watermark_image) # Paste (x, y) configuration.log_debug_out( configuration.inspect.stack()[0][3], "(int((float(img_width) / 2) - (float(watermark_width))), int(img_height + (1.5 * watermark_height))) = {0}" .format((int((float(img_width) / 2) - (float(watermark_width))), int(img_height - (1.5 * watermark_height))))) # image.paste(watermark_image, (int((float(img_width) / 2) - (float(watermark_width))), int(img_height + (1.5 * watermark_height))), watermark_image) # image.size = (4480, 6820) # watermark_image.size = (467, 112) # (4480/2) - (467/2) = 2007 # 6820 - 112 - 10 = 6698 # The 10 is for a padding on the bottom of the image # image.paste(watermark_image, (2007, image.size[1] - watermark_image.size[1] - 10), watermark_image) image.paste(watermark_image, (int((image.size[0] / 2.0) - (watermark_image.size[0] / 2.0)), image.size[1] - watermark_image.size[1] - 10), watermark_image) configuration.log_debug_out( configuration.inspect.stack()[0][3], "Image size after adding watermark {0}".format(image.size)) return image
def process_image(filename, image_type): # Check for a valid file extension check_file_extension(filename=filename, image_type=image_type) # Start internal function timer configuration.log_debug_out( configuration.inspect.stack()[0][3], "Processing {0}{1}".format( filename, "-" * (150 - len("Processing {0}".format(filename))))) start = timeit.default_timer() configuration.log_debug_out( configuration.inspect.stack()[0][3], "Processing image type: {0}".format(image_type)) # Handle the image type accordingly if image_type == "case": if "case3" in filename: configuration.log_debug_out(configuration.inspect.stack()[0][3], "ENTERING CASE MODE") cases.process_cases(filename=filename) else: configuration.logging.warn( "Waiting for third case file to process cases") ErrorHandler.sys_exit(configuration.EXIT_STATUS.WAITING_FOR_CASES) elif image_type == "guitar": configuration.log_debug_out(configuration.inspect.stack()[0][3], "ENTERING GUITAR MODE") guitar_process.process_guitar(filename=filename) else: configuration.log_debug_out(configuration.inspect.stack()[0][3], "Could not determine image type") ErrorHandler.sys_exit(configuration.EXIT_STATUS.BAD_TYPE) # Stop internal function timer and log the info stop = timeit.default_timer() # If we are not testing we want to remove the source image if not configuration.TESTING: try: os.remove(filename) except: configuration.log_debug_out( configuration.inspect.stack()[0][3], "Failed to remove file {0}".format(filename)) configuration.log_debug_out( configuration.inspect.stack()[0][3], "It took {0} seconds to process image{1}\n".format( stop - start, "-" * (150 - len( "It took {0} seconds to process image".format(stop - start)))))
def test_method(**kwargs): configuration.log_debug_out(configuration.inspect.stack()[0][3], "Entering test method") return
args = parser.parse_args() # Perform a sanity check on the filesystem sanity_check() # Check if we are testing if args.testing or configuration.TESTING: test_method(image=sys.argv[1] if len(sys.argv) > 1 else None) # If the two necessary arguments are missing show usage and exit if Utilities.string_is_none_or_empty(args.path): show_help_and_die(parser=parser) # Do not process the image if we do not know the type if Utilities.string_is_none_or_empty(args.type): configuration.log_debug_out(configuration.inspect.stack()[0][3], "Bad file type") ErrorHandler.sys_exit(configuration.EXIT_STATUS.BAD_TYPE) else: image_type = args.type # Set the log verbosity if args.verbose is not None: configuration.logging.basicConfig(stream=sys.stderr, level=configuration.logging.WARNING) if args.very_verbose is not None: configuration.logging.basicConfig(stream=sys.stderr, level=configuration.logging.DEBUG) # Attempt to open a log file, will fail if there are incorrect permissions on the output folder try: if configuration.getboolean("logging", "enabled"):
def get_background_from_image(image, background=None, background_landscape=None): if background is None: background = configuration.get_wd("green_screen", "background") if background_landscape is None: background_landscape = configuration.get_wd("green_screen", "background_land") configuration.log_debug_out( configuration.inspect.stack()[0][3], "Opening background = {bg}".format(bg=background)) configuration.log_debug_out( configuration.inspect.stack()[0][3], "Opening background_landscape = {bg}".format(bg=background_landscape)) # # Check if we have already created this background and if we have do either of the _sized images match our current images size # # If so we can just use this one instead of resizing # bg_previous_size = configuration.working_directory + background + "_sized.png" # bg_previous_land_size = configuration.working_directory + background_landscape + "_sized.png" # if os.path.isfile(bg_previous_size): # bg_image = Image.open(bg_previous_size) # if bg_image.size == image.size: # return bg_image # # if os.path.isfile(bg_previous_land_size): # bg_image = Image.open(bg_previous_land_size) # if bg_image.size == image.size: # return bg_image oriimage = image bg_image = Image.open(background) # Determine if we need to resize im_width, im_height = oriimage.size bg_width, bg_height = bg_image.size configuration.log_debug_out(configuration.inspect.stack()[0][3], "Image Size") configuration.log_debug_out( configuration.inspect.stack()[0][3], "im_height = {0}, im_width = {1}".format(im_height, im_width)) # Resize to background size if bg_height > im_height: background = background_landscape bg_image = Image.open(background) bg_width, bg_height = bg_image.size if bg_height != im_height or bg_width != im_width: configuration.log_debug_out(configuration.inspect.stack()[0][3], "Resizing background") bg_image = bg_image.resize((im_width, im_height), Image.BICUBIC) bg_height, bg_width = bg_image.size configuration.log_debug_out(configuration.inspect.stack()[0][3], "Background Size") configuration.log_debug_out( configuration.inspect.stack()[0][3], "bg_height = {0}, bg_width = {1}".format(bg_height, bg_width)) # configuration.log_debug_out(configuration.inspect.stack()[0][3], "Using background image at {0}".format(background)) return bg_image
def get_rotation_angle(file): img = cv2.imread(file).copy() im_height, im_width = img.shape[:2] # If the photo is rotated if im_width > im_height: # img = rotate_image(img, 90) img = ndimage.rotate(img, 90) # Convert the image to gray to help with edge detection gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150, apertureSize=3) # Check if we have found an angle angle_found = False angles = [] angle_to_rotate = 0 # Calculate the hough lines from the image lines = cv2.HoughLines(edges, 1, np.pi / 180, 200) # Loop throgh the found lines in the image for rho, theta in lines[0]: a = np.cos(theta) b = np.sin(theta) x0 = a * rho y0 = b * rho x1 = int(x0 + 1000 * (-b)) y1 = int(y0 + 1000 * a) x2 = int(x0 - 1000 * (-b)) y2 = int(y0 - 1000 * a) # Calculate the angle beteen two points on the line angle_to_rotate = get_angle_between_points(x1, y1, x2, y2) # If the angle is greater than pi restrict it to the first half if angle_to_rotate > pi: angle_to_rotate = pi - angle_to_rotate # Else if the angle is less than pi bring it back to the upper half elif angle_to_rotate < pi: angle_to_rotate = pi + angle_to_rotate # Add this angle to the list of angles angles.append(get_angle_between_points(x1, y1, x2, y2)) # DEBUG -- If we haven't found an angle force it true if not angle_found or angle_to_rotate > angle_found: angle_found = angle_to_rotate angle_found = True # print("New angle_to_rotate: {0}".format(angle_to_rotate)) # print("Angle of line: {0}".format(angle_to_rotate)) # For debugging add the calculate line to the image cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) # Determine the average angle from the max of the set angles_mode = max(set(angles), key=angles.count) # print "Average Angle: {0}".format(sum(angles)/len(angles)) configuration.log_debug_out(configuration.inspect.stack()[0][3], "Mode of angles: {0}".format(angles_mode)) # Restrict the angle to the first quadrant final_angle_to_rotate = (pi / 2) - angles_mode final_angle_to_rotate = angles_mode configuration.log_debug_out( configuration.inspect.stack()[0][3], "Final angle_to_rotate: {0}".format(final_angle_to_rotate)) # cv2.imwrite(file + '_houghlines.jpg', img) # If the rotation angle falls within the min and max angles write the rotated file # if min_angle < final_angle_to_rotate < max_angle: # cv2.imwrite(file + '_original.png', cv2.imread(file).copy()) # img2 = cv2.imread(file + '_original.png', 0) # rotated = ndimage.rotate(img2, degrees(final_angle_to_rotate)) # cv2.imwrite(file + '_rotated.png', rotated) configuration.log_debug_out(configuration.inspect.stack()[0][3], final_angle_to_rotate) return final_angle_to_rotate
def process_cases(filename, outbox=configuration.get("outbox", "outbox1")): directory = "/".join(filename.split('/')[:-1]) configuration.log_debug_out(configuration.inspect.stack()[0][3], "Searching for cases in {0}".format(directory)) # Determine the case prefix and only grab case files that are for this guitar case_prefix = "--".join(filename.split('/')[-1].split('--')[:-1]) onlyfiles = [ x for x in [f for f in listdir(directory) if isfile(join(directory, f))] if "case" in x and "_new_image" not in x and case_prefix in x ] # Initialize variables case_data = {} total_case_height = 0 max_case_width = 0 paste_y = 0 guitar_model, guitar_serial, guitar_shot = filename.split('/')[-1].split( '--') file_type = guitar_shot.split('.')[-1] # Loop through all the files that we found earlier for case_file in onlyfiles: configuration.log_debug_out(configuration.inspect.stack()[0][3], "Found {0}".format(case_file)) # case_size = get_case_height(directory + case_file) # Get the case height case_size = get_case_height("{0}/{1}".format(directory, case_file)) # Add this to the total case height total_case_height += case_size[2].size[1] # Check for the largest photo width # May cause stretching of smaller images if they decide to shoot different file sizes for some reason if max_case_width < case_size[0]: max_case_width = case_size[0] # Add the cropped image to the case data dict case_data[case_file] = case_size[2] configuration.log_debug_out( configuration.inspect.stack()[0][3], "Total case image width = {0}, height = {1}".format( max_case_width, total_case_height)) # Image.fromarray(data, 'RGB') configuration.log_debug_out( configuration.inspect.stack()[0][3], "Creating image of size ({0}, {1})".format(max_case_width, total_case_height)) im_new = Image.new("RGBA", (max_case_width, total_case_height)) # Loop through the sorted case keys for key in sorted(case_data.keys()): # Paste the image at y configuration.log_debug_out(configuration.inspect.stack()[0][3], paste_y) im_new.paste(case_data[key], (0, paste_y)) configuration.log_debug_out(configuration.inspect.stack()[0][3], case_data[key]) configuration.log_debug_out(configuration.inspect.stack()[0][3], case_data[key].size) # Increment y by the y size of the photo paste_y += case_data[key].size[1] # Build the save path from the name, serial and shot type (In this case it is a case) save_path = "{0}/{1}--case.{2}".format(outbox, guitar_serial, file_type) configuration.log_debug_out( configuration.inspect.stack()[0][3], "Saving case composite to {0}".format(save_path)) # Save the image to the save path im_new.save(save_path)
return width, y, case.crop((0, y, width, height)) # Get the case height based on finding the first non green line - Uses mostly the same algorithm from the YCbCr green screen removal # This should theoretically get better pictures as it will always include the full case in the photo def get_case_height(case, green_offset=configuration.get("green_screen", "offset"), height_offset=10): # DEBUG - Just use the one-third return get_case_height2(case=case) # Open the image and load the pixel data img = Image.open(case) img = img.convert("RGBA") configuration.log_debug_out( configuration.inspect.stack()[0][3], "Case size: x = {0}, y = {1}".format(img.size[0], img.size[1])) pixdata = img.load() img_np = np.array(img) width = img.size[0] height = img.size[1] # Check for green values using the old imageengine (2015) code for speed for y in xrange(height): for x in xrange(width): # Get the RGBA values from the pixel r, g, b, a = pixdata[x, y] # Calculate the non green max and the green threshold non_green_max = max(r, b) green_threshold = (non_green_max + green_offset)