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] } }
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
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)
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
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
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
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)
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)))]
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]
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
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
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)
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
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}')
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)))
def stats(image): """ Obtain basic image statics; mean of pixel values and total number of pixels """ stat = Stat(image) return stat.mean, stat.count
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