def crop_row(image_to_crop: Image, original_image: Image) -> (Image, Image): transposed_image_to_crop = image_to_crop.rotate(90, expand=True) transposed_original_image = original_image.rotate(90, expand=True) cropped_image, marked_original_image = crop_column( transposed_image_to_crop, transposed_original_image) return (cropped_image.rotate(3 * 90, expand=True), marked_original_image.rotate(3 * 90, expand=True))
def _check_rotation_exif(image: Image) -> Image: """ Checks the rotational exif data on a given image and rotates it accordingly. :param image: :return: Rotated image. :rtype: PIL.Image """ for orientation in ExifTags.TAGS.keys(): if ExifTags.TAGS[orientation] == 'Orientation': try: exif = dict(image._getexif().items()) val = exif[orientation] except (AttributeError, KeyError): return image if val == 3: image = image.rotate(180, expand=True) elif val == 6: image = image.rotate(270, expand=True) elif val == 8: image = image.rotate(90, expand=True) return image return image
def rotate_within_exif(img: Image): orientation = img.getexif().get(ORIENTATION_EXIF_TAG, ORIENTATION.NORMAL_HORIZONTAL) if orientation in [ ORIENTATION.NORMAL_180_ROTATED, ORIENTATION.MIRROR_VERTICAL ]: img = img.rotate(180, expand=True) elif orientation in [ ORIENTATION.NORMAL_270_ROTATED, ORIENTATION.MIRROR_HORIZONTAL_90_ROTATED ]: img = img.rotate(90, expand=True) elif orientation in [ ORIENTATION.NORMAL_90_ROTATED, ORIENTATION.MIRROR_HORIZONTAL_270_ROTATED ]: img = img.rotate(270, expand=True) if orientation in [ ORIENTATION.MIRROR_HORIZONTAL, ORIENTATION.MIRROR_VERTICAL, ORIENTATION.MIRROR_HORIZONTAL_270_ROTATED, ORIENTATION.MIRROR_HORIZONTAL_90_ROTATED, ]: img = img.transpose(Image.FLIP_LEFT_RIGHT) return img
def transform_rotate(img: Image, labels: Image, deg: Optional[float] = None): if deg is None: deg = np.random.rand() * 5. img = img.rotate(deg) labels = labels.rotate(deg) # TODO: smarter crop then margin = angle... img, labels = Loader.transform_crop(img, labels, margin=deg / 100) return img, labels
def rotate_image_to_direction(image: Image, direction: Direction) -> Image: if direction == Direction.RIGHT: return image elif direction == Direction.UP: return image.rotate(90) elif direction == Direction.LEFT: return image.transpose(Image.FLIP_LEFT_RIGHT) elif direction == Direction.DOWN: return image.rotate(90*3) raise ValueError("Invalid direction")
def exif_rotate(image: Image) -> Image: if hasattr(image, '_getexif') is False: return image exif_dict = dict(image._getexif().items()) orientation = exif_dict.get(name_to_tag_num['Orientation']) if orientation == 3: return image.rotate(180, expand=True) elif orientation == 6: return image.rotate(270, expand=True) elif orientation == 8: return image.rotate(90, expand=True) return image
def _assert_expected_chained(self, case): with open(case["source_path"], "rb") as f: img = Image(f) for operation in case["operation"]: if operation == "resize": img.resize(case["width"], case["height"]) elif operation == "rotate": img.rotate(case["degree"]) elif operation == "region": img.region(case["rect"].split(",")) rv = img.save() with open(case["expected_path"], "rb") as expected: msg = "{} does not match {}".format(case["source_path"], case["expected_path"]) self.assertEqual(rv.read(), expected.read(), msg)
def clip_and_align(img: Image) -> Image: try: # 识别关键点 landmarks = face_recognition.face_landmarks(np.array(img), model='small')[0] print(landmarks) l_eye = landmarks['left_eye'] r_eye = landmarks['right_eye'] l_mean = np.mean(l_eye, axis=0).astype(int) r_mean = np.mean(r_eye, axis=0).astype(int) dy = r_mean[1] - l_mean[1] dx = r_mean[0] - l_mean[0] # 计算旋转角度 angle = math.atan2(dy, dx) * 180. / math.pi # 旋转 img = img.rotate(angle, expand=True) # 再次识别 landmarks = face_recognition.face_landmarks(np.array(img), model='small')[0] # 剪裁, 以鼻子为中心 nose = landmarks['nose_tip'] center = np.mean(nose, axis=0).astype(int) center[0] = max(center[0], clip_size // 2) center[0] = min(center[0], img.size[0] - clip_size // 2) center[1] = max(center[1], clip_size // 2) center[1] = min(center[1], img.size[1] - clip_size // 2) assert clip_size % 2 == 0 left = center[0] - clip_size // 2 right = center[0] + clip_size // 2 down = center[1] + clip_size // 2 top = center[1] - clip_size // 2 img = img.crop((left, top, right, down)) assert img.size == (clip_size, clip_size) return img except: # 部分图片过于模糊,排除 return None
def preprocess_im(im: Image, height_offset: int = 100, rotation: int = 180, brightness_factor: float = None) -> Image: """ Method preprocessing an image Parameters ---------- im : Image Image to be preprocessed height_offset : int, optional `height_offset` will be cropped from the top of the image. This transformation is applied before `rotation`. By default, pikrellcam prints the date and time in its video. Thus, by default 100 rotation : int, optional Rotate the image by `rotation` degrees. On my rpi, the camera is upside down, thus, by default 180 brightness_factor : float, optional Factor by which to scale the brightness by. 2.5 is a good number for a brighter image. If None, leave the brightness unadjusted, by default None. Returns ------- Image Image preprocessed """ w, h = im.size im = im.crop((0, height_offset, w, h)) im = im.rotate(rotation) if brightness_factor is not None: enhancer = ImageEnhance.Brightness(im) im = enhancer.enhance(brightness_factor) return im
def insert_cropped_face(self, face_image: Image, empty_face_idx=0): if len(self.empty_faces) == 0 or empty_face_idx > len( self.empty_faces): raise "No faces or face index is out of bounds" if self.img is None: raise "Main splash image is not set" face_bounds = self.empty_faces[empty_face_idx] face_box = (face_bounds.left, face_bounds.top, face_bounds.left + face_bounds.width, face_bounds.top + face_bounds.height) logger.info( "Face Bounds: {0} Image Size: {1} Face Image Size: {2}".format( str(face_bounds), self.img.size, face_image.size)) cropped_face_image = Image.new("RGBA", self.img.size) #Would like to use thumbnail, but for some reason throws an error for images not matching in pillow when pasting below #face_image.thumbnail((face_bounds.width, face_bounds.height), Image.ANTIALIAS) face_image = face_image.resize((face_bounds.width, face_bounds.height), Image.ANTIALIAS) if face_bounds.angle > 0: logger.info("Angling") face_image = face_image.rotate(face_bounds.angle) logger.info("New face image size: {0}".format(face_image.size)) cropped_face_image.paste(face_image, face_box) self.empty_face_layers.append(cropped_face_image)
def rotate(im: Image) -> Image: """ Rotates an pillow.Image image :param im: the image :return: rotated pillow.Image object """ return im.rotate(random.randint(0, 360))
def drawLine(im: Image, canvas: Image, point: tuple, theta: int, scale=1.0): # im: assumed to be a line; width ignored # theta: int deg, within [-90, 90] # positive is counter-clockwise (to the right) im_rotated = im.rotate(theta, expand=True, resample=Image.BICUBIC) # im_enhanced = im_rotated.filter(ImageFilter.SMOOTH) im_scaled = im_rotated.resize( (round(im_rotated.size[0] * scale), round(im_rotated.size[1] * scale))) h = im.size[1] * scale x, y = point theta = mathutils.normalize_into_interval(theta, (-180, 180)) if 0 <= theta <= 90: top_left = point elif 90 < theta <= 180: top_left = (x, round(y - h * cos(theta))) elif -90 <= theta < 0: top_left = (round(x - h * sin(theta)), y) elif -180 <= theta < -90: top_left = (round(x - h * sin(theta)), round(y - h * cos(theta))) paste(im_scaled, canvas, top_left) # returns the endpoint of the line return (round(x + h * math.sin(math.radians(theta))), round(y + h * math.cos(math.radians(theta))))
def recover_rotate(self, image: Image, angle: int): """ Rotates the input image back to fit the original image, \ and fills in the parts that are missing due to rotation. Assumes that the angle of rotation is provided, and that the image \ has not been expanded when rotated (i.e. corners have been cut off). Also ssumes that no other modification has been made to the input. :param image: input image :type image: PIL.Image :param angle: the degree that the image was rotated (CCW) :type angle: int :return: the input image modified to match the original image :rtype: PIL.Image """ out = image.rotate(-angle) ''' for coord in product(range(self.original.size[1]), range(self.original.size[0])): if out.getpixel(coord) != 0: out.putpixel(coord, self.original.getpixel(coord)) ''' #mask = out.convert(mode="1",dither=None).convert('L') # insufficient masking mask = out.point(lambda x: 255*int(x>0)) mask = invert(mask).convert('1') out.paste(self.original,mask=mask) return out
def rotate_by_orient(img: Image) -> Image: """ Rotate image by exif orientation tag :param img: original image :return: rotated image """ orientation = 0x0112 exif = dict(img.getexif()) if orientation in exif: if exif[orientation] == 3: img = img.rotate(180, expand=True) elif exif[orientation] == 6: img = img.rotate(270, expand=True) elif exif[orientation] == 8: img = img.rotate(90, expand=True) return img
def rotate_image(im: Image) -> Image: try: orientation = -1 for orientation in ExifTags.TAGS.keys(): if ExifTags.TAGS[orientation] == 'Orientation': break exif = dict(im._getexif().items()) if orientation in exif and exif[orientation] == 3: im = im.rotate(180, expand=True) elif orientation in exif and exif[orientation] == 6: im = im.rotate(270, expand=True) elif orientation in exif and exif[orientation] == 8: im = im.rotate(90, expand=True) except Exception as ex: logging.debug(ex) return im
def exif_rotate(image: Image) -> Image: if not hasattr(image, "_getexif"): return image exif_data = image._getexif() if exif_data is None: return image exif_dict = dict(exif_data.items()) orientation = exif_dict.get(name_to_tag_num["Orientation"]) if orientation == 3: return image.rotate(180, expand=True) elif orientation == 6: return image.rotate(270, expand=True) elif orientation == 8: return image.rotate(90, expand=True) return image
def exif_rotate(image: Image) -> Image: if not hasattr(image, '_getexif'): return image exif_data = image._getexif() if exif_data is None: return image exif_dict = dict(exif_data.items()) orientation = exif_dict.get(name_to_tag_num['Orientation']) if orientation == 3: return image.rotate(180, expand=True) elif orientation == 6: return image.rotate(270, expand=True) elif orientation == 8: return image.rotate(90, expand=True) return image
def exif_rotate(image: Image) -> Image: if not hasattr(image, '_getexif'): return image exif_data = image._getexif() if exif_data is None: # nocoverage # don't have a test image for this case, but it happens return image exif_dict = dict(exif_data.items()) orientation = exif_dict.get(name_to_tag_num['Orientation']) if orientation == 3: return image.rotate(180, expand=True) elif orientation == 6: return image.rotate(270, expand=True) elif orientation == 8: return image.rotate(90, expand=True) return image
def __call__(self, im: Image) -> Image: """ Produces a randomly rotated image every time the instance is called. Args: im: The image to rotate. Returns: Randomly rotated image. """ return im.rotate(angle=random.sample(population=self.degrees, k=1)[0])
def random_Rotation(image): """ 对图像进行随机任意角度(0~360度)旋转 :param mode 邻近插值,双线性插值,双三次B样条插值(default) :param image PIL的图像image :return: 旋转转之后的图像 """ random_angle = np.random.randint(1, 360) image = Image.rotate(random_angle) return image
def rotate(image: Image, angle: int): """ :param image: input image :type image: PIL.Image :param angle: the degrees by which to rotate the input image (CCW) :type angle: int :return: the modified image :rtype: PIL.Image """ return image.rotate(angle)
def rotate_image(image: Image) -> Image: ALLOCATION={3: 180, 6: -90, 8: 90} #{orientation value : rotation angle} exif=image._getexif() # print(f"exif={exif}") if exif != None and 274 in exif: if exif[274] in ALLOCATION: return image.rotate(ALLOCATION[exif[274]], expand=True) else: return image else: return image
def rotate_upright(self, image: Image): """ Rotate a PIL image to upright depending on its current orientation according to EXIF data. """ try: for orientation in ExifTags.TAGS.keys(): if ExifTags.TAGS[orientation] == "Orientation": break exif = dict(image._getexif().items()) orientation = exif[orientation] if orientation == 3: image = image.rotate(180, expand=True) elif orientation == 6: image = image.rotate(270, expand=True) elif orientation == 8: image = image.rotate(90, expand=True) except (AttributeError, KeyError) as e: pass return image
def simple_geometry_transform(self, image: Image, size: Tuple(int, int), angle: int) -> Tuple[object, bool]: ''' resize and rotate something ''' status = True try: image = image.resize(size) image = image.rotate(angle) # degrees counter-clockwise except: status = False return (image, status)
def _renderCrewmate(image_path: str, crewmate: Image, index: int, total: int): fly_over_speed = 1.8 # 2 is half of the screen width degree = index * 360 / total * -1 image = Image.open(image_path) c_w, c_h = crewmate.size crewmate_rotated = crewmate.rotate(degree, expand=True) sky_w, sky_h = image.size x_offset = -1 * c_w + index * sky_w // total * fly_over_speed offset = (int(x_offset), (sky_h - c_h) // 2) image.paste(crewmate_rotated, offset) return image
def apply_transformations(image: Image, params: Params): image_width, image_height = image.size # If crop dimensions are set to 0 or exceed image dimensions set crop dimensions to image dimensions. if image_width < params.crop_width or params.crop_width == 0: params.crop_width = image_width if image_height < params.crop_height or params.crop_height == 0: params.crop_height = image_height # If size parameter is not given set size of image to the size of input image. if params.size is None: params.size["width"] = image_width params.size["height"] = image_height # Coordinates of upper left corner of crop window are random values such that image contains window. crop_x: int = random.randint(0, image_width - params.crop_width) crop_y: int = random.randint(0, image_height - params.crop_height) image = image.crop((crop_x, crop_y, crop_x + params.crop_width, crop_y + params.crop_height)) # Rotation degree is random value between min_rotation and max_rotation parameters. degrees: float = random.uniform(params.min_rotation, params.max_rotation) image = image.rotate(degrees) # Flip parameters are equal to probability of applying flip. if random.random() < params.flip_horizontal: image = image.transpose(Image.FLIP_LEFT_RIGHT) if random.random() < params.flip_vertical: image = image.transpose(Image.FLIP_TOP_BOTTOM) # Apply all filters. Default filter parameters result in not changing input image. image = image.convert("RGB") if params.edges: image = image.filter(ImageFilter.FIND_EDGES) enhancer = ImageEnhance.Brightness(image) image = enhancer.enhance(params.brightness) enhancer = ImageEnhance.Contrast(image) image = enhancer.enhance(params.contrast) enhancer = ImageEnhance.Sharpness(image) image = enhancer.enhance(params.sharpness) enhancer = ImageEnhance.Color(image) image = enhancer.enhance(params.color) # Return resized image to match requested output dimensions. return image.resize(tuple(params.size))
def auto_rotate(self, img: Image) -> Image: exif = img.getexif() if hasattr(img, "getexif") else None if not exif: return img orientation_key = 274 # cf ExifTags if orientation_key in exif: orientation = exif[orientation_key] rotate_values = {3: 180, 6: 270, 8: 90} if orientation in rotate_values: return img.rotate(rotate_values[orientation], expand=True) return img
def _rotate_exif_orientation(self, img: Image) -> Image: """Rotate the image according to metadata in the payload. Some cameras do not rotate the image, they just add orientation metadata to the file, so we rotate it here. """ if not hasattr(img, '_getexif'): return img # PIL.PngImagePlugin.PngImageFile apparently lacks EXIF tags = img._getexif() if tags is None: return img orientation = tags.get(self.EXIF_TAGS['Orientation']) if orientation is None: return img degrees = self.EXIF_ROTATION_FIX.get(orientation) return img.rotate(degrees) if degrees else img
def unetnested_multi_scale_predict(self, image_ori: Image): self.unetNested_model.eval() # 预测原图 sample_ori = image_ori.copy() output_ori = self.unetnested_predict(sample_ori) # 预测旋转三个 angle_list = [90, 180, 270] for angle in angle_list: img_rotate = image_ori.rotate(angle, Image.BILINEAR) output = self.unetnested_predict(img_rotate) pred = output.data.cpu().numpy()[0] pred = pred.transpose((1, 2, 0)) m_rotate = cv2.getRotationMatrix2D((200, 200), 360.0 - angle, 1) pred = cv2.warpAffine(pred, m_rotate, (400, 400)) pred = pred.transpose((2, 0, 1)) output = torch.from_numpy(np.array([ pred, ])).float() output_ori = torch.cat([output_ori, output.cuda()], 1) # 预测竖直翻转 img_flip = image_ori.transpose(Image.FLIP_TOP_BOTTOM) output = self.unetnested_predict(img_flip) pred = output.data.cpu().numpy()[0] pred = pred.transpose((1, 2, 0)) pred = cv2.flip(pred, 0) pred = pred.transpose((2, 0, 1)) output = torch.from_numpy(np.array([ pred, ])).float() output_ori = torch.cat([output_ori, output.cuda()], 1) # 预测水平翻转 img_flip = image_ori.transpose(Image.FLIP_LEFT_RIGHT) output = self.unetnested_predict(img_flip) pred = output.data.cpu().numpy()[0] pred = pred.transpose((1, 2, 0)) pred = cv2.flip(pred, 1) pred = pred.transpose((2, 0, 1)) output = torch.from_numpy(np.array([ pred, ])).float() output_ori = torch.cat([output_ori, output.cuda()], 1) return output_ori
def rotate(): # retrieve parameters from html form angle = request.form['angle'] filename = request.form['image'] # open and process image target = os.path.join(APP_ROOT, 'static/images') destination = "/".join([target, filename]) img = Image.open(destination) img = img.rotate(-1 * int(angle)) # save and return image destination = "/".join([target, 'temp.png']) if os.path.isfile(destination): os.remove(destination) img.save(destination) return send_image('temp.png')
def make_feels_img(self, template: Image, colour: str, avatar: Image) -> BytesIO: # print(template.info) template = template.convert("RGBA") # avatar = Image.open(self.files + "temp." + ext) # transparency = template.split()[-1].getdata() data = np.array(template) red, green, blue, alpha = data.T blue_areas = (red == 0) & (blue == 255) & (green == 0) & (alpha == 255) data[..., :-1][blue_areas.T] = colour temp2 = Image.fromarray(data) temp2 = temp2.convert("RGBA") avatar = avatar.convert("RGBA") avatar = avatar.rotate(-30, expand=True) avatar = avatar.resize((60, 60), Image.ANTIALIAS) temp2.paste(avatar, (40, 25), avatar) temp = BytesIO() temp2.save(temp, format="PNG") temp.name = "feels.png" return temp
def write_image_with_rotations( image: Image, name: str, output_dir: Path, # raw_rotation: Union[None, int, list] = None, ) -> None: """ Write image to disk along with the rotations """ context_color = OVERMAP_TERRAIN_DATA.get(name) if context_color: pixels = image.load() height, width = image.size for col in range(height): for row in range(width): if pixels[col, row] in SCHEME['replace_with_context']: pixels[col, row] = context_color image.save(output_dir / f'{name}.png') for rotation_suffix in ROTATIONS: image = image.rotate(-90) image.save(output_dir / f'{name}{rotation_suffix}.png')
def ShowAprilTag(self, id): try: filename = config.aprilTagRawName + str(id).zfill(5) + ".png" path = projectDir + "../" + config.aprilTagPath + filename rospy.loginfo("Showing TagID: " + str(id) + " with filename: " + filename) image = Image.open(path) if config.upsideDown: image = Image.rotate(180) self._display.ShowImage(image) self._currentID = id self.DumpSave() return True except ValueError: print("Could not convert data to the needed ID") except: print("Exception during ID-Change") return False
def main(): import sys import tornado.httpclient import tornado.options from tornado.options import define, options, parse_command_line define("operation", help="the operation to be performed", type=str, default="resize", metavar="|".join(["resize", "rotate", "none"])) define("width", help="the desired image width", type=int) define("height", help="the desired image height", type=int) define("mode", help="the resizing mode", metavar="|".join(Image.MODES), type=str) define("background", help="the hexidecimal fill background color", type=str) define("position", help="the crop position", metavar="|".join(Image.POSITIONS), type=str) define("filter", help="default filter to use when resizing", metavar="|".join(Image.FILTERS), type=str) define("degree", help="the desired rotation degree", type=int) define("expand", help="expand image size to accomodate rotation", type=int) define("rect", help="rectangle: x,y,w,h", type=str) define("format", help="default format to use when saving", metavar="|".join(Image.FORMATS), type=str) define("quality", help="default jpeg quality, 0-100", type=int) args = parse_command_line() if not args: print("Missing image source url") sys.exit() elif options.operation == "region": if not options.rect: tornado.options.print_help() sys.exit() elif options.operation == "resize": if not options.width and not options.height: tornado.options.print_help() sys.exit() elif options.operation == "rotate": if not options.degree: tornado.options.print_help() sys.exit() elif options.operation != "noop": tornado.options.print_help() sys.exit() if args[0].startswith("http://") or args[0].startswith("https://"): client = tornado.httpclient.HTTPClient() resp = client.fetch(args[0]) image = Image(resp.buffer) else: image = Image(open(args[0], "r")) if options.operation == "resize": image.resize(options.width, options.height, mode=options.mode, filter=options.filter, background=options.background, position=options.position) elif options.operation == "rotate": image.rotate(options.degree, expand=options.expand) elif options.operation == "region": image.region(options.rect.split(",")) stream = image.save(format=options.format, quality=options.quality) sys.stdout.write(stream.read()) stream.close()