def make_circular(img: Image):
    """
    Makes the given image circular

    :param img: Image opened with PIL.Image
    """

    width, height = img.size
    result = Image.new(size=img.size, color=(0, 0, 0, 0), mode='RGBA')

    for y in range(height):
        # Get new width at this height
        relative_y = (y / height - 0.5) * 2  # Convert to value between -1 and +1
        angle = math.asin(relative_y)
        relative_x = math.cos(angle)
        new_width = int(math.ceil(relative_x * width))

        # Cut a strip at this height
        left, right = 0, width
        upper, lower = y, y + 1
        box = (left, upper, right, lower)
        img_strip = img.crop(box)

        # Resize the strip
        img_resized = img_strip.resize(size=(new_width, 1))

        # Paste the resized strip in place
        left = int(round(0.5 * (width - new_width)))
        upper = y
        box = (left, upper)
        result.paste(img_resized, box)

    return result
Example #2
0
def identify_board(img: Image = None) -> Board:
    """OCR the (new) board represented in img.

    If img is None, a screenshot of the primary monitor - or, when
    available, the game window - is taken.

    img must represent a new game with the window in pixel-perfect scaling
    mode and contain only the contents of the game window
    """
    if img is None:
        img = pyautogui.screenshot()
    # Find out how many times the game has been scaled up; note that the
    # fullscreen window gets a surrounding black border and so the game will
    # be scaled as many times as it can fit and then centred
    scale = min(img.width // GAME_RESOLUTION[0],
                img.height // GAME_RESOLUTION[1])
    new_width, new_height = GAME_RESOLUTION[0] * scale, GAME_RESOLUTION[
        1] * scale

    # Get the bounds of the image centre
    left = (img.width - new_width) / 2
    top = (img.height - new_height) / 2
    right = (img.width + new_width) / 2
    bottom = (img.height + new_height) / 2

    # crop then resize the image
    img = img.crop((left, top, right, bottom))
    img = img.resize(GAME_RESOLUTION).convert("1")
    return cast(
        Board,
        tuple((
            [([
                card for card, card_img in CARDS.items()
                if not ImageChops.difference(
                    card_img,
                    img.crop((
                        LEFT + COL_WIDTH * x,
                        TOP + ROW_HEIGHT * y,
                        LEFT + COL_WIDTH * x + CARD_WIDTH,
                        TOP + ROW_HEIGHT * y + CARD_HEIGHT,
                    )),
                ).getbbox()
            ] + ["?"])[0] for y in range(6)],
            False,
        ) for x in range(6)),
    )
Example #3
0
def cut_pil_image_v_old(image: Image, border=20, spread=.05):
    w, h = image.size
    iw, ih = w - 2 * border, h - 2 * border
    dw, dh = int(iw * spread), int(ih * spread)
    return image.crop(
        (randint(border // 2, border + dw), randint(border // 2, border + dh),
         randint(w - border - dw,
                 w - border // 2), randint(h - border - dh, h - border // 2)))
Example #4
0
def generate_thumb(im: Image) -> Image:
    x, y = im.size
    while y > x:
        slice_height = min(y - x, 10)
        bottom = im.crop((0, y - slice_height, x, y))
        top = im.crop((0, 0, x, slice_height))

        if _image_entropy(bottom) < _image_entropy(top):
            im = im.crop((0, 0, x, y - slice_height))
        else:
            im = im.crop((0, slice_height, x, y))

        x, y = im.size
        gevent.sleep(0)

    im.thumbnail((70, 70), Image.ANTIALIAS)
    return im
Example #5
0
def crop_center_image(img: PIL.Image, size: int) -> PIL.Image:
    """ crop center PIL-image """
    w, h = img.size
    if size == w and size == h:
        return img
    else:
        return img.crop(((w - size) // 2, (h - size) // 2, (w + size) // 2,
                         (h + size) // 2))
Example #6
0
def cropimg(img: Image, bbox: Box, camera_intrinsic: np.ndarray) -> Image:
    bbox_img = view_points(bbox.corners(), view=camera_intrinsic, normalize=True)
    # in case the annotation runs off the edge of the page
    bbox_img[bbox_img < 0] = 0
    bbox_img[0, bbox_img[0, :] > img.size[0]] = img.size[0]-1
    bbox_img[1, bbox_img[1, :] > img.size[1]] = img.size[1]-1
    # crop
    return img.crop((min(bbox_img[0]), min(bbox_img[1]), max(bbox_img[0]), max(bbox_img[1])))
Example #7
0
def central_crop(img: Image) -> Image:
    w, h = img.size
    size = min(w, h)
    offset_h = int((h - size) / 2)
    offset_w = int((w - size) / 2)

    cropped = img.crop((offset_w, offset_h, offset_w + size, offset_h + size))

    return cropped
Example #8
0
 def make_thumbnail(self, image: Image,
                    ThumbnailSize=((100, 100))) -> Image:
     try:
         # Crop the image into a square
         if image.size[0] > image.size[1]:
             trim = (image.size[0] - image.size[1]) / 2
             image = image.crop(
                 (trim, 0, image.size[0] - trim, image.size[1]))
         if image.size[1] > image.size[0]:
             trim = (image.size[0] - image.size[1]) / 2
             image = image.crop(
                 (0, trim, image.size[1], image.size[0] - trim))
         image.thumbnail(ThumbnailSize)
         return image
     except Exception as e:
         logging.error("Exception in Thumbnailer::make_thumbnail: %s" %
                       str(e))
         raise e
Example #9
0
 def rolling_an_image(self, image: Image, delta: int) -> Tuple[object, bool]:
     '''
     rolll an image sideways
     '''
     status = False
     try:
         xsize, ysize = image.size
         delta = delta % xsize
         if delta == 0:
             return (image, status)
         part1 = image.crop((0, 0, delta, ysize))
         part2 = image.crop((delta, 0, xsize, ysize))
         image.paste(part2, (0, 0, xsize-delta, ysize))
         image.paste(part1, (xsize-delta, 0, xsize, ysize))
         status = True
     except:
         status = False
     return (image, status)
 def _crop_img(img: Image, person_range):
     """
     検出した人物の範囲(座標)に従ってトリミング
     :param Image img:
     :param tuple person_range:
     :return:
     """
     # print(person_range)
     return img.crop(person_range)
Example #11
0
    def crop(image: Image, width: int, height: int, space: int) -> list:
        croppedImages = []
        imgWidth, imageHeight = image.size
        for row in range(0, imageHeight, height + space):
            for column in range(0, imgWidth, width + space):
                crop = image.crop((column, row, column + width, row + height))
                croppedImages.append(crop)

        return croppedImages
Example #12
0
 def extracts(cls, image: Image, return_bounding_boxes = False):
     faces_bounding_boxes, confidents = cls.model.detect(image)
     if faces_bounding_boxes is None or len(faces_bounding_boxes) == 0:
         return False
     faces = []
     for face_bounding_box, confident in zip(faces_bounding_boxes, confidents):
         face = image.crop(face_bounding_box)
         faces.append(face)
     return faces if not return_bounding_boxes else faces, faces_bounding_boxes
Example #13
0
 def crop(image: Image, norm_pos, crop_size: int):
     if image is None:
         return None
     w, h = image.size
     pos = scale_to_image_coordinate(norm_pos, w, h, flip_y=False)
     rect = roi_rect(width=w, height=h, center_x=pos[0], center_y=pos[1], size=crop_size)
     if rect is None:
         return None
     return image.crop(rect)
Example #14
0
    def ocr(
            x_start: int,
            y_start: int,
            x_end: int,
            y_end: int,
            debug: bool = False,
            bmp: Image = None,
            cropb: bool = False,
            ocr_filter: bool = True,
            binf: int = 0,
            sliced: bool = False
    ) -> str:
        """Perform an OCR of the supplied area, returns a string of the result.
        
        Keyword arguments
        debug  -- Saves an image of what is sent to the OCR (default False)
        bmp    -- A bitmap from the get_bitmap() function, use this if you're
                  performing multiple different OCR-readings in succession from
                  the same page. This is to avoid to needlessly get the same
                  bitmap multiple times. If a bitmap is not passed, the function
                  will get the bitmap itself. (default None)
        cropb  -- Whether the bmp provided should be cropped.
        filter -- Whether to filter the image for better OCR.
        binf   -- Threshold value for binarizing filter. Zero means no filtering.
        sliced -- Whether the image has ben sliced so there's very little blank
                  space. Gets better readings from small values for some reason.
        """
        x_start += Window.x
        x_end += Window.x
        y_start += Window.y
        y_end += Window.y

        if bmp is None:
            bmp = Inputs.get_cropped_bitmap(x_start, y_start, x_end, y_end)

        elif cropb:
            # Bitmaps are created with a 8px border
            bmp = bmp.crop((x_start + 8, y_start + 8, x_end + 8, y_end + 8))

        if binf > 0:  # Binarizing Filter
            fn = lambda x: 255 if x > binf else 0
            bmp = bmp.convert('L')  # To Monochrome
            bmp = bmp.point(fn, mode='1')
            if debug: bmp.save("debug_ocr_whiten.png")

        if ocr_filter:  # Resizing and sharpening
            *_, right, lower = bmp.getbbox()
            bmp = bmp.resize((right * 4, lower * 4), Image.BICUBIC)  # Resize image
            bmp = bmp.filter(ImageFilter.SHARPEN)
            if debug: bmp.save("debug_ocr_filter.png")

        if sliced:
            s = pytesseract.image_to_string(bmp, config='--psm 6')
        else:
            s = pytesseract.image_to_string(bmp, config='--psm 4')

        return s
Example #15
0
def crop_and_send(frame,
                  det,
                  destination="home/rossis/TEST_CROPS/",
                  name="test.jpg"):
    det = xywh2xyxy(det)
    for el in det:
        el = el - 40
    crop = Image.crop((det[0], det[1], det[2], det[3]))
    crop.save(destination + name)
Example #16
0
def resize_image(im: Image, fg: Image, resize_mode: str,
                 offset: dict) -> Image:
    """Resizes the image with the method specified in resize_mode

    Args:
        im (Image): image to resize
        fg (Image): images wich dimensions will be used to resize the former image
        resize_mode (str): how to resize the image
        offset (dict): offset used to crop the image

    Returns:
        Image: newly resized image
    """
    orig_w, orig_h = im.size  # size of the bg image
    temp_w, temp_h = fg.size  # size of the template image

    if resize_mode == "crop":  # crops the image from the center + the offset
        im = im.crop(box=((orig_w - temp_w) / 2 + offset['x'],
                          (orig_h - temp_h) / 2 + offset['y'],
                          (orig_w + temp_w) / 2 + offset['x'],
                          (orig_h + temp_h) / 2 + offset['y']))
    elif resize_mode == "scale":  # scales the image so that it fits (ignores proportions)
        im = im.resize(fg.size)
    elif resize_mode == "scale&crop":
        # Make the image as big as the template proportionally
        for i in range(0, 2):
            ratio = temp_w / im.size[i]
            if ratio > 1:
                im = im.resize((int(orig_w * ratio), int(orig_h * ratio)))
        orig_w, orig_h = im.size  # update the bg image size
        im = im.crop(box=((orig_w - temp_w) / 2 + offset['x'],
                          (orig_h - temp_h) / 2 + offset['y'],
                          (orig_w + temp_w) / 2 + offset['x'],
                          (orig_h + temp_h) / 2 + offset['y']))
    elif resize_mode == "random":  # crops the image from the center + the random offset
        x_offset = random.randint(-abs(orig_w - temp_w) // 2,
                                  abs(orig_w - temp_w) // 2)
        y_offset = random.randint(-abs(orig_h - temp_h) // 2,
                                  abs(orig_h - temp_h) // 2)
        im = im.crop(box=((orig_w - temp_w) / 2 + x_offset,
                          (orig_h - temp_h) / 2 + y_offset,
                          (orig_w + temp_w) / 2 + x_offset,
                          (orig_h + temp_h) / 2 + y_offset))
    return im
Example #17
0
 def crop_rect(self, image: Image, box_position: Tuple[int, int, int, int]) -> Tuple[object, bool]:
     '''
     crop
     '''
     status = True
     try:
         image = image.crop(box_position)
     except:
         status = False
     return (image, status)
Example #18
0
def scale(img: PIL.Image, size=200):
    """ Приводит img к размеру (size,size) """

    center = (img.size[0] // 2, img.size[1] // 2)
    d = min(center)

    res = img.crop(
        (center[0] - d, center[1] - d, center[0] + d, center[1] + d))

    return [res.resize((size, size))]
def GLCD_to_SSD1306(image: Image) -> Image:
    output = bytearray()

    for bn in range(8): #block number
        block: Image = image.crop((0, bn*8, 128, bn*8+8))
        rblock: Image = block.rotate(-90, expand=True)
        output += rblock.tobytes()

    reassembled: Image = Image.frombytes('1', (64, 128), bytes(output))
    return reassembled
Example #20
0
def rating_type(image: Image, scores: typing.List[Score]) -> str:

    for score in scores:
        width_height = width_and_height(score.position_start,
                                        score.position_end)
        im_crop = image.crop((score.position_start.x, score.position_start.y,
                              score.position_start.x + width_height[0],
                              score.position_start.y + width_height[1]))

    return ""
Example #21
0
 def extract(cls, image: Image):
     faces_bounding_boxes, confidents = cls.model.detect(image)
     if len(faces_bounding_boxes) == 0:
         return False
     if len(faces_bounding_boxes) == 1:
         largest_face_bounding_box = faces_bounding_boxes[0]
     else:
         faces_areas = [GeometryUtils.calc_box_area(face_bounding_box) for face_bounding_box in faces_bounding_boxes]
         largest_face_index = numpy.argmax(faces_areas)
         largest_face_bounding_box = faces_bounding_boxes[largest_face_index]
     return image.crop(largest_face_bounding_box)
def replace_from_frame(image: Image, detection: dict):
    cx = detection.get(CROP_X)
    cy = detection.get(CROP_Y)
    w, h = detection.get(CROP_SIZE)
    hit_img = image.crop((cx, cy, cx + w, cy + h))
    detection[ORIG_IMAGE] = detection[IMAGE]
    detection[IMAGE] = hit_img
    with BytesIO() as output:
        hit_img.save(output, format="png")
        # hit_img.save('/tmp/%d.png' % detection.get('id'))
        detection[FRAME_DECODED] = output.getvalue()
Example #23
0
def predict_img(img: Image):
    img = img.crop((0, 0, 256, 256))
    img = img.convert("L")
    img = img.resize((64, 64), Image.ANTIALIAS)
    data = np.asarray(img)
    data = np.reshape(data, (64, 64, 1))
    data = data / 255.0
    data = np.array([data])

    res = model.predict(data)
    return list_all[np.argmax(res)]
Example #24
0
    def _resize_input(self, img: Image) -> Image:
        border = tuple(
            np.floor_divide(np.subtract(self._target_icon_size, img.size), 2))

        if all(size > 0 for size in border):
            resized_icon = ImageOps.expand(img, border=border, fill="black")
        else:
            resized_icon = img.crop((-border[0], -border[1],
                                     -border[0] + self._target_icon_size[0],
                                     -border[1] + self._target_icon_size[1]))
        return resized_icon
Example #25
0
def crop_image(image: Image):
    center_x = int(image.width / 2)
    center_y = int(image.height / 2)

    screen_width = screen_size[0]
    screen_height = screen_size[1]

    left_upper = (center_x - int(screen_width / 2), center_y - int(screen_height / 2))
    right_lower = (center_x + int(screen_width / 2), center_y + int(screen_height / 2))

    return image.crop(left_upper + right_lower)
Example #26
0
    def cut(self, box):
        """
        cut out a box of the image and return it

        args:
            box (4-tuple of int): (left, top, right, bottom) (see PIL documentation)

        returns:
            a new cut image
        """

        # copy image
        # deepcopy does not work somehow, so create a new image exactly like
        # this one
        cutimage = Image(self)

        # crop image
        cutimage.crop(box)

        return cutimage
Example #27
0
def crop(image: Image, face) -> (Image, 'face'):
    ratio = 0.20 / 0.85  # delta_size / face_size
    width, height = image.size
    face_height = face.height()
    face_width = face.width()
    delta_height = ratio * face_height
    delta_width = ratio * width

    img_left = int(max(0, face.left() - delta_width))
    img_top = int(max(0, face.top() - delta_height))
    img_right = int(min(width, face.right() + delta_width))
    img_bottom = int(min(height, face.bottom() + delta_height))
    image = image.crop((img_left, img_top, img_right, img_bottom))
    face = dlib.rectangle(face.left() - img_left,
                          face.top() - img_top,
                          face.right() - img_left,
                          face.bottom() - img_top)
    center = face.center()
    width, height = image.size
    if width > height:
        left = int(center.x - height / 2)
        right = int(center.x + height / 2)
        if left < 0:
            left, right = 0, height
        elif right > width:
            left, right = width - height, width
        image = image.crop((left, 0, right, height))
        face = dlib.rectangle(face.left() - left, face.top(),
                              face.right() - left, face.bottom())
    elif width < height:
        top = int(center.y - width / 2)
        bottom = int(center.y + width / 2)
        if top < 0:
            top, bottom = 0, width
        elif bottom > height:
            top, bottom = height - width, height
        image = image.crop((0, top, width, bottom))
        face = dlib.rectangle(face.left(),
                              face.top() - top, face.right(),
                              face.bottom() - top)
    return image, face
Example #28
0
def generate(master: Image, master_size: int, small_size: int) -> Image:

    dir_src = Config.get_default_dir()

    images_sources = FileCheck.get_dir_content(dir_src)

    images = LoadImages.load_images_with_resize(dir_src, images_sources,
                                                small_size, small_size)

    master_w, master_h = master.size

    if master_w > master_h:
        master_w = master_h
    elif master_h > master_w:
        master_h = master_w

    master_h -= master_h % master_size
    master_w = master_h

    master.resize((master_w, master_h))

    part_size = master_w // master_size

    master_parts = {}

    for i in range(master_size):
        if i not in master_parts:
            master_parts[i] = {}
        for j in range(master_size):
            master_parts[i][j] = np.array(
                master.crop((part_size * i, part_size * j, part_size * (i + 1),
                             part_size * (j + 1))).getdata())

    images_reduce = {}

    for small_image in Model.resize_all(images.copy(), part_size, part_size):
        images_reduce[len(images_reduce)] = np.array(small_image.getdata())

    links = {}

    for i, line in master_parts.items():
        for j, sub_image in line.items():
            best_value = 195075 * part_size * part_size + 1
            best_id = None
            for k, small_image in images_reduce.items():
                value = ((sub_image - small_image)**2).sum()
                if value < best_value:
                    best_value = value
                    best_id = k
            links[i * master_size + j] = best_id

    Model.make_final(links, images, master_size,
                     small_size).rotate(-90).save(Config.get_save_path())
Example #29
0
def Binarized(Image, Threshold):

    ImgNew = Image.crop()
    Pixels = ImgNew.load()
    (Width, Height) = ImgNew.size
    for i in xrange(Width):
        for j in xrange(Height):
            if Pixels[i, j] > Threshold:  # 大于阈值的置为白色,否则黑色
                Pixels[i, j] = 255  # 白色
            else:
                Pixels[i, j] = 0  # 黑色
    return ImgNew
Example #30
0
    def get_image_resized(self, image: Image) -> Image:
        """
        Getting image resized

        :param image:
        :return:
        """

        cropped_image = image.crop(
            (self.x_axis, self.y_axis, self.width + self.x_axis,
             self.height + self.y_axis))
        return cropped_image.resize((256, 256), Image.ANTIALIAS)
def center_crop(img: Image):
    """ Crop image in center.
    """
    width, height = img.size
    if width > height:
        # 横長
        box = ((width - height) / 2, 0, (width + height) / 2, height)
    else:
        # 縦長
        box = (0, (height - width) / 2, width, (height + width) / 2)
    cropped_img = img.crop(box)
    return cropped_img
Example #32
0
def crop_image(image: Image, x1: int, y1: int, x2: int, y2: int) -> Image:
    """Crop an image.

    The arguments `x1`, `y1`, `x2`, `y2` are the coordinates of the cropped region
    in percent.
    """
    width, height = image.size
    x1_abs = x1 * width / 100
    x2_abs = x2 * width / 100
    y1_abs = y1 * height / 100
    y2_abs = y2 * height / 100
    return image.crop((x1_abs, y1_abs, x2_abs, y2_abs))
Example #33
0
def crop_face(image: Image,
              face_keypoints: Optional,
              hyp_ratio: float = 1 / 3) -> Image:
    """Crop input image to just the face"""
    if face_keypoints is None:
        print("No keypoints detected on image")
        return image

    left, upper, right, lower = get_crop_points(image, face_keypoints,
                                                hyp_ratio)

    return image.crop((left, upper, right, lower))
Example #34
0
def cut_pic(Image,dst_w,dst_h):
    # dst_w = 800,dst_h = 600
    try:
        ori_w, ori_h = Image.size
        if(ori_h>ori_w):
            y = (ori_h-dst_h)/2
            box = (0, int(y), dst_w, dst_h+y)
        newImg = Image.crop(box)
        try:
            return newImg
        except IOError:
            return None
    except IOError:None
Example #35
0
 def center_crop(cls, img: Image):
     """ Crop image in center.
     """
     width, height = img.size
     if width > height:
         # 横長
         box = (int((width - height) / 2), 0,
                int((width + height) / 2), height)
     else:
         # 縦長
         box = (0, int((height - width) / 2),
                width, int((height + width) / 2))
     cropped_img = img.crop(box)
     return cropped_img
def crop_image(img: Image, xy: (float, float), scale_factor: float) -> Image:
    """Crop the image around the tuple xy
    
    Inputs:
    -------
    img: Image opened with PIL.Image
    xy: tuple with relative (x,y) position of the center of the cropped image
        x and y shall be between 0 and 1
    scale_factor: the ratio between the original image's size and the cropped image's size
    """

    center = (img.size[0] * xy[0], img.size[1] * xy[1])
    new_size = (img.size[0] / scale_factor, img.size[1] / scale_factor)
    left = max(0, int(center[0] - new_size[0] / 2))
    right = min(img.size[0], int(center[0] + new_size[0] / 2))
    upper = max(0, int(center[1] - new_size[1] / 2))
    lower = min(img.size[1], int(center[1] + new_size[1] / 2))
    cropped_img = img.crop((left, upper, right, lower))
    return cropped_img
Example #37
0
def process(input: Image, output: Image, pixel: int, scale: int):
    """
    Do the needful.
    """
    size = pixel * scale
    x = y = 0
    source_x, source_y = input.size

    draw = ImageDraw.Draw(output)

    while True:
        # color = input.getpixel((x * pixel, y * pixel)
        art_pixel = input.crop((x * pixel, y * pixel, (x + 1) * pixel, (y + 1) * pixel))
        colors = list(art_pixel.getdata())
        total_pixels = len(colors)

        r = g = b = a = 0
        for color in colors:
            r += color[0]
            g += color[1]
            b += color[2]
            a += color[3]

        r //= total_pixels
        g //= total_pixels
        b //= total_pixels
        a //= total_pixels

        drawpixel(draw, x, y, size, (r, g, b, a))

        x += 1

        if x * pixel >= source_x:
            x = 0
            y += 1

            if y * pixel >= source_y:
                break
Example #38
0
    def _extract_years(self, image: Image, x_ticks: list, bottom_line_y: int) -> list:
        years = []
        for tick in x_ticks:
            # this 15s is bugprone estimations
            # todo  fairly find gaps bw words

            box = (tick - 15, bottom_line_y + 3, tick + 20, image.size[1])
            region = image.crop(box)

            text = region.crop(ImageOps.invert(region.convert('RGB')).getbbox())
            # debug
            # region.save(str(tick)+'.bmp')
            word = ''
            rightmost_unread_pixel = text.size[0]
            while rightmost_unread_pixel > 0:
                x_left = rightmost_unread_pixel - self.tesser.max_width
                if x_left < 0:
                    x_left = 0
                x_right = rightmost_unread_pixel
                glyph = Image.new('RGBA', (x_right - x_left, 8), (255, 255, 255))
                glyph.paste(text.crop((x_left, 0, x_right, 8)))
                letter, width = self.tesser.tess(glyph, left=False)
                word = letter + word
                rightmost_unread_pixel -= width
            years.append((self._word_to_year(word), tick))

        years = sorted(years)
        # add first and last years
        min_year_0 = years[0]
        min_year_1 = years[1]
        first_year = (min_year_0[0] - 1, min_year_0[1] - (min_year_1[1] - min_year_0[1]))

        max_year_n1 = years[-2]
        max_year_n = years[-1]
        last_year = (max_year_n[0] + 1, max_year_n[1] + (max_year_n[1] - max_year_n1[1]))

        return [first_year] + years + [last_year]
Example #39
0
def cut_box(lft,up,rght,lwr, Image):
	Image.load()
	box = (lft, up, rght ,lwr)
	i = Image.crop(box)
	return i
Example #40
0
    def find_slots(cls, loot_image: Image) -> List[Dict[str, Any]]:
        """Scans through an image, looking for inventory slots

        :param loot_image: An inventory screenshot
        :return: A list of dictionaries, containing the images and coordinates for every slot.
        """
        image_copy = loot_image.copy()
        loot_bytes = loot_image.tobytes()
        slot_list = []
        if loot_image.size[0] < 34 or loot_image.size[1] < 27:
            return slot_list

        x = -1
        y = 0
        skip = False
        for _ in loot_bytes:
            x += 1
            if x + 34 > image_copy.size[0]:
                y += 1
                x = 0
            if y + 27 > image_copy.size[1]:
                break
            if skip:
                # Skip every other pixel to save time
                skip = False
            else:
                if x + 34 != image_copy.size[0]:
                    # Can't skip the last part of an image
                    skip = True
                if image_copy.getpixel((x, y)) == slot_border[0]:
                    # If the current pixel looks like a slot
                    s = 0
                    diff = 0
                    diffmax = 1  # 3/4's of the border size
                    xs = 0
                    ys = 0

                    if x != 0 and image_copy.getpixel((x - 1, y)) == slot_border[0]:
                        # Make sure we didnt skip the beggining of a slot
                        # go back if we did
                        x -= 1
                        # We also flag the next pixel to avoid looping here forever if this turns out not to be a slot
                        image_copy.putpixel((x + 1, y), (255, 0, 255, 0))
                    while diff < diffmax:
                        if xs == 0 or xs == 33 or ys == 0 or ys == 33:
                            if not image_copy.getpixel((x + xs, y + ys)) == slot_border[s] \
                                and image_copy.getpixel((x + xs, y + ys)) not in [(24, 24, 24, 255),
                                                                                  (55, 55, 55, 255),
                                                                                  (57, 57, 57, 255),
                                                                                  (75, 76, 76, 255),
                                                                                  (255, 0, 255, 0)]:
                                # ^ This is a workaround to ignore the bottom-left border of containers
                                # as well as make the skipping work correctly
                                    break
                        s += 1
                        xs += 1
                        if xs == 34:
                            xs = 0
                            ys += 1
                        if ys == 28:
                            slot_list.append({'image': loot_image.crop((x + 1, y + 1, x + 33, y + 33)), 'x': x, 'y': y})
                            image_copy.paste(Image.new("RGBA", (34, 34), (255, 255, 255, 255)), (x, y))
                            x += 33
                            break
        return slot_list