<jupyter_start><jupyter_text>minHash Image Clustering (MHIC) algorithm (Seed Generation Only)Implementation based on * [Large-Scale Discovery of Spatially Related Images](ieeexplore.ieee.org/iel5/34/4359286/05235143.pdf) by <NAME> and <NAME>* [Scalable Near Identical Image and Shot Detection - Microsoft](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/civr2007.pdf) by <NAME>, <NAME>, <NAME>, <NAME> PurposeIf we see a similar image cluster as a connected compoenent, images are vertex. We have to find edges to get image cluster. minHash can be used to find subset of the edges quickly. Afterward, you may use image retrieval system to complete the connected component.  Requirements* Visual words index list for each image<jupyter_code>%load_ext autoreload
%autoreload 2

from src import mhic_seed_generation

config_path='./oxf5k_extracted_13M_rootsift_1M_vocab_pqkmeans_1M_codebook_train/mhic_seed_gen.config'
config = mhic_seed_generation.read_config(config_path)
mhic_seed_generation.main(config)
import os
import pickle
from tqdm import tqdm
import numpy as np

similar_pairs = pickle.load(open(os.path.join(config["work_dir"], config["output_similar_pair_result"]), 'rb'))
ransac_result = pickle.load(open(os.path.join(config["work_dir"], config["output_ransac_result"]), 'rb'))

# with open(config["image_descriptor_dict_path"], 'rb') as f:
#     # key: image_name, value: 2d numpy array of shape (num_descriptor, dim_descriptor)
#     image_descriptor_dict = pickle.load(f)

# ransac_config = config

# def parallel_task(val):
#     image_names, score = val
#     np_keypoints, des1 = image_descriptor_dict[image_names[0]]
#     kp1 = mhic_seed_generation.convert_to_cv_keypoints(np_keypoints)
#     np_keypoints, des2 = image_descriptor_dict[image_names[1]]
#     kp2 = mhic_seed_generation.convert_to_cv_keypoints(np_keypoints)
    
#     inlier = mhic_seed_generation.get_ransac_inlier(kp1, kp2, des1, des2, False, ransac_config["ransac_match_method"], ransac_config["ransac_min_samples"], ransac_config["ransac_residual_threshold"], ransac_config["ransac_max_trials"])
#     num_inlier = len(inlier)
#     return (image_cluster, score, num_inlier)
            
            
# ransac_result = []
# # similar_pairs = list(filter(lambda x: filter_keep_similar_only(x[1], config["THRESHOLD_DATAMINING_SIMILARITY_MIN"], config["THRESHOLD_DATAMINING_SIMILARITY_MAX"]), similar_pairs))
# for pair in tqdm(similar_pairs):
#     result = parallel_task(pair)
#     if result is not None:
#         ransac_result.append(result)

# # ransac_result = pickle.load(open(os.path.join(config["work_dir"], config["output_ransac_result"]), 'rb'))
# print(ransac_result[:5])
# IMAGE_DIR = "./data/oxford5k_images"
IMAGE_DIR = "./data/oxford/oxford5k/images"
ransac_result.sort(key=lambda x: x[2], reverse=False)
for image_cluster, score, num_inlier in ransac_result[10:20]:
    print("pair: {}, score: {}, num_inlier: {}".format(image_cluster, score, num_inlier))
    # show_image_cluster(IMAGE_DIR, image_cluster)
    mhic_seed_generation.show_image_pair_ransac(config, image_cluster)
    print() 
import random
def show_image_cluster(image_dir, image_names):
    """
    show image cluster for oxford 5k dataset
    """
    # Visualize images assigned to this cluster    
    from PIL import Image
    import matplotlib.pyplot as plt
    
    imgs = []    
    for image_name in image_names:
        image_name = image_name.replace("oxc1_", "") + ".jpg"
        image_path = os.path.join(image_dir, image_name)
        img = Image.open(image_path)
        imgs.append(img)            
        
    cols = 5
    imgs = imgs[:cols]
    plt.figure(figsize=(20, 5))
    for i, img in enumerate(imgs):
        plt.subplot(1, cols, i + 1)
        plt.imshow(img)
    plt.show()

    
# IMAGE_DIR = "./data/oxford5k_images"
IMAGE_DIR = "./data/oxford/oxford5k/images"
ransac_result.sort(key= lambda x: x[2], reverse=True)
for image_cluster, score, inlier in ransac_result:
    print("pair: {}, score: {}, inlier: {}".format(image_cluster, score, inlier))
    show_image_cluster(IMAGE_DIR, image_cluster)
    print('\n')    
    
    
# # IMAGE_DIR = "./data/oxford5k_images"
# IMAGE_DIR = "./data/oxford/oxford5k/images"
# sample_count = 10
# print("Sampling from irrelevant images.")
# target_seq = similar_pairs[:count_irr]
# k = min(sample_count, len(target_seq))
# for image_cluster, score in random.sample(target_seq, k):
#     print("pair: {}, score: {}".format(image_cluster, score))
#     show_image_cluster(IMAGE_DIR, image_cluster)
#     print('\n')    
    

print("Sampling from similar images.")
target_seq = similar_pairs[count_irr:count_irr+count_sim]
k = min(sample_count, len(target_seq))
target_seq.sort(key=lambda x: x[1], reverse=True)
for image_cluster, score in target_seq:
    print("pair: {}, score: {}".format(image_cluster, score))
    show_image_cluster(IMAGE_DIR, image_cluster)
    print('\n')    
    
print("Sampling from near-duplicates images.")
target_seq = similar_pairs[count_irr+count_sim:]
target_seq.sort(key=lambda x: x[1], reverse=True)
k = min(sample_count, len(target_seq))
for image_cluster, score in random.sample(target_seq, k):
    print("pair: {}, score: {}".format(image_cluster, score))
    show_image_cluster(IMAGE_DIR, image_cluster)
    print('\n')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12280044926993636, 'fraction_numerical': 0.013290902283788843, 'mean_word_length': 4.916943521594685, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '133144', 'license': 'MIT', 'n_tokens_mistral': 1945, 'n_tokens_neox': 1838, 'n_words': 378, 'path': 'minHash Image Clustering (MHIC) algorithm (Seed Generation Only).ipynb', 'repo_name': 'insikk/bow_image_retrieval', 'size': '5380'}