def predict(image_file):
    """
    Interface method between model and server. This signature must not be
    changed and your model must be able to predict given a file-like object
    with the image as an input.
    """

    image = Image.open(image_file.name, mode='r')
    stat = Stat(image)
    av_r = stat.mean[0]
    av_g = stat.mean[1]
    av_b = stat.mean[2]

    image.convert('L')  # Convert to grayscale
    stat = Stat(image)
    brightness = stat.mean[0]  # Between 0 -> 255. 0 is DARK and 255 is LIGHT

    image.close()
    return {
        'classes':
        ['average_red', 'average_green', 'average_blue',
         'brightness'],  # List every class in the classifier
        'result':
        {  # For results, use the class names above with the result value
            'average_red': av_r,
            'average_green': av_g,
            'average_blue': av_b,
            'brightness': stat.mean[0]
        }
    }
Beispiel #2
0
 def compare(self):
     ''' Compare the image in the sceen is the same as saved image'''
     # start_time = time.time()
     if not self.image:
         self.image = Image.open(self.__generate_image_path())
     current_image = grab(bbox=(self.tl_point[0], self.tl_point[1],
                                self.br_point[0], self.br_point[1]))
     result = (Stat(current_image).sum == Stat(self.image).sum)
     # end_time = time.time()
     # print("comparing {} took {}".format(self.name, str(end_time - start_time)))
     self.empty_click()
     return result
Beispiel #3
0
def calc_stats(im1, im2):
    """
    Calculate statistics to use in linear regression.

    :param im1: PIL Image object
    :param im2: PIL Image object
    :returns: numpy ndarray of shape (12, )
    """
    ph = []
    or1 = im1.convert('L')
    or2 = im2.convert('L')
    ds1 = or1.resize((1024, 1024))
    ds2 = or2.resize((1024, 1024))

    ph.append(
        np.abs(
            stats(np.array(or1.resize((2, 2)), dtype=np.float32)) -
            stats(np.array(or2.resize((2, 2)), dtype=np.float32))))
    ph.append([rms(np.array(ds1), np.array(ds2))])
    ph.append([np.abs(Stat(or1).mean[0] - Stat(or2).mean[0])])
    ph.append([np.abs(Stat(or1).stddev[0] - Stat(or2).stddev[0])])

    ph.append(Stat(ops.lighter(ds1, ds2)).mean)
    ph.append(Stat(ops.darker(ds1, ds2)).mean)
    ph.append(Stat(ops.lighter(ds1, ds2)).stddev)
    ph.append(Stat(ops.darker(ds1, ds2)).stddev)

    ph.append([np.abs(or1.size[0] / or1.size[1] - or2.size[0] / or2.size[1])])
    return np.hstack(ph)
Beispiel #4
0
def stats():
    stylist = Stylist()
    variance_array = np.zeros((stylist.n_styles, 3))
    mean_array = np.zeros((stylist.n_styles, 3))
    for index, style in enumerate(stylist.get_styles()):
        image = Image.open(style['image'])
        stat = Stat(image)
        variance_array[index] = np.array(stat.stddev)
        mean_array[index] = np.array(stat.mean)
    variance = variance_array.mean(axis=1)
    variance -= variance.min()
    variance /= variance.max()
    brightness = mean_array.mean(axis=1)
    brightness -= brightness.min()
    brightness /= brightness.max()
    tilt = np.abs(mean_array[:, 0] - mean_array[:, 1]) + \
           np.abs(mean_array[:, 0] - mean_array[:, 1]) + \
           np.abs(mean_array[:, 0] - mean_array[:, 1])
    tilt -= tilt.min()
    tilt /= tilt.max()
    neutrality_array = (variance + brightness + tilt) / 3
    indexes = np.argsort(neutrality_array)
    split = {
        'low': list(indexes[:41]),
        'medium': list(indexes[41:41 * 2]),
        'high': list(indexes[41 * 2:]),
    }
    print(split)
    def standarizeImageFormat(self, image, bbox=None):
        image = image.copy()

        #Crop if bbox is smaller than image size
        if bbox is not None:
            width = int(bbox[2])
            height = int(bbox[3])
            bottom = int(bbox[1])
            left = int(bbox[0])

            image = image.crop((left, bottom, left + width, bottom + height))

        #Scale to self.image_size
        width, height = image.size
        ratio = float(self.image_size) / max([width, height])
        new_size = tuple([int(x * ratio) for x in [width, height]])
        image = image.resize(new_size, Image.ANTIALIAS)

        #Pad with mean value
        if image.mode == 'RGB':
            stat = Stat(image)
            median_val = tuple([int(x) for x in stat.median])
        elif image.mode == 'I':
            median_val = int(np.round(np.median(image, axis=0))[0])
        else:
            raise ValueError('Mode not supported')
        pad_image = Image.new(image.mode, (self.image_size, self.image_size),
                              median_val)
        pad_image.paste(image, (int((self.image_size - new_size[0]) / 2),
                                int((self.image_size - new_size[1]) / 2)))

        return pad_image
Beispiel #6
0
def blurriness(img):
    from PIL.ImageFilter import Kernel
    from PIL.ImageStat import Stat
    lap = Kernel((3, 3), [0, 1, 0, 1, -4, 1, 0, 1, 0])
    img.copy().filter(lap)
    img_stat = Stat(img)
    return img_stat.var
