Team Ai
Apppublic

aphilippov/python-server-api

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
0likes
img_utils.py171 linesDownload Raw Back to contrib
1import base642import mimetypes3import re4from io import BytesIO5from typing import Any, Dict, List, Optional, Tuple, Union6 7import requests8from PIL import Image9 10 11def get_image_data(image_file: str, use_b64=True) -> bytes:12    if image_file.startswith("http://") or image_file.startswith("https://"):13        response = requests.get(image_file)14        content = response.content15    elif re.match(r"data:image/(?:png|jpeg);base64,", image_file):16        return re.sub(r"data:image/(?:png|jpeg);base64,", "", image_file)17    else:18        image = Image.open(image_file).convert("RGB")19        buffered = BytesIO()20        image.save(buffered, format="PNG")21        content = buffered.getvalue()22 23    if use_b64:24        return base64.b64encode(content).decode("utf-8")25    else:26        return content27 28 29def llava_formatter(prompt: str, order_image_tokens: bool = False) -> Tuple[str, List[str]]:30    """31    Formats the input prompt by replacing image tags and returns the new prompt along with image locations.32 33    Parameters:34        - prompt (str): The input string that may contain image tags like <img ...>.35        - order_image_tokens (bool, optional): Whether to order the image tokens with numbers.36            It will be useful for GPT-4V. Defaults to False.37 38    Returns:39        - Tuple[str, List[str]]: A tuple containing the formatted string and a list of images (loaded in b64 format).40    """41 42    # Initialize variables43    new_prompt = prompt44    image_locations = []45    images = []46    image_count = 047 48    # Regular expression pattern for matching <img ...> tags49    img_tag_pattern = re.compile(r"<img ([^>]+)>")50 51    # Find all image tags52    for match in img_tag_pattern.finditer(prompt):53        image_location = match.group(1)54 55        try:56            img_data = get_image_data(image_location)57        except Exception as e:58            # Remove the token59            print(f"Warning! Unable to load image from {image_location}, because of {e}")60            new_prompt = new_prompt.replace(match.group(0), "", 1)61            continue62 63        image_locations.append(image_location)64        images.append(img_data)65 66        # Increment the image count and replace the tag in the prompt67        new_token = f"<image {image_count}>" if order_image_tokens else "<image>"68 69        new_prompt = new_prompt.replace(match.group(0), new_token, 1)70        image_count += 171 72    return new_prompt, images73 74 75def convert_base64_to_data_uri(base64_image):76    def _get_mime_type_from_data_uri(base64_image):77        # Decode the base64 string78        image_data = base64.b64decode(base64_image)79        # Check the first few bytes for known signatures80        if image_data.startswith(b"\xff\xd8\xff"):81            return "image/jpeg"82        elif image_data.startswith(b"\x89PNG\r\n\x1a\n"):83            return "image/png"84        elif image_data.startswith(b"GIF87a") or image_data.startswith(b"GIF89a"):85            return "image/gif"86        elif image_data.startswith(b"RIFF") and image_data[8:12] == b"WEBP":87            return "image/webp"88        return "image/jpeg"  # use jpeg for unknown formats, best guess.89 90    mime_type = _get_mime_type_from_data_uri(base64_image)91    data_uri = f"data:{mime_type};base64,{base64_image}"92    return data_uri93 94 95def gpt4v_formatter(prompt: str) -> List[Union[str, dict]]:96    """97    Formats the input prompt by replacing image tags and returns a list of text and images.98 99    Parameters:100        - prompt (str): The input string that may contain image tags like <img ...>.101 102    Returns:103        - List[Union[str, dict]]: A list of alternating text and image dictionary items.104    """105    output = []106    last_index = 0107    image_count = 0108 109    # Regular expression pattern for matching <img ...> tags110    img_tag_pattern = re.compile(r"<img ([^>]+)>")111 112    # Find all image tags113    for match in img_tag_pattern.finditer(prompt):114        image_location = match.group(1)115 116        try:117            img_data = get_image_data(image_location)118        except Exception as e:119            # Warning and skip this token120            print(f"Warning! Unable to load image from {image_location}, because {e}")121            continue122 123        # Add text before this image tag to output list124        output.append({"type": "text", "text": prompt[last_index : match.start()]})125 126        # Add image data to output list127        output.append({"type": "image_url", "image_url": {"url": convert_base64_to_data_uri(img_data)}})128 129        last_index = match.end()130        image_count += 1131 132    # Add remaining text to output list133    output.append({"type": "text", "text": prompt[last_index:]})134    return output135 136 137def extract_img_paths(paragraph: str) -> list:138    """139    Extract image paths (URLs or local paths) from a text paragraph.140 141    Parameters:142        paragraph (str): The input text paragraph.143 144    Returns:145        list: A list of extracted image paths.146    """147    # Regular expression to match image URLs and file paths148    img_path_pattern = re.compile(149        r"\b(?:http[s]?://\S+\.(?:jpg|jpeg|png|gif|bmp)|\S+\.(?:jpg|jpeg|png|gif|bmp))\b", re.IGNORECASE150    )151 152    # Find all matches in the paragraph153    img_paths = re.findall(img_path_pattern, paragraph)154    return img_paths155 156 157def _to_pil(data: str) -> Image.Image:158    """159    Converts a base64 encoded image data string to a PIL Image object.160 161    This function first decodes the base64 encoded string to bytes, then creates a BytesIO object from the bytes,162    and finally creates and returns a PIL Image object from the BytesIO object.163 164    Parameters:165        data (str): The base64 encoded image data string.166 167    Returns:168        Image.Image: The PIL Image object created from the input data.169    """170    return Image.open(BytesIO(base64.b64decode(data)))171