""" AUTHOR: Khushal P Soonderji DATE: Monday, 2nd Sept., 2024 OBJECTIVE: To provide an easy way to assess images for adult content. Tried and implemented using HuggingFace behaviour_models. REFERENCES: N/A DOWNLOADS: N/A """ # ***************************************************************************************************************** # ***** **** # *** IMPORT *** # ***** **** # ***************************************************************************************************************** # To make sibling directories accessible for imports: import sys sys.path.append(".") sys.path.append("..") # System-level activities: import io # For using the AI model: import torch from transformers import pipeline # To download images from URLs: import requests # To read images: from PIL import Image # Common: from shared import variables # ***************************************************************************************************************** # ***** **** # *** MACROS / ONE-TIME INIT *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** VARIABLES *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** CLASSES *** # ***** **** # ***************************************************************************************************************** class AssessImageNSFW: def __init__( self, model, nsfw_label = "nsfw", nsfw_threshold = 0.25, ): """ This class assesses the input image and tells if it is blurry or clear. :param model: The model to use. Either the name of the HuggingFace repo, or the directory where the model is stored. :param nsfw_threshold: The max allowed blurriness (0 to 1 range). """ # Note down the config: self.__model = model self.__device = "gpu" if torch.cuda.is_available() else "cpu" self.__nsfw_label = nsfw_label self.__nsfw_threshold = nsfw_threshold # Initialize the classifier: self.__classifier = pipeline( task = "image-classification", model = self.__model, device = self.__device ) @staticmethod async def read_image(source): """ Reads an image in whichever format it is provided and returns it as a PIL object. :param source: The image as either a path or a URL or a io.BytesIO object. :return: The image opened as a PIL object. """ # If the input image is already a PIL image: if isinstance(source, Image.Image): return source # If a buffer is provided: elif isinstance(source, io.BytesIO): source.seek(0) return Image.open(source) # If a string is provided (local path or URL): elif isinstance(source, str): if source.startswith("http://") or source.startswith("https://"): response = await variables.http_client.get(source) return Image.open(io.BytesIO(response.content)) else: return Image.open(source) async def classify(self, image): """ To get the prediction of the model from the given input image. :param image: The image (as a PIL object or file path or a URL). :return: The dictionary of classes with their respective predictions. """ image = await self.read_image(image) predictions = self.__classifier(image) classes = {p["label"]: p["score"] for p in predictions} return classes async def is_ok( self, image, nsfw_threshold = None ): """ Checks if the image given to it can be used, or should be rejected. :param image: The image (as a PIL object or file path or a URL). :param nsfw_threshold: A custom threshold to test against. If not provided, the default will be taken that was provided when the instance was created. :return: True if the image is okay, else False. """ image = await self.read_image(image) nsfw_threshold = nsfw_threshold or self.__nsfw_threshold classes = await self.classify(image) return True if classes[self.__nsfw_label] <= nsfw_threshold else False # ***************************************************************************************************************** # ***** **** # *** MAIN PROGRAM *** # ***** **** # ***************************************************************************************************************** if __name__ == "__main__": import asyncio async def main(): assessor = AssessImageNSFW(model = r"/path/to/model") usable = await assessor.is_ok(r"/path/to/image/img.jpg") classes = await assessor.classify(r"https://...") asyncio.run(main())