Beispiel #7
0
def tile_by_id(id, path):
    '''
    '''

    conn = mysql_connection()
    mysql = conn.cursor(cursor_class=MySQLCursorDict)

    tms_path = '.'.join(path.split('.')[:-1])
    bucket = aws_prefix + 'stuff'
    opaque = False

    image = Image.new('RGBA', (256, 256), (0, 0, 0, 0))

    if request.endpoint == "tilemap":
        mysql.execute("SELECT tiles FROM maps WHERE id = %s", (id, ))
    elif request.endpoint == "tileatlas":
        mysql.execute(
            "SELECT tiles FROM maps WHERE atlas_id = %s AND image IS NOT NULL ORDER BY image DESC",
            (id, ))

    items = mysql.fetchdicts()

    conn.close()

    if items:
        for item in items:
            if 'tiles' in item and item['tiles'] != None:
                #s3_path = 'maps/%s/%s/%s.png' % (item.name, item['tiles'], tms_path)
                s3_path = '%s/%s.png' % (item['tiles'], tms_path)
                url = 'http://%(bucket)s.s3.amazonaws.com/%(s3_path)s' % locals(
                )

                try:
                    tile_img = Image.open(StringIO(urlopen(url).read()))
                except IOError:
                    continue

                fresh_img = Image.new('RGBA', (256, 256), (0, 0, 0, 0))
                fresh_img.paste(tile_img, (0, 0), tile_img)
                fresh_img.paste(image, (0, 0), image)
                image = fresh_img

            if Stat(image).extrema[3][0] > 0:
                opaque = True
                break

    if not opaque:
        url = 'http://tile.stamen.com/toner-lite/%s.png' % tms_path
        tile_img = Image.open(StringIO(urlopen(url).read()))
        tile_img.paste(image, (0, 0), image)
        image = tile_img

    bytes = StringIO()
    image.save(bytes, 'JPEG')

    resp = make_response(bytes.getvalue(), 200)
    resp.headers['Content-Type'] = 'image/jpeg'

    return resp
Beispiel #8
0
    def test_master_maker_save(self):
        self.logger.debug('test_master_maker_save')
        profile_target_path = abspath(join(
            dirname(realpath(__file__)),
            '..',
            'isaw',
            'awib',
            'icc',
            '{}.icc'.format('ProPhoto')))
        profile_target = getOpenProfile(profile_target_path)
        i = 0
        for fn, im_in in self.images.items():
            i += 1
            self.logger.debug('input filename: "{}"'.format(fn))
            maker = MasterMaker(im_in, logging_threshold=logging.DEBUG)
            master = maker.make()
            name, extension = splitext(fn)
            fn_out = 'test{}.tif'.format(i)
            self.logger.debug('output filename: "{}"'.format(fn_out))
            path_out = join(self.data_dir, 'scratch', fn_out)
            maker.save(path_out)
            continue

            im_out = Image.open(path_out)
            im_out.load()
            try:
                im_out.fp.close()
            except AttributeError:
                pass
            assert_equal(im_out.format, 'TIFF')
            assert_equal(master.mode, im_out.mode)
            stat_im_out = Stat(im_out)
            stat_master = Stat(master)
            assert_equal(stat_im_out.extrema, stat_master.extrema)
            assert_equal(stat_im_out.count, stat_master.count)
            assert_equal(stat_im_out.sum, stat_master.sum)
            assert_equal(stat_im_out.mean, stat_master.mean)
            assert_equal(stat_im_out.median, stat_master.median)
            assert_equal(stat_im_out.rms, stat_master.rms)
            assert_equal(stat_im_out.var, stat_master.var)
            self.logger.debug('info keys: {}'.format(im_out.info.keys()))
            assert_equal(
                getProfileName(
                    getOpenProfile(BytesIO(master.info['icc_profile']))),
                getProfileName(profile_target))
def _process_files(paths: List[Path], input_dir: str, output_dir: str,
                   logfile: str) -> int:
    def hash_fun(img: Image):
        return sha1(img.tobytes()).hexdigest()

    hashes = {}
    with open(logfile, 'w') as log:

        def _write_to_log(path: Path, error_code: int):
            log.write(f'{path.relative_to(input_dir)};{error_code}\n')

        for path in tqdm(paths, desc='Checking images'):
            # check if extension (including leading '.') is valid
            if not path.suffix[1:].lower() in _file_types:
                _write_to_log(path, 1)
                continue
            if path.stat().st_size < _min_file_size:
                _write_to_log(path, 2)
                continue

            # file exists, is small enough and might be an image
            try:
                img = Image.open(path)
            except (FileNotFoundError, ValueError,
                    UnidentifiedImageError) as e:
                _write_to_log(path, 3)
                if _verbose:
                    print(e)
                continue

            if Stat(img).var == 0:
                _write_to_log(path, 4)
                continue

            # check if (W, H) big enough and image has exactly two dimensions
            if len(img.size
                   ) != 2 or img.size[0] < _w_min or img.size[1] < _h_min:
                _write_to_log(path, 5)
                continue

            # file is valid in every way
            h = hash_fun(img)
            if h in hashes:
                _write_to_log(path, 6)
                if _verbose:
                    print(f"'{path}' duplicate of {hashes[h]}")
                continue
            # new file found
            else:
                if _verbose:
                    print(f"New file: '{path}'")
                hashes[h] = (path, len(hashes) + 1)

    # batch copy all valid files
    for path, num in tqdm(hashes.values(), desc='Copying images'):
        shutil.copy(path, Path(output_dir, f'{num:06d}.jpg'))
    return len(hashes)
Beispiel #10
0
 def predict(self, inputs: JpegImageFile) -> List[float]:
     stats = Stat(inputs)
     composer = inference_composer((256, 256), np.divide(stats.stddev, 255),
                                   np.divide(stats.mean, 255))
     with torch.no_grad():
         image = composer(inputs)
         output = self.model(image.float().unsqueeze(0))
         sigmoid = torch.nn.Sigmoid()
         # most CNNs return lists, wrapping this in a list to conform
         # to analysis APIs later on.
     return [float(sigmoid(output.detach().squeeze(1)))]
Beispiel #11
0
 def __getitem__(self, idx: int) -> Tuple[torch.Tensor, int, dict]:
     image = Image.open(
         os.path.join(self.base_dir, self.metadata[idx]["image"])
     ).convert("L")
     stats = Stat(image)
     stddev = np.divide(stats.stddev, 255)
     mean = np.divide(stats.mean, 255)
     if self.set_type == SetType.train:
         composer = train_composer(DIMS, stddev, mean)
     else:
         composer = inference_composer(DIMS, stddev, mean)
     return composer(image), self.metadata[idx]["label"], self.metadata[idx]
Beispiel #12
0
def split_normalize(image):
    """Splitting source image then normalize it.
    
    :param image: source image
    :return: blue and green channel
    """
    im = Image.Image.split(image)
    g = ImageOps.equalize(im[1], mask = None)
    mean = Stat(im[2]).mean[0]
    b = np.array(im[2]).astype('float32')
    b /= (1.0 + mean) 
    mean = Stat(g).mean[0]
    g = np.array(g).astype('float32')
    g /= (1.0 + mean)
    b = np.clip(b, 0, 1)
    g = np.clip(g, 0, 1)
    b *= 255.0
    g *= 255.0
    b = Image.fromarray(b.astype('uint8'))
    g = Image.fromarray(g.astype('uint8'))
    return b, g
Beispiel #13
0
    def __getitem__(self, idx: int) -> Tuple[torch.tensor, torch.tensor]:
        image = Image.open(
            os.path.join(self.base_dir,
                         self.metadata[idx]["image"])).convert("L")
        stats = Stat(image)
        stddev = np.divide(stats.stddev, 255)
        mean = np.divide(stats.mean, 255)

        curr_img_label = self.metadata[idx]["label"]
        random_idx = random.randint(0, len(self) - 1)
        diff_img_label = self.metadata[random_idx]["label"]
        get_same_class = random.choice([True, False])
        if get_same_class:
            while curr_img_label != diff_img_label:
                random_idx = random.randint(0, len(self) - 1)
                diff_img_label = self.metadata[random_idx]["label"]
        else:
            while curr_img_label == diff_img_label:
                random_idx = random.randint(0, len(self) - 1)
                diff_img_label = self.metadata[random_idx]["label"]

        distance = 1 if get_same_class else 0

        image2 = Image.open(
            os.path.join(self.base_dir,
                         self.metadata[random_idx]["image"])).convert("L")
        stats2 = Stat(image2)
        stddev2 = np.divide(stats2.stddev, 255)
        mean2 = np.divide(stats2.mean, 255)

        if self.set_type == SetType.train:
            composer = train_composer(DIMS, stddev, mean)
            composer2 = train_composer(DIMS, stddev2, mean2)
        else:
            composer = inference_composer(DIMS, stddev, mean)
            composer2 = inference_composer(DIMS, stddev2, mean2)
        return composer(image), composer2(image2), distance
Beispiel #14
0
    async def thumbnail(self,
                        data: bytes | str,
                        content_type: str = '') -> Resource.Thumbnail:
        """Generate a thumbnail from image *data*.

        *content_type* is the media type of the image. The generated thumbnail is stored in
        :attr:`files`. If *data* is corrupt, a :exc:`BrokenResourceError` is raised.

        If alternatively an image *url* is given, the image is fetched first. If there is a problem,
        an :exc:`AnalysisError` or :exc:`CommunicationError` is raised.
        """
        if isinstance(data, str):
            data, content_type, _ = await self.fetch(data)
            return await self.thumbnail(data, content_type)
        if not self.files:
            raise ValueError('No files')

        if content_type in {
                'image/bmp', 'image/gif', 'image/jpeg', 'image/png'
        }:
            try:
                with PIL.Image.open(BytesIO(data),
                                    formats=[content_type[6:]]) as src:
                    image = exif_transpose(src)
                    image.thumbnail(Analyzer.THUMBNAIL_SIZE)
                    if image.mode == 'RGB':
                        r, g, b = cast(tuple[float, float, float],
                                       Stat(image).mean)
                        color = f'#{int(r):02x}{int(g):02x}{int(b):02x}'
                    else:
                        # At the moment, transparent (RGBA, LA), grayscale (L, I, 1), CMYK and color
                        # palette (P) images are not handled
                        color = '#ffffff'
                    stream = BytesIO()
                    image.save(stream, format=cast(str, src.format))
                    data = stream.getvalue()
            except DecompressionBombError as e:
                raise BrokenResourceError('Exceeding data size') from e
            except OSError as e:
                raise BrokenResourceError('Bad data') from e
        elif content_type == 'image/svg+xml':
            color = '#ffffff'
        else:
            raise BrokenResourceError(f'Unknown content_type {content_type}')

        url = await self.files.write(data, content_type)
        return Resource.Thumbnail(url, color)
Beispiel #15
0
def get_pil_image_statistics(img: ImageType, channels: List[str] = _IMAGE_HSV_CHANNELS, image_stats: List[str] = _STATS_PROPERTIES) -> Dict:
    """
    Compute statistics data for a PIL Image

    Args:
        img (ImageType): PIL Image

    Returns:
        Dict: of metadata
    """

    stats = Stat(img.convert("HSV"))
    metadata = {}
    for index in range(len(channels)):
        for statistic_name in image_stats:
            if hasattr(stats, statistic_name):
                metadata[channels[index] + "." + statistic_name] = getattr(stats, statistic_name)[index]

    return metadata
Beispiel #16
0
def classify_rulebased(im1, im2):
    """
    Classify 2 images using rule-based method.

    :param im1: PIL Image object
    :param im2: PIL Image object
    :returns: False if images are different, True otherwise
    """
    or1 = im1.convert('L')
    or2 = im2.convert('L')
    ds1 = or1.resize((1024, 1024))
    ds2 = or2.resize((1024, 1024))

    err = rms(np.array(ds1), np.array(ds2))
    size_diff = np.abs(or1.size[0] / or1.size[1] - or2.size[0] / or2.size[1])
    d_std = Stat(ops.darker(ds1, ds2)).stddev[0]

    if err < 9.8 and (err == 0 or size_diff < 0.5 or d_std > 28):
        return True
    else:
        return False
sums = []

# Loop over all the files in the directory

for file in list_files:

    img = Image.open(file)
    width, height = img.size

    # Crop as needed

    img_c = img.crop((790, 400, 2300, 1200))  # left top right bottom
    img_c.show()

    file_out = file.replace('/in/', f'/out/{i:05}_')

    # Get a checksum for the cropped image (or just a 'sum', which is just as good)

    sum = Stat(img_c).sum
    sums.append(sum)
    i += 1

    # If the cropped image's checksum is the same as the previous one, then skip it
    # And if it *has* changed, write the output image

    if (i > 1):
        if sum == sums[i - 2]:
            print('sum matched! -- skipping write')
        else:
            img_c.save(file_out)
            print(f'Wrote: {file_out}')
Beispiel #18
0
import os
import sys
from collections import defaultdict
from math import floor
from statistics import mean

from PIL import Image
from PIL.ImageStat import Stat

base_dir = sys.argv[1]

buckets = defaultdict(list)

for dirpath, dirs, files in os.walk(base_dir):
    for filename in files:
        if filename.endswith(".jpg"):
            input_file = os.path.join(dirpath, filename)
            # print(input_file)
            image = Image.open(input_file)
            image_statistics = Stat(image)
            bucket = floor(mean(image_statistics.mean))
            buckets[bucket].append(image)

for bucket in sorted(buckets.keys()):
    images = buckets[bucket]
    print("{}: {}".format(bucket, len(images)))
Beispiel #19
0
def stats(image):
    """
    Obtain basic image statics; mean of pixel values and total number of pixels
    """
    stat = Stat(image)
    return stat.mean, stat.count
Beispiel #20
0
def byColor(url):
    allPokemon = {
        8229509: 'Bulbasaur',
        7372414: 'Ivysaur',
        8948874: 'Venusaur',
        9732213: 'Charmander',
        9664626: 'Charmeleon',
        9340798: 'Charizard',
        7108730: 'Squirtle',
        8094087: 'Wartortle',
        8486785: 'Blastoise',
        7436382: 'Caterpie',
        7502948: 'Metapod',
        9408403: 'Butterfree',
        8813686: 'Weedle',
        12893865: 'Kakuna',
        8618365: 'Beedrill',
        7695713: 'Pidgey',
        8353903: 'Pidgeotto',
        7300700: 'Pidgeot',
        7827573: 'Rattata',
        7497561: 'Raticate',
        7232857: 'Spearow',
        6971223: 'Fearow',
        8087665: 'Ekans',
        8287868: 'Arbok',
        8484703: 'Pikachu',
        7235677: 'Raichu',
        9472374: 'Sandshrew',
        7300695: 'Sandslash',
        8752279: 'Nidoran♀',
        7897991: 'Nidorina',
        7305342: 'Nidoqueen',
        8419205: 'Nidoran♂',
        8418946: 'Nidorino',
        9603731: 'Nidoking',
        11574174: 'Clefairy',
        10391950: 'Clefable',
        9861998: 'Vulpix',
        10591106: 'Ninetales',
        9668748: 'Jigglypuff',
        10459805: 'Wigglytuff',
        5525850: 'Zubat',
        6907503: 'Golbat',
        6518377: 'Oddish',
        8946049: 'Gloom',
        9205373: 'Vileplume',
        9798522: 'Paras',
        8941673: 'Parasect',
        7959424: 'Venonat',
        10986922: 'Venomoth',
        9142652: 'Diglett',
        8287344: 'Dugtrio',
        9209986: 'Meowth',
        8091503: 'Persian',
        11840152: 'Psyduck',
        5397604: 'Golduck',
        9802127: 'Mankey',
        7827307: 'Primeape',
        11774625: 'Growlithe',
        9800062: 'Arcanine',
        8949397: 'Poliwag',
        8028297: 'Poliwhirl',
        9804449: 'Poliwrath',
        10328196: 'Abra',
        8946542: 'Kadabra',
        8222823: 'Alakazam',
        8686478: 'Machop',
        9276821: 'Machoke',
        7435641: 'Machamp',
        7501416: 'Bellsprout',
        9738632: 'Weepinbell',
        8753017: 'Victreebel',
        7567227: 'Tentacool',
        8422279: 'Tentacruel',
        13092807: 'Geodude',
        12040374: 'Graveler',
        7697009: 'Golem',
        11441546: 'Ponyta',
        11178628: 'Rapidash',
        10982810: 'Slowpoke',
        10194834: 'Slowbro',
        11514290: 'Magnemite',
        7632504: 'Magneton',
        8881020: 'Farfetch’d',
        9868176: 'Doduo',
        7367529: 'Dodrio',
        9079951: 'Seel',
        9146001: 'Dewgong',
        10130845: 'Grimer',
        11908023: 'Muk',
        7630973: 'Shellder',
        6907759: 'Cloyster',
        10325146: 'Gastly',
        6710121: 'Haunter',
        6973044: 'Gengar',
        6645097: 'Onix',
        10985094: 'Drowzee',
        8945762: 'Hypno',
        11511200: 'Krabby',
        10984857: 'Kingler',
        11244437: 'Voltorb',
        11117481: 'Electrode',
        11708841: 'Exeggcute',
        6252124: 'Exeggutor',
        10197139: 'Cubone',
        9144196: 'Marowak',
        7433580: 'Hitmonlee',
        8815234: 'Hitmonchan',
        11442330: 'Lickitung',
        10921378: 'Koffing',
        8420480: 'Weezing',
        8027778: 'Rhyhorn',
        8553093: 'Rhydon',
        11640999: 'Chansey',
        8028554: 'Tangela',
        8682358: 'Kangaskhan',
        7768204: 'Horsea',
        7372418: 'Seadra',
        12302264: 'Goldeen',
        9537928: 'Seaking',
        7827040: 'Staryu',
        8157307: 'Starmie',
        7433072: 'Mr. Mime',
        7107179: 'Scyther',
        9996164: 'Jynx',
        6249297: 'Electabuzz',
        7298640: 'Magmar',
        6578529: 'Pinsir',
        6643289: 'Tauros',
        8614250: 'Magikarp',
        7370361: 'Gyarados',
        5924717: 'Lapras',
        10853805: 'Ditto',
        9208182: 'Eevee',
        7175552: 'Vaporeon',
        8946029: 'Jolteon',
        9403756: 'Flareon',
        7566198: 'Porygon',
        10133915: 'Omanyte',
        8357508: 'Omastar',
        11181717: 'Kabuto',
        7235683: 'Kabutops',
        9802646: 'Aerodactyl',
        10396579: 'Snorlax',
        6517371: 'Articuno',
        9670275: 'Zapdos',
        13549753: 'Moltres',
        6447975: 'Dratini',
        6712177: 'Dragonair',
        9735809: 'Dragonite',
        8354687: 'Mewtwo',
        11511464: 'Mew',
        9212805: 'Chikorita',
        11184542: 'Bayleef',
        12170413: 'Meganium',
        11639950: 'Cyndaquil',
        12957094: 'Quilava',
        12299416: 'Typhlosion',
        10068899: 'Totodile',
        7238512: 'Croconaw',
        7503488: 'Feraligatr',
        12499639: 'Sentret',
        9537408: 'Furret',
        6906204: 'Hoothoot',
        11117728: 'Noctowl',
        9603712: 'Ledyba',
        10459028: 'Ledian',
        11054239: 'Spinarak',
        7365730: 'Ariados',
        9606038: 'Crobat',
        8092797: 'Chinchou',
        10790570: 'Lanturn',
        8158062: 'Pichu',
        10588813: 'Cleffa',
        11642791: 'Igglybuff',
        11249820: 'Togepi',
        11448492: 'Togetic',
        7105361: 'Natu',
        10262929: 'Xatu',
        11118235: 'Mareep',
        9801360: 'Flaaffy',
        9736066: 'Ampharos',
        8814187: 'Bellossom',
        8426911: 'Marill',
        6188662: 'Azumarill',
        7038816: 'Sudowoodo',
        10265484: 'Politoed',
        8419187: 'Hoppip',
        10069890: 'Skiploom',
        13158085: 'Jumpluff',
        8156790: 'Aipom',
        9605754: 'Sunkern',
        8028008: 'Sunflora',
        10986141: 'Yanma',
        7766149: 'Wooper',
        8951452: 'Quagsire',
        6643297: 'Espeon',
        6645092: 'Umbreon',
        5659230: 'Murkrow',
        12366256: 'Slowking',
        6910585: 'Misdreavus',
        6909552: 'Unown',
        10202550: 'Wobbuffet',
        10195848: 'Girafarig',
        7042680: 'Pineco',
        10589075: 'Forretress',
        8553588: 'Dunsparce',
        8153208: 'Gligar',
        7040369: 'Steelix',
        9864069: 'Snubbull',
        9997972: 'Granbull',
        6844774: 'Qwilfish',
        8219755: 'Scizor',
        7892574: 'Shuckle',
        4673623: 'Heracross',
        5198678: 'Sneasel',
        11903892: 'Teddiursa',
        10721424: 'Ursaring',
        10517876: 'Slugma',
        10649981: 'Magcargo',
        11642271: 'Swinub',
        9667193: 'Piloswine',
        8940912: 'Corsola',
        8685957: 'Remoraid',
        9728105: 'Octillery',
        10720402: 'Delibird',
        11119019: 'Mantine',
        9473167: 'Skarmory',
        8288889: 'Houndour',
        5459791: 'Houndoom',
        6253421: 'Kingdra',
        8295829: 'Phanpy',
        11251377: 'Donphan',
        7432819: 'Porygon2',
        8683128: 'Stantler',
        8552312: 'Smeargle',
        6775137: 'Tyrogue',
        6447456: 'Hitmontop',
        12432811: 'Smoochum',
        10197388: 'Elekid',
        10456714: 'Magby',
        9471618: 'Miltank',
        11311518: 'Blissey',
        9209723: 'Raikou',
        7629410: 'Entei',
        7172726: 'Suicune',
        11053730: 'Larvitar',
        9541279: 'Pupitar',
        7633006: 'Tyranitar',
        8948365: 'Lugia',
        7496537: 'Ho-Oh',
        8949381: 'Celebi',
        6975065: 'Treecko',
        6975335: 'Grovyle',
        6187358: 'Sceptile',
        11839636: 'Torchic',
        6971734: 'Combusken',
        9800064: 'Blaziken',
        6779767: 'Mudkip',
        7963009: 'Marshtomp',
        9146773: 'Swampert',
        7763574: 'Poochyena',
        5395026: 'Mightyena',
        11315622: 'Zigzagoon',
        13026499: 'Linoone',
        10128007: 'Wurmple',
        8026748: 'Silcoon',
        6644059: 'Beautifly',
        8683908: 'Cascoon',
        10855830: 'Dustox',
        8164486: 'Lotad',
        8095603: 'Lombre',
        10132617: 'Ludicolo',
        10394262: 'Seedot',
        7696491: 'Nuzleaf',
        7500653: 'Shiftry',
        8683653: 'Noivern',
        7762551: 'Swellow',
        8750726: 'Wingull',
        9276802: 'Pelipper',
        11646383: 'Ralts',
        11317161: 'Kirlia',
        6514274: 'Gardevoir',
        6514536: 'Surskit',
        9341320: 'Masquerain',
        10591896: 'Shroomish',
        8421240: 'Breloom',
        12565432: 'Slakoth',
        11118504: 'Vigoroth',
        11644071: 'Slaking',
        12040375: 'Nincada',
        10196886: 'Ninjask',
        8880247: 'Shedinja',
        10326156: 'Whismur',
        7959418: 'Loudred',
        8025468: 'Exploud',
        11182992: 'Makuhita',
        9667701: 'Hariyama',
        7046550: 'Azurill',
        7434113: 'Nosepass',
        9734276: 'Skitty',
        9669002: 'Delcatty',
        5854305: 'Sableye',
        8815486: 'Mawile',
        9145999: 'Aron',
        10066330: 'Lairon',
        7171439: 'Aggron',
        8160392: 'Meditite',
        11642278: 'Medicham',
        11186595: 'Electrike',
        9606801: 'Manectric',
        11246743: 'Plusle',
        8949389: 'Minun',
        12892856: 'Volbeat',
        9869211: 'Illumise',
        6581095: 'Roselia',
        9082501: 'Gulpin',
        8287883: 'Swalot',
        8814972: 'Carvanha',
        7041399: 'Sharpedo',
        11712958: 'Wailmer',
        11449527: 'Wailord',
        10130040: 'Numel',
        10851213: 'Camerupt',
        9997442: 'Torkoal',
        11249833: 'Spoink',
        6972520: 'Grumpig',
        9931142: 'Spinda',
        11374466: 'Trapinch',
        8357502: 'Vibrava',
        8882304: 'Flygon',
        9804944: 'Cacnea',
        6450015: 'Cacturne',
        13226971: 'Swablu',
        9477542: 'Altaria',
        8551550: 'Zangoose',
        7237231: 'Seviper',
        10064770: 'Lunatone',
        6510666: 'Solrock',
        11054512: 'Barboach',
        8159624: 'Whiscash',
        9598829: 'Corphish',
        8284517: 'Crawdaunt',
        6906457: 'Baltoy',
        7695467: 'Claydol',
        9274245: 'Lileep',
        9014145: 'Cradily',
        6512735: 'Anorith',
        7632505: 'Armaldo',
        9934482: 'Feebas',
        8155759: 'Milotic',
        12171707: 'Castform',
        9342328: 'Kecleon',
        7764099: 'Shuppet',
        6710371: 'Banette',
        9276810: 'Duskull',
        7829109: 'Dusclops',
        7042918: 'Tropius',
        12171192: 'Chimecho',
        10395554: 'Absol',
        7964295: 'Wynaut',
        9998469: 'Snorunt',
        8422022: 'Glalie',
        10922671: 'Spheal',
        9476765: 'Sealeo',
        7110536: 'Walrein',
        7896968: 'Clamperl',
        8882054: 'Gothitelle',
        8880002: 'Gorebyss',
        10262420: 'Relicanth',
        13745085: 'Luvdisc',
        10726060: 'Bagon',
        10921382: 'Shelgon',
        8947083: 'Salamence',
        11647680: 'Beldum',
        8226958: 'Metang',
        9607838: 'Metagross',
        8681589: 'Regirock',
        7900051: 'Regice',
        9342350: 'Registeel',
        7367275: 'Latias',
        8883345: 'Latios',
        11515844: 'Kyogre',
        11244175: 'Groudon',
        5660504: 'Rayquaza',
        10658712: 'Jirachi',
        7169378: 'Deoxys',
        10001803: 'Turtwig',
        7107930: 'Grotle',
        7502443: 'Torterra',
        12102557: 'Chimchar',
        9272946: 'Monferno',
        9864055: 'Infernape',
        10530483: 'Piplup',
        6449513: 'Prinplup',
        7303794: 'Empoleon',
        8420217: 'Starly',
        9473676: 'Staravia',
        7894129: 'Staraptor',
        9470063: 'Bidoof',
        9273713: 'Bibarel',
        12497322: 'Kricketot',
        10062984: 'Kricketune',
        6647405: 'Shinx',
        6383203: 'Luxio',
        5724760: 'Luxray',
        11648418: 'Budew',
        9936027: 'Roserade',
        7699842: 'Cranidos',
        8027776: 'Rampardos',
        8025452: 'Shieldon',
        8355194: 'Bastiodon',
        10792351: 'Burmy',
        7108203: 'Wormadam',
        11709344: 'Mothim',
        11775135: 'Combee',
        8682090: 'Vespiquen',
        9410972: 'Pachirisu',
        11181973: 'Buizel',
        9471864: 'Floatzel',
        8943728: 'Cherubi',
        8552578: 'Cherrim',
        10720406: 'Shellos',
        9798783: 'Gastrodon',
        8353911: 'Ambipom',
        10131608: 'Drifloon',
        6840929: 'Drifblim',
        12301742: 'Buneary',
        9472122: 'Lopunny',
        9735574: 'Mismagius',
        8750986: 'Honchkrow',
        6514023: 'Glameow',
        8618373: 'Purugly',
        8484710: 'Chingling',
        7367534: 'Stunky',
        9604495: 'Skuntank',
        7900562: 'Bronzor',
        10397349: 'Bronzong',
        10330005: 'Bonsly',
        9736339: 'Mime Jr.',
        12103343: 'Happiny',
        6580326: 'Chatot',
        11968414: 'Spiritomb',
        6976375: 'Gible',
        5723484: 'Gabite',
        5920860: 'Garchomp',
        9278872: 'Munchlax',
        5725791: 'Riolu',
        9080206: 'Lucario',
        10656392: 'Hippopotas',
        10722707: 'Hippowdon',
        7172216: 'Skorupi',
        10722981: 'Drapion',
        8290953: 'Croagunk',
        6250853: 'Toxicroak',
        7961967: 'Carnivine',
        7961727: 'Finneon',
        6844784: 'Lumineon',
        8490647: 'Mantyke',
        9672340: 'Snover',
        8752010: 'Abomasnow',
        6641243: 'Weavile',
        9145742: 'Magnezone',
        9073010: 'Lickilicky',
        10326927: 'Rhyperior',
        7436157: 'Tangrowth',
        9012601: 'Electivire',
        8743512: 'Magmortar',
        11711925: 'Togekiss',
        9341059: 'Yanmega',
        8422775: 'Leafeon',
        6910834: 'Glaceon',
        7039855: 'Gliscor',
        10459022: 'Mamoswine',
        7763834: 'Porygon-Z',
        7172461: 'Gallade',
        7958643: 'Probopass',
        8947586: 'Dusknoir',
        13093063: 'Froslass',
        9351882: 'Rotom',
        8553083: 'Uxie',
        9868183: 'Mesprit',
        9278615: 'Azelf',
        6251369: 'Dialga',
        8289152: 'Palkia',
        10657177: 'Heatran',
        10526872: 'Regigigas',
        7300191: 'Giratina',
        10191745: 'Cresselia',
        8556948: 'Phione',
        9805986: 'Manaphy',
        5723476: 'Darkrai',
        9870217: 'Shaymin',
        8487294: 'Arceus',
        8814453: 'Victini',
        8029040: 'Snivy',
        6580830: 'Servine',
        7438195: 'Serperior',
        8614504: 'Tepig',
        8876900: 'Pignite',
        8349529: 'Emboar',
        10397093: 'Oshawott',
        9673372: 'Dewott',
        6514794: 'Samurott',
        8616044: 'Patrat',
        12761779: 'Watchog',
        11246734: 'Lillipup',
        7498600: 'Herdier',
        10131346: 'Stoutland',
        8749188: 'Purrloin',
        7235687: 'Liepard',
        8622976: 'Pansage',
        7833721: 'Simisage',
        10585723: 'Pansear',
        9072485: 'Simisear',
        8293253: 'Panpour',
        7308417: 'Simipour',
        12033701: 'Munna',
        11572131: 'Musharna',
        7039079: 'Pidove',
        6513249: 'Tranquill',
        8158074: 'Unfezant',
        10461085: 'Blitzle',
        7566194: 'Zebstrika',
        10066072: 'Roggenrola',
        7235949: 'Boldore',
        6444889: 'Gigalith',
        9935258: 'Woobat',
        6185314: 'Swoobat',
        7170922: 'Drilbur',
        8618111: 'Excadrill',
        11312278: 'Audino',
        9143165: 'Timburr',
        7563111: 'Gurdurr',
        9538697: 'Conkeldurr',
        8948358: 'Tympole',
        9213074: 'Palpitoad',
        7044998: 'Seismitoad',
        8485752: 'Throh',
        7766404: 'Sawk',
        10198142: 'Sewaddle',
        8490095: 'Swadloon',
        11383204: 'Leavanny',
        9665920: 'Venipede',
        9078666: 'Whirlipede',
        5984338: 'Scolipede',
        11975861: 'Cottonee',
        11381916: 'Whimsicott',
        11713195: 'Petilil',
        10199693: 'Lilligant',
        7239277: 'Basculin',
        10130316: 'Sandile',
        6972510: 'Krokorok',
        7563885: 'Krookodile',
        9400681: 'Darumaka',
        8810603: 'Darmanitan',
        8620415: 'Maractus',
        8943985: 'Dwebble',
        9077115: 'Crustle',
        10458759: 'Scraggy',
        11115665: 'Scrafty',
        7762542: 'Sigilyph',
        7565420: 'Yamask',
        10593951: 'Cofagrigus',
        10791342: 'Tirtouga',
        8358292: 'Carracosta',
        10328213: 'Archen',
        8751754: 'Archeops',
        6514787: 'Trubbish',
        8618877: 'Garbodor',
        8419966: 'Zorua',
        6050131: 'Zoroark',
        10065556: 'Minccino',
        10329248: 'Cinccino',
        10855078: 'Gothita',
        9342606: 'Gothorita',
        11323313: 'Solosis',
        10929327: 'Duosion',
        13031631: 'Reuniclus',
        9674652: 'Ducklett',
        8619652: 'Swanna',
        10725548: 'Vanillite',
        12109008: 'Vanillish',
        10464700: 'Vanilluxe',
        11248798: 'Deerling',
        6182992: 'Sawsbuck',
        10526358: 'Emolga',
        10462111: 'Karrablast',
        8747641: 'Escavalier',
        10327954: 'Foongus',
        8945791: 'Amoonguss',
        6658474: 'Frillish',
        10336973: 'Jellicent',
        12563124: 'Alomomola',
        10788228: 'Joltik',
        9933189: 'Galvantula',
        8291455: 'Ferroseed',
        8554115: 'Ferrothorn',
        8093055: 'Klink',
        9212049: 'Klang',
        10856360: 'Klinklang',
        12108488: 'Tynamo',
        8946817: 'Eelektrik',
        11579824: 'Eelektross',
        10793646: 'Elgyem',
        10722456: 'Beheeyem',
        12501198: 'Litwick',
        7500917: 'Lampent',
        6776940: 'Chandelure',
        8553854: 'Axew',
        6316636: 'Fraxure',
        8223342: 'Haxorus',
        11385538: 'Cubchoo',
        8752011: 'Beartic',
        7503503: 'Cryogonal',
        9603463: 'Shelmet',
        7038826: 'Accelgor',
        11577245: 'Stunfisk',
        8549481: 'Mienfoo',
        6118492: 'Mienshao',
        6516595: 'Druddigon',
        6780273: 'Golett',
        7306360: 'Golurk',
        8157303: 'Pawniard',
        11446696: 'Bisharp',
        8222833: 'Bouffalant',
        12368567: 'Rufflet',
        6577501: 'Braviary',
        6644318: 'Vullaby',
        10854558: 'Mandibuzz',
        10061438: 'Heatmor',
        10921638: 'Durant',
        8421505: 'Deino',
        5526356: 'Zweilous',
        5262672: 'Hydreigon',
        8090480: 'Larvesta',
        9337974: 'Volcarona',
        9542555: 'Cobalion',
        8420472: 'Terrakion',
        9146501: 'Virizion',
        10263452: 'Tornadus',
        9080207: 'Thundurus',
        8422280: 'Reshiram',
        7303537: 'Zekrom',
        9735049: 'Landorus',
        7764347: 'Kyurem',
        7367784: 'Keldeo',
        11119269: 'Meloetta',
        8221565: 'Genesect',
        10328203: 'Chespin',
        6578256: 'Quilladin',
        8947583: 'Chesnaught',
        11839124: 'Fennekin',
        10656399: 'Braixen',
        9271408: 'Delphox',
        8228493: 'Froakie',
        7831428: 'Frogadier',
        9934232: 'Greninja',
        10262677: 'Bunnelby',
        9209471: 'Diggersby',
        8221809: 'Fletchling',
        6839640: 'Fletchinder',
        8485494: 'Talonflame',
        10657951: 'Scatterbug',
        10394523: 'Spewpa',
        8678516: 'Vivillon',
        7957602: 'Litleo',
        8283733: 'Pyroar',
        8614761: 'Flabébé',
        8485495: 'Floette',
        8160128: 'Florges',
        5989469: 'Skiddo',
        7633776: 'Gogoat',
        11184549: 'Pancham',
        7960954: 'Pangoro',
        11448235: 'Furfrou',
        10000285: 'Espurr',
        7568009: 'Meowstic',
        10001309: 'Honedge',
        10325651: 'Doublade',
        8486265: 'Aegislash',
        10060423: 'Spritzee',
        11704996: 'Aromatisse',
        12828609: 'Swirlix',
        11049118: 'Slurpuff',
        9276045: 'Inkay',
        8091518: 'Malamar',
        8485749: 'Binacle',
        7104614: 'Barbaracle',
        8748411: 'Skrelp',
        6511707: 'Dragalge',
        9673886: 'Clauncher',
        10462633: 'Clawitzer',
        9670530: 'Helioptile',
        8157296: 'Heliolisk',
        9867147: 'Tyrunt',
        8615540: 'Tyrantrum',
        10593696: 'Amaura',
        10066839: 'Aurorus',
        10722720: 'Sylveon',
        9605516: 'Hawlucha',
        9799534: 'Dedenne',
        9672093: 'Carbink',
        8354174: 'Goomy',
        11117993: 'Sliggoo',
        8683651: 'Goodra',
        8947333: 'Klefki',
        5920596: 'Phantump',
        6579551: 'Trevenant',
        7892324: 'Pumpkaboo',
        8483947: 'Gourgeist',
        11253703: 'Bergmite',
        12109787: 'Avalugg',
        7695734: 'Noibat',
        8158073: 'Xerneas',
        6575702: 'Yveltal',
        5921358: 'Zygarde',
        12626872: 'Diancie',
        5590346: 'Hoopa',
        8020833: 'Volcanion',
        12828858: 'Rowlet',
        11052959: 'Dartrix',
        9934477: 'Decidueye',
        10196628: 'Litten',
        9733760: 'Torracat',
        11839911: 'Incineroar',
        9476003: 'Popplio',
        11582400: 'Brionne',
        8752788: 'Primarina',
        9539213: 'Pikipek',
        10000021: 'Trumbeak',
        9472903: 'Toucannon',
        12630709: 'Yungoos',
        9670277: 'Gumshoos',
        13880517: 'Grubbin',
        11778992: 'Charjabug',
        9277588: 'Vikavolt',
        8490386: 'Crabrawler',
        10527653: 'Crabominable',
        9207166: 'Oricorio',
        12368048: 'Cutiefly',
        12499635: 'Ribombee',
        11183523: 'Rockruff',
        11644845: 'Lycanroc',
        13422545: 'Wishiwashi',
        10266540: 'Mareanie',
        8487818: 'Toxapex',
        10525336: 'Mudbray',
        8813176: 'Mudsdale',
        11976634: 'Dewpider',
        10596532: 'Araquanid',
        12042170: 'Fomantis',
        12366001: 'Lurantis',
        14079189: 'Morelull',
        9999504: 'Shiinotic',
        8355196: 'Salandit',
        8881285: 'Salazzle',
        10260881: 'Stufful',
        8880514: 'Bewear',
        10261646: 'Bounsweet',
        10067090: 'Steenee',
        10197903: 'Tsareena',
        13285030: 'Comfey',
        10329245: 'Oranguru',
        8026999: 'Passimian',
        10921126: 'Wimpod',
        8356223: 'Golisopod',
        11578277: 'Sandygast',
        13086622: 'Palossand',
        11116706: 'Pyukumuku',
        9539727: 'Type: Null',
        11053482: 'Silvally',
        11183010: 'Minior',
        10658980: 'Komala',
        9667449: 'Turtonator',
        12303030: 'Togedemaru',
        10131603: 'Mimikyu',
        11578028: 'Bruxish',
        11449006: 'Drampa',
        9343632: 'Dhelmise',
        9276550: 'Jangmo-o',
        9868171: 'Hakamo-o',
        9209983: 'Kommo-o',
        10262153: 'Tapu Koko',
        12233646: 'Tapu Lele',
        8287601: 'Tapu Bulu',
        9737115: 'Tapu Fini',
        9018294: 'Cosmog',
        10986651: 'Cosmoem',
        10197655: 'Solgaleo',
        7894651: 'Lunala',
        14279145: 'Nihilego',
        9271670: 'Buzzwole',
        13881034: 'Pheromosa',
        8291458: 'Xurkitree',
        7243907: 'Celesteela',
        6512731: 'Kartana',
        8488067: 'Guzzlord',
        11513002: 'Necrozma',
        11381673: 'Magearna',
        8947850: 'Marshadow',
        10064286: 'Poipole',
        9341588: 'Naganadel',
        3487284: 'Stakataka',
        7434096: 'Blacephalon',
        2762518: 'Zeraora',
        2762269: 'Meltan',
        309201: 'Melmetal'
    }

    image_url = url

    resp = requests.get(image_url)
    img = Image.open(BytesIO(resp.content)).convert('RGB')
    val = getIfromRGB([round(x) for x in Stat(img).mean])

    return allPokemon[val]
def find_duplicates(root_path: str):
    """Remove duplicate photos by substracting
    sum of all pixels for each band in the image.
    """
    # Prepare dict with ImageObjects
    photos = {}
    print("\nIndexing files...")
    files = listdir(root_path)
    t1 = tqdm(range(len(files)), unit=' img', file=stdout, desc='Progress')
    for filename in files:
        # Get files only with permitted extension
        err = []
        t1.update(1)
        t1.refresh()
        check_filename = filename.lower()
        if not check_filename.endswith(permitted_ext):
            continue
        else:
            try:
                img_path = path.join(root_path, filename).replace('\\', '/')
                img = Image.open(img_path)
                photos[img_path] = sum(Stat(img)._getsum())
            except:
                err.append(filename)
                continue
    t1.close()
    if len(err) > 0:
        print(
            "\nFailed to index all files!\nFile list available in logs-indexing.txt"
        )
        with open('logs-indexing.txt', "w", encoding="utf-8") as f:
            for e in err:
                f.write(e + '\n')
    print("\nChecking files...")
    t2 = tqdm(range(len(photos)), unit=' img', desc='Progress', file=stdout)
    duplicates = []
    p = list(photos.keys())
    # O(n^2) algorithm
    for i in range(len(p)):
        for j in range(i + 1, len(p)):
            # Faster expression than difference method in ImageChops module
            try:
                img1 = photos[p[i]]
                diff = img1 - photos[p[j]]
                if diff == 0.0:
                    exists_tuple = [
                        i for i, x in enumerate(duplicates) if x[0] == img1
                    ]
                    if len(exists_tuple) == 0:
                        duplicates.append([img1, p[i], p[j]])
                    else:
                        if p[i] not in duplicates[exists_tuple[0]]:
                            duplicates[exists_tuple[0]].append(p[i])
                        if p[j] not in duplicates[exists_tuple[0]]:
                            duplicates[exists_tuple[0]].append(p[j])
                else:
                    continue
            except Exception as e:
                print(str(e))
        t2.update(1)
        t2.refresh()
    if len(duplicates) > 0:
        for duplicate in duplicates:
            duplicate.pop(0)
    t2.close()
    return duplicates