{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":71885,"databundleVersionId":8143495,"sourceType":"competition"},{"sourceId":7884485,"sourceType":"datasetVersion","datasetId":4628051},{"sourceId":7884725,"sourceType":"datasetVersion","datasetId":4628331},{"sourceId":172469456,"sourceType":"kernelVersion"},{"sourceId":173217852,"sourceType":"kernelVersion"},{"sourceId":4534,"sourceType":"modelInstanceVersion","modelInstanceId":3326},{"sourceId":17191,"sourceType":"modelInstanceVersion","modelInstanceId":14317},{"sourceId":17555,"sourceType":"modelInstanceVersion","modelInstanceId":14611}],"dockerImageVersionId":30683,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# SETUP","metadata":{}},{"cell_type":"code","source":"from imc24 import *","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-05-28T23:47:04.265019Z","iopub.execute_input":"2024-05-28T23:47:04.266062Z","iopub.status.idle":"2024-05-28T23:47:04.270614Z","shell.execute_reply.started":"2024-05-28T23:47:04.266025Z","shell.execute_reply":"2024-05-28T23:47:04.269470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# SIMILLIAR PAIRS","metadata":{}},{"cell_type":"code","source":"def get_pairs(images_list,device=DEVICE):\n    if EXHAUSTIVE:\n        return list(combinations(range(len(images_list)), 2)) \n    \n    processor = AutoImageProcessor.from_pretrained('/kaggle/input/dinov2/pytorch/base/1/')\n    model = AutoModel.from_pretrained('/kaggle/input/dinov2/pytorch/base/1/').eval().to(DEVICE)\n    embeddings = []\n    \n    for img_path in images_list:\n        image = K.io.load_image(img_path, K.io.ImageLoadType.RGB32, device=DEVICE)[None, ...]\n        with torch.inference_mode():\n            inputs = processor(images=image, return_tensors=\"pt\", do_rescale=False ,do_resize=True, \n                               do_center_crop=True, size=224).to(DEVICE)\n            outputs = model(**inputs)\n            embedding = F.normalize(outputs.last_hidden_state.max(dim=1)[0])\n        embeddings.append(embedding)\n        \n    embeddings = torch.cat(embeddings, dim=0)\n    distances = torch.cdist(embeddings,embeddings).cpu()\n    distances_ = (distances <= DISTANCES_THRESHOLD).numpy()\n    np.fill_diagonal(distances_,False)\n    z = distances_.sum(axis=1)\n    idxs0 = np.where(z == 0)[0]\n    for idx0 in idxs0:\n        t = np.argsort(distances[idx0])[1:MIN_PAIRS]\n        distances_[idx0,t] = True\n        \n    s = np.where(distances >= TOLERANCE)\n    distances_[s] = False\n    \n    idxs = []\n    for i in range(len(images_list)):\n        for j in range(len(images_list)):\n            if distances_[i][j]:\n                idxs += [(i,j)] if i<j else [(j,i)]\n    \n    idxs = list(set(idxs))\n    return idxs","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:04.272603Z","iopub.execute_input":"2024-05-28T23:47:04.272946Z","iopub.status.idle":"2024-05-28T23:47:04.286881Z","shell.execute_reply.started":"2024-05-28T23:47:04.272920Z","shell.execute_reply":"2024-05-28T23:47:04.285843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# KEYPOINTS EXTRACTOR AND MATCHER","metadata":{}},{"cell_type":"code","source":"from IPython.display import clear_output\n\n!pip install -r /kaggle/input/check-image-orientation/requirements.txt\n!pip install --no-index /kaggle/input/imc2024-packages-lightglue-rerun-kornia/* --no-deps\n!mkdir -p /root/.cache/torch/hub/checkpoints\n!cp /kaggle/input/aliked/pytorch/aliked-n16/1/* /root/.cache/torch/hub/checkpoints/\n!cp /kaggle/input/lightglue/pytorch/aliked/1/* /root/.cache/torch/hub/checkpoints/\n!cp /kaggle/input/lightglue/pytorch/aliked/1/aliked_lightglue.pth /root/.cache/torch/hub/checkpoints/aliked_lightglue_v0-1_arxiv-pth\n!cp /kaggle/input/check-image-orientation/2020-11-16_resnext50_32x4d.zip /root/.cache/torch/hub/checkpoints/\n\nclear_output(wait=False)","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:04.288422Z","iopub.execute_input":"2024-05-28T23:47:04.288812Z","iopub.status.idle":"2024-05-28T23:47:47.179004Z","shell.execute_reply.started":"2024-05-28T23:47:04.288782Z","shell.execute_reply":"2024-05-28T23:47:47.177861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from lightglue.utils import rbd, batch_to_device\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:47.180682Z","iopub.execute_input":"2024-05-28T23:47:47.181003Z","iopub.status.idle":"2024-05-28T23:47:47.186267Z","shell.execute_reply.started":"2024-05-28T23:47:47.180976Z","shell.execute_reply":"2024-05-28T23:47:47.185074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calculate_bounding_box(kpts, top_k=50):\n    # Convert keypoints to numpy array\n    kpts_np = kpts.detach().cpu().numpy()\n    \n    # Calculate top_k largest values for x and y coordinates\n    x_coords = kpts_np[:, 0]\n    y_coords = kpts_np[:, 1]\n    \n    # Sort and take the top_k values\n    top_k_x = np.sort(x_coords)[-top_k:]\n    top_k_y = np.sort(y_coords)[-top_k:]\n    #print(top_k_x)\n    # Calculate the mean of the top_k largest values\n    avg_x_max = top_k_x.mean()\n    avg_y_max = top_k_y.mean()\n    \n    # Sort and take the bottom_k values\n    bottom_k_x = np.sort(x_coords)[:top_k]\n    bottom_k_y = np.sort(y_coords)[:top_k]\n    #print(bottom_k_x)\n    # Calculate the mean of the bottom_k smallest values\n    avg_x_min = bottom_k_x.mean()\n    avg_y_min = bottom_k_y.mean()\n    \n    # Define the bounding box using the average values\n    left = int(avg_x_min)\n    top = int(avg_y_min)\n    width = int(avg_x_max - avg_x_min)\n    height = int(avg_y_max - avg_y_min)\n    \n    return top, left, height, width","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:47.189647Z","iopub.execute_input":"2024-05-28T23:47:47.190035Z","iopub.status.idle":"2024-05-28T23:47:47.842056Z","shell.execute_reply.started":"2024-05-28T23:47:47.190000Z","shell.execute_reply":"2024-05-28T23:47:47.841129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def overlap_detection_fixed(extractor, matcher, desc1, desc2, kp1, kp2, image0, image1, min_matches): # Passar o processo de achar os kps e desc para dentro e deixar so as imagens como parametros\n    with torch.inference_mode():\n        _, matches01 = matcher(desc1, desc2, KF.laf_from_center_scale_ori(kp1[None]), KF.laf_from_center_scale_ori(kp2[None]))\n    #data = [kp1, kp2, matches01]\n    # remove batch dim and move to target device\n    #kp1, kp2, matches01 = [batch_to_device(rbd(x), device) for x in data]\n    if len(matches01) < min_matches:\n        return matches01\n    kpts0, kpts1, matches = kp1, kp2, matches01\n    m_kpts0, m_kpts1 = kpts0[matches[..., 0]], kpts1[matches[..., 1]]\n    top0, left0, height0, width0 = calculate_bounding_box(m_kpts0)\n    top1, left1, height1, width1 = calculate_bounding_box(m_kpts1)\n    crop_box0 = (top0, left0, height0, width0) \n    crop_box1 = (top1, left1, height1, width1)\n    cropped_img_tensor0 = TF.crop(image0, *crop_box0)\n    cropped_img_tensor1 = TF.crop(image1, *crop_box1)\n    print(type(cropped_img_tensor0))\n    if(cropped_img_tensor0.numel()==0 or cropped_img_tensor1.numel() == 0):\n        return matches # Problema nas imagens que nao preve que da 0s e 1s <<<<<<<<<<<<<<<<<<<< Tirar talvez ? try resolve.\n    \n    # Comparar os shape[1] e [2] e encontrar os maiores\n    # Ou transforma a cropped img para jpg de novo ou para numpy,cv2.resize() para os maiores, checar o teorema da amostragem do resize do openCV nos croppeds, imwrite nos croppeds e load_image, mas testar sem load_image, apenas permutando.\n    # Ver esse erro de acordo com oq eduardo falou\n    print(\"Imagem_0_C: \", cropped_img_tensor0.shape[2], \"Largura \", cropped_img_tensor0.shape[1], \"Altura\") \n    print(\"Imagem_1_C: \", cropped_img_tensor1.shape[2], \"Largura \", cropped_img_tensor1.shape[1], \"Altura\") \n    \n    img0_n = \"img0.jpg\"\n    img1_n = \"img1.jpg\"\n    \n    #cv2.imwrite(\"imagem0_teste\", image0.permute(1,2,0).cpu().numpy())\n    #cv2.imwrite(img0_n, cropped_img_tensor0.permute(1,2,0).cpu().numpy())\n    #cv2.imwrite(img1_n, cropped_img_tensor1.permute(1,2,0).cpu().numpy())\n    #pdb.set_trace()\n    \n    #fig, ax = plt.subplots(3, figsize=(8,6))\n    #ax[0].imshow(image0.permute(1,2,0).cpu().numpy())\n    #ax[1].imshow(cropped_img_tensor0.permute(1,2,0).cpu().numpy())\n    #ax[2].imshow(cropped_img_tensor1.permute(1,2,0).cpu().numpy())\n    #plt.show()\n    #print(cropped_img_tensor0.shape)\n    #pdb.set_trace()\n    # width e height\n    if cropped_img_tensor0.shape[2] >= cropped_img_tensor1.shape[2] and cropped_img_tensor0.shape[1] >= cropped_img_tensor1.shape[1]:\n        w_new = cropped_img_tensor0.shape[2]\n        h_new = cropped_img_tensor0.shape[1]\n        \n        cropped_img_tensor1 = cv2.resize(cropped_img_tensor1.permute(1,2,0).cpu().numpy(), (w_new, h_new), interpolation = cv2.INTER_CUBIC)\n        # Retorna a tensor\n        cropped_img_tensor1 = torch.Tensor(cropped_img_tensor1).permute(2,0,1).cuda()\n    elif cropped_img_tensor0.shape[2] <= cropped_img_tensor1.shape[2] and cropped_img_tensor0.shape[1] >= cropped_img_tensor1.shape[1]:\n        w_new = cropped_img_tensor1.shape[2]\n        h_new = cropped_img_tensor0.shape[1]\n        \n        #cropped_img_tensor0 = cv2.imread(img0_n)\n        #cropped_img_tensor0 = cv2.imread(img1_n)\n        # Width (0)\n        cropped_img_tensor0 = cv2.resize(cropped_img_tensor0.permute(1,2,0).cpu().numpy(), (w_new, cropped_img_tensor0.shape[1]), interpolation = cv2.INTER_CUBIC)\n        # Height (1)\n        cropped_img_tensor1 = cv2.resize(cropped_img_tensor1.permute(1,2,0).cpu().numpy(), (cropped_img_tensor1.shape[2], h_new), interpolation = cv2.INTER_CUBIC)\n        # Retorna a tensor\n        \n        #fig, ax = plt.subplots(2, figsize=(8,6))\n        #ax[0].imshow(cropped_img_tensor0)  #.permute(1,2,0).cpu())\n        #ax[1].imshow(cropped_img_tensor1)  #.permute(1,2,0).cpu())\n        #plt.show()\n        \n        #cv2.imwrite(img0_n, cropped_img_tensor0)\n        #cv2.imwrite(img1_n, cropped_img_tensor1)\n        \n        #cropped_img_tensor0 = load_image(img0_n).to(DEVICE) \n        #cropped_img_tensor1 = load_image(img1_n).to(DEVICE) \n        \n        cropped_img_tensor0 = torch.Tensor(cropped_img_tensor0).permute(2,0,1).cuda()\n        cropped_img_tensor1 = torch.Tensor(cropped_img_tensor1).permute(2,0,1).cuda()\n    elif cropped_img_tensor0.shape[2] >= cropped_img_tensor1.shape[2] and cropped_img_tensor0.shape[1] <= cropped_img_tensor1.shape[1]:\n        w_new = cropped_img_tensor0.shape[2]\n        h_new = cropped_img_tensor1.shape[1]  \n        \n        # Width (0)\n        cropped_img_tensor0 = cv2.resize(cropped_img_tensor0.permute(1,2,0).cpu().numpy(), (cropped_img_tensor0.shape[2], h_new), interpolation = cv2.INTER_CUBIC)\n        # Height (1)\n        cropped_img_tensor1 = cv2.resize(cropped_img_tensor1.permute(1,2,0).cpu().numpy(), (w_new, cropped_img_tensor1.shape[1]), interpolation = cv2.INTER_CUBIC)\n        # Retorna a tensor\n        #print(type(cropped_img_tensor0))\n        #print(cropped_img_tensor0.shape)\n        cropped_img_tensor0 = torch.Tensor(cropped_img_tensor0).permute(2,0,1).cuda()\n        cropped_img_tensor1 = torch.Tensor(cropped_img_tensor1).permute(2,0,1).cuda()\n    else:\n        w_new = cropped_img_tensor1.shape[2]\n        h_new = cropped_img_tensor1.shape[1]\n        \n        cropped_img_tensor0 = cv2.resize(cropped_img_tensor0.permute(1,2,0).cpu().numpy(), (w_new, h_new), interpolation = cv2.INTER_CUBIC)\n        # Retorna a tensor\n        cropped_img_tensor0 = torch.Tensor(cropped_img_tensor0).permute(2,0,1).cuda()\n    \n    print(f'Larguras: {cropped_img_tensor0.shape[2]}, {cropped_img_tensor1.shape[2]} e Alturas: {cropped_img_tensor0.shape[1]}, {cropped_img_tensor1.shape[1]}')\n    #pdb.set_trace()\n    extractor_overlap = ALIKED(max_num_keypoints=MAX_NUM_KEYPOINTS_OVERLAP,detection_threshold=DETECTION_THRESHOLD_OVERLAP,resize=RESIZE_TO_OVERLAP).eval().to(DEVICE)\n    feats0_c = extractor_overlap.extract(cropped_img_tensor0)#.permute(2,0,1))\n    feats1_c = extractor_overlap.extract(cropped_img_tensor1)#.permute(2,0,1))\n    kp1_c = feats0_c[\"keypoints\"].squeeze()#cpu().numpy()\n    kp2_c = feats1_c[\"keypoints\"].squeeze()#cpu().numpy()\n    desc1_c = feats0_c[\"descriptors\"].squeeze()#.detach().cpu().numpy()\n    desc2_c = feats1_c[\"descriptors\"].squeeze()#.detach().cpu().numpy()\n    \n    print(desc1_c.shape)\n    print(desc2_c.shape)\n    print(KF.laf_from_center_scale_ori(kp1_c[None]).shape)\n    print(KF.laf_from_center_scale_ori(kp2_c[None]).shape)\n    \n    # Problema quando muda o shape, tem que ver visualmente. <<<<<<<<<<<<<<<<<<<<<, solução provisoria, evitar os shapes diferentes no matcher_c usando TRY EXCEPT\n    with torch.inference_mode():\n        _, matches01_c = matcher(desc1_c, desc2_c, KF.laf_from_center_scale_ori(kp1_c[None]), KF.laf_from_center_scale_ori(kp2_c[None]))\n    \n    kp1_c[...,0] += left0\n    kp1_c[...,1] += top0\n    kp2_c[...,0] += left1  # Pq soma aqui e oq é isso n no torch.cat >vscode or plot <<<<<<<<<<\n    kp2_c[...,1] += top1  \n    m_kpts0_c, m_kpts1_c = kp1_c[matches01_c[..., 0]], kp2_c[matches01_c[..., 1]] # match kpoints com overlap, sao igauis ?\n    matches_ = torch.cat([matches,matches01_c],axis=0) # pq + matches01_c + len(kpts0.squeeze(), ajusta indices ?\n    kpts0_ = torch.cat([kpts0.squeeze(),kp1_c.squeeze()],axis=0) # Resultante normal + overlap keypoints\n    kpts1_ = torch.cat([kpts1.squeeze(),kp2_c.squeeze()],axis=0) # Resultante normal + overlap keypoints\n    m_kpts0_, m_kpts1_ = kpts0_.squeeze()[matches_[..., 0]], kpts1_.squeeze()[matches_[..., 1]] # Resultante normal + overlap keypoints match\n    \n    # Print\n    #fig, ax = plt.subplots(5, 2, figsize=(10, 8))\n    # Matches sem overlap\n    #ax[0][0].imshow(image0.permute(1,2,0).cpu())\n    #ax[0][0].scatter(kpts0.squeeze()[:, 0].cpu(), kpts0.squeeze()[:, 1].cpu(), s=0.5, c=\"red\")\n    #ax[0][0].scatter(m_kpts0[:, 0].cpu(), m_kpts0[:, 1].cpu(), s=0.5, c=\"blue\")\n    #ax[0][1].imshow(image1.permute(1,2,0).cpu())\n    #ax[0][1].scatter(kpts1.squeeze()[:, 0].cpu(), kpts1.squeeze()[:, 1].cpu(), s=0.5, c=\"red\")\n    #ax[0][1].scatter(m_kpts1[:, 0].cpu(), m_kpts1[:, 1].cpu(), s=0.5, c=\"blue\")\n\n    # Matches com overlap\n    #ax[1][0].imshow(image0.permute(1,2,0).cpu())\n    #ax[1][0].scatter(kp1_c.squeeze()[:, 0].cpu(), kp1_c.squeeze()[:, 1].cpu(), s=0.5, c=\"red\")\n    #ax[1][0].scatter(m_kpts0_c[:, 0].cpu(), m_kpts0_c[:, 1].cpu(), s=0.5, c=\"blue\")\n    #ax[1][1].imshow(image1.permute(1,2,0).cpu())\n    #ax[1][1].scatter(kp2_c.squeeze()[:, 0].cpu(), kp2_c.squeeze()[:, 1].cpu(), s=0.5, c=\"red\")\n    #ax[1][1].scatter(m_kpts1_c[:, 0].cpu(), m_kpts1_c[:, 1].cpu(), s=0.5, c=\"blue\")\n\n    # Soma dos dois matches\n    #ax[2][0].imshow(image0.permute(1,2,0).cpu())\n    #ax[2][0].scatter(kpts0_.squeeze()[:, 0].cpu(), kpts0_.squeeze()[:, 1].cpu(), s=0.5, c=\"red\")\n    #ax[2][0].scatter(m_kpts0_[:, 0].cpu(), m_kpts0_[:, 1].cpu(), s=0.5, c=\"blue\")\n    #ax[2][1].imshow(image1.permute(1,2,0).cpu())\n    #ax[2][1].scatter(kpts1_.squeeze()[:, 0].cpu(), kpts1_.squeeze()[:, 1].cpu(), s=0.5, c=\"red\")\n    #ax[2][1].scatter(m_kpts1_[:, 0].cpu(), m_kpts1_[:, 1].cpu(), s=0.5, c=\"blue\")\n\n    # Images\n    #ax[3][0].imshow(image0.permute(1,2,0).cpu())\n    #ax[3][1].imshow(image1.permute(1,2,0).cpu())\n    #ax[4][0].imshow(cropped_img_tensor0.permute(1,2,0).cpu())\n    #ax[4][1].imshow(cropped_img_tensor1.permute(1,2,0).cpu())\n\n    #ax[0][0].axis('off')\n    #ax[0][1].axis('off')\n    #ax[1][0].axis('off')\n    #ax[1][1].axis('off')\n    #plt.tight_layout()\n    #plt.show()\n    \n    #print(f'Original Matches: {len(matches)}')\n    #print(f'Matches After Overlap Detection: {len(matches01_c)}')\n    #print(f'Matches combined: {len(matches) + len(matches01_c)}')\n    #pdb.set_trace()\n     \n    unique_tensor = torch.unique(matches_, dim=0, sorted=True) # Reorganiza os valores do tensor, mas sao os mesmos\n    ######## Checar as tuplas iguais --------------------------\n    #print(\"MATCHES_\")\n    #pair_counts1 = {}\n\n    # Percorrer o tensor e contar pares repetidos\n    #for pair in matches_:\n    #    pair_tuple = tuple(pair.tolist())\n    #    if pair_tuple in pair_counts1:\n    #        pair_counts1[pair_tuple] += 1\n    #    else:\n    #        pair_counts1[pair_tuple] = 1\n\n    # Imprimir pares repetidos e suas contagens -\n    #for pair, count in pair_counts1.items():\n    #    if count > 1:\n    #        print(f\"Par {pair} se repete {count} vezes\")\n    #        pdb.set_trace()\n            \n    # Dicionário para armazenar pares e suas contagens\n    #print(\"UNIQUE\")\n    #pair_counts2 = {}\n\n    ######## Percorrer o tensor e contar pares repetidos\n    #for pair in unique_tensor:\n    #    pair_tuple = tuple(pair.tolist())\n    #    if pair_tuple in pair_counts2:\n    #        pair_counts2[pair_tuple] += 1\n    #    else:\n    #        pair_counts2[pair_tuple] = 1\n\n    # Imprimir pares repetidos e suas contagens\n    #for pair, count in pair_counts2.items():\n    #    if count > 1:\n    #        print(f\"Par {pair} se repete {count} vezes\")\n    #        pdb.set_trace()\n    # -------------------------------------------------------------------------------\n    \n    #if len(matches01_c) >= MIN_MATCHES_OVERLAP:\n    return unique_tensor\n    \n    #return matches","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:47.843729Z","iopub.execute_input":"2024-05-28T23:47:47.844083Z","iopub.status.idle":"2024-05-28T23:47:47.880316Z","shell.execute_reply.started":"2024-05-28T23:47:47.844036Z","shell.execute_reply":"2024-05-28T23:47:47.879479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def keypoints_matches(images_list,pairs):\n    extractor = ALIKED(max_num_keypoints=MAX_NUM_KEYPOINTS,detection_threshold=DETECTION_THRESHOLD,resize=RESIZE_TO).eval().to(DEVICE)\n    matcher = KF.LightGlueMatcher(\"aliked\", {'width_confidence':-1, 'depth_confidence':-1, 'mp':True if 'cuda' in str(DEVICE) else False}).eval().to(DEVICE)\n    #pdb.set_trace()\n    rotation = create_model(\"swsl_resnext50_32x4d\").eval().to(DEVICE) # Relacionado a rotação da imagem\n    \n    with h5py.File(\"keypoints.h5\", mode=\"w\") as f_kp, h5py.File(\"descriptors.h5\", mode=\"w\") as f_desc:  \n        for image_path in images_list:\n            with torch.inference_mode():\n                image = load_image(image_path).to(DEVICE)\n                feats = extractor.extract(image)\n                #pdb.set_trace()\n                f_kp[image_path.name] = feats[\"keypoints\"].squeeze().cpu().numpy()\n                f_desc[image_path.name] = feats[\"descriptors\"].squeeze().detach().cpu().numpy()\n                \n    with h5py.File(\"keypoints.h5\", mode=\"r\") as f_kp, h5py.File(\"descriptors.h5\", mode=\"r\") as f_desc, \\\n         h5py.File(\"matches.h5\", mode=\"w\") as f_matches:  \n        for pair in pairs:\n            key1, key2 = images_list[pair[0]].name, images_list[pair[1]].name\n            kp1 = torch.from_numpy(f_kp[key1][...]).to(DEVICE)\n            kp2 = torch.from_numpy(f_kp[key2][...]).to(DEVICE) # keypoints das imagens\n            desc1 = torch.from_numpy(f_desc[key1][...]).to(DEVICE) # descriptors das imagens\n            desc2 = torch.from_numpy(f_desc[key2][...]).to(DEVICE)\n            \n            image0 = load_image(images_list[pair[0]]).to(DEVICE)\n            image1 = load_image(images_list[pair[1]]).to(DEVICE)\n            print(\"Imagem_0: \",image0.shape[2], \"Largura \", image0.shape[1], \"Altura\") \n            print(\"Imagem_1: \",image1.shape[2], \"Largura \", image1.shape[1], \"Altura\") \n            #print(images_list[pair[0]])\n            #print(images_list[pair[1]])\n            try:\n                matches_ = overlap_detection_fixed(extractor, matcher, desc1, desc2, kp1, kp2, image0, image1, 100)\n                #_, matches_ = matcher(desc1, desc2, KF.laf_from_center_scale_ori(kp1[None]), KF.laf_from_center_scale_ori(kp2[None])) # N da pra usa match pair por causa que o KF.LightGlue do kornia n funciona com match_pair do lightglue pq os inputs sao diferentes\n                #pdb.set_trace()\n            except Exception as e:\n                print(f\"Error: {e}\")\n                #pdb.set_trace()\n                with torch.inference_mode():\n                    _, matches_ = matcher(desc1, desc2, KF.laf_from_center_scale_ori(kp1[None]), KF.laf_from_center_scale_ori(kp2[None])) # N da pra usa match pair por causa que o KF.LightGlue do kornia n funciona com match_pair do lightglue pq os inputs sao diferentes\n            # aqui vem os matchs em valores (0,0,0,1,1,etc), antigo idxs\n            if len(matches_): group = f_matches.require_group(key1) # Problema vem quando passa pro group o tensor concatenado\n            if len(matches_) >= MIN_MATCHES: group.create_dataset(key2, data=matches_.detach().cpu().numpy() ) \n            #print(\"Adding to the matches.h5\")\n        #pdb.set_trace()","metadata":{"execution":{"iopub.status.busy":"2024-05-29T00:50:58.826557Z","iopub.execute_input":"2024-05-29T00:50:58.826977Z","iopub.status.idle":"2024-05-29T00:50:58.843084Z","shell.execute_reply.started":"2024-05-29T00:50:58.826943Z","shell.execute_reply":"2024-05-29T00:50:58.842012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Debug > Group\n#f = h5py.File('matches.h5', 'r') \n#print(list(f.keys()))\n#dset = f['12.png']\n#a,b,c = dset.items()\n#print(a, b, c) # A priori, tem uma imagem, eu entro nela (dset) e tem outras imagens com as infos sobre ela (keypoints ou descriptor ou os dois?)\n\n#dset['1']\n#len(f.keys()","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:47.899356Z","iopub.execute_input":"2024-05-28T23:47:47.899621Z","iopub.status.idle":"2024-05-28T23:47:47.911864Z","shell.execute_reply.started":"2024-05-28T23:47:47.899598Z","shell.execute_reply":"2024-05-28T23:47:47.911031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# RANSAC AND SPARSE RECONSTRUCTION","metadata":{}},{"cell_type":"code","source":"def ransac_and_sparse_reconstruction(images_path):\n    #pdb.set_trace()\n    now = datetime.datetime.now()\n    time_str = now.strftime(\"%Y-%m-%d_%H-%M-%S\")\n    db_name = f'colmap_{time_str}.db'\n    db = COLMAPDatabase.connect(db_name)\n    db.create_tables()\n    fname_to_id = add_keypoints(db, '/kaggle/working/', images_path, '', 'simple-pinhole', False)\n    add_matches(db, '/kaggle/working/',fname_to_id) # Debugar isso aqui para ver pq os resultados sao iguais, fato é que o \"matches.h5\" é diferente, mas o mmA é igual.\n    db.commit()\n    \n    pycolmap.match_exhaustive(db_name, sift_options={'num_threads':1})\n    maps = pycolmap.incremental_mapping(\n        database_path=db_name, \n        image_path=images_path,\n        output_path='/kaggle/working/', \n        options=pycolmap.IncrementalPipelineOptions({'min_model_size':MIN_MODEL_SIZE, 'max_num_models':MAX_NUM_MODELS, 'num_threads':1})\n    )\n    return maps","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-05-28T23:47:47.912857Z","iopub.execute_input":"2024-05-28T23:47:47.913106Z","iopub.status.idle":"2024-05-28T23:47:47.922586Z","shell.execute_reply.started":"2024-05-28T23:47:47.913071Z","shell.execute_reply":"2024-05-28T23:47:47.921610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# HYPERPARAMETER TUNING","metadata":{}},{"cell_type":"code","source":"import pdb\n# SIMILLIAR PAIRS\nEXHAUSTIVE = True\nMIN_PAIRS = 50\nDISTANCES_THRESHOLD = 0.3\nTOLERANCE = 500\n\n# KEYPOINTS EXTRACTOR AND MATCHER\nMAX_NUM_KEYPOINTS = 4096\nRESIZE_TO = 1280\nDETECTION_THRESHOLD = 0.005\nMIN_MATCHES = 100\n\n# KEYPOINTS EXTRACTOR AND MATCHER (OVERLAP)\nMAX_NUM_KEYPOINTS_OVERLAP = 4096\nRESIZE_TO_OVERLAP = 1080\nDETECTION_THRESHOLD_OVERLAP = 0.005\nMIN_MATCHES_OVERLAP = 20\n\n# RANSAC AND SPARSE RECONSTRUCTION\nMIN_MODEL_SIZE = 5\nMAX_NUM_MODELS = 3\n\n# CROSS VALIDATION\nN_SAMPLES = 10  # 20\n\nSUBMISSION = True","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:47.923756Z","iopub.execute_input":"2024-05-28T23:47:47.924106Z","iopub.status.idle":"2024-05-28T23:47:47.935121Z","shell.execute_reply.started":"2024-05-28T23:47:47.924082Z","shell.execute_reply":"2024-05-28T23:47:47.934353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## CROSS VALIDATION","metadata":{}},{"cell_type":"code","source":"#!pip install torch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 ","metadata":{"execution":{"iopub.status.busy":"2024-05-28T23:47:47.936122Z","iopub.execute_input":"2024-05-28T23:47:47.936454Z","iopub.status.idle":"2024-05-28T23:47:47.945075Z","shell.execute_reply.started":"2024-05-28T23:47:47.936429Z","shell.execute_reply":"2024-05-28T23:47:47.944314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if not SUBMISSION:\n    import cv2\n    def image_path(row):\n        row['image_path'] = 'train/' + row['dataset'] + '/images/' + row['image_name']\n        return row\n\n    train_df = pd.read_csv(f'{IMC_PATH}/train/train_labels.csv')\n    train_df = train_df.apply(image_path,axis=1).drop_duplicates(subset=['image_path'])\n    G = train_df.groupby(['dataset','scene'])['image_path']\n    image_paths = []\n    \n    for g in G:\n        n = N_SAMPLES\n        n = n if n < len(g[1]) else len(g[1])\n        g = g[0],g[1].sample(n,random_state=42).reset_index(drop=True)\n        for image_path in g[1]:\n            image_paths.append(image_path)\n    #pdb.set_trace()    \n    gt_df = train_df[train_df.image_path.isin(image_paths)].reset_index(drop=True)\n    pred_df = gt_df[['image_path','dataset','scene','rotation_matrix','translation_vector']]\n    gt_df.to_csv('gt_df.csv',index=False)\n    pred_df.to_csv('pred_df.csv',index=False)\n    #pdb.set_trace()\n    os.environ[\"CUDA_LAUNCH_BLOCKING\"] = \"1\"\n    os.environ[\"TORCH_USE_CUDA_DSA\"] = \"1\"\n    run('pred_df.csv', get_pairs, keypoints_matches, ransac_and_sparse_reconstruction, submit=False) # Atualiza os valores ao final de cada dataset\n    pred_df = pd.read_csv('submission.csv')\n    mAA = round(score(gt_df, pred_df),4) # Debugar aqui dentro pra ver se ele da um sort (provavel)\n    print('*** Total mean Average Accuracy ***')\n    print(f\"mAA: {mAA}\")","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-05-29T00:30:01.440355Z","iopub.execute_input":"2024-05-29T00:30:01.441071Z","iopub.status.idle":"2024-05-29T00:43:46.256815Z","shell.execute_reply.started":"2024-05-29T00:30:01.441031Z","shell.execute_reply":"2024-05-29T00:43:46.255443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Media dos 20 valores para definir os limites da caixa, ajustar os parametros para cada dataset e diminuir a complexidade do matcher. Honestamente o que da pra fazer caso n der certo aqui e ir atras de como fazer, outros trabalhos, etc.\n\ne\n\n/usr/local/src/pytorch/aten/src/ATen/native/cuda/IndexKernel.cu:92: operator(): block: [15,0,0], thread: [34,0,0] Assertion `-sizes[i] <= index && index < sizes[i] && \"index out of bounds\"` failed.\n\nPointIDX nao existe e duplicatas >> mexer nos indexes, por isso soma o len dos keypoints >> solusao testar com 5 imagens bem poucas, rapida.","metadata":{}},{"cell_type":"markdown","source":"# SUBMISSION","metadata":{}},{"cell_type":"code","source":"# Dois tensores de exemplo\n#tensor1 = torch.tensor([[1, 2], [3, 4], [5, 6], [7, 8]], device='cuda')\n#tensor2 = torch.tensor([[3, 4], [5, 6], [9, 10], [11, 12]], device='cuda')\n\n# Concatenar os dois tensores\n#concatenated_tensor = torch.cat((tensor1, tensor2), dim=0)\n\n# Aplicar unique ao longo da dimensão 0 para encontrar os pares únicos\n#unique_tensor = torch.unique(concatenated_tensor, dim=0)\n\n\n#print(tensor1)\n#print(tensor2)\n#print(concatenated_tensor)\n#print(unique_tensor)\n\n# Dicionário para armazenar pares e suas contagens\n#pair_counts = {}\n\n# Percorrer o tensor e contar pares repetidos\n#for pair in concatenated_tensor:\n#    pair_tuple = tuple(pair.tolist())\n#    if pair_tuple in pair_counts:\n#        pair_counts[pair_tuple] += 1\n#    else:\n#        pair_counts[pair_tuple] = 1\n\n# Imprimir pares repetidos e suas contagens\n#for pair, count in pair_counts.items():\n#    if count > 1:\n#        print(f\"Par {pair} se repete {count} vezes\")","metadata":{"execution":{"iopub.status.busy":"2024-05-29T00:01:29.762853Z","iopub.execute_input":"2024-05-29T00:01:29.763541Z","iopub.status.idle":"2024-05-29T00:01:29.770831Z","shell.execute_reply.started":"2024-05-29T00:01:29.763482Z","shell.execute_reply":"2024-05-29T00:01:29.769811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if SUBMISSION:\n    import cv2\n    data_path = IMC_PATH + \"/sample_submission.csv\"\n    run(data_path, get_pairs, keypoints_matches, ransac_and_sparse_reconstruction)\n    \n# Otimizações\n# Resize para o menor valor das 2 (altura e largura), mas mantendo o image ratio (fx e fy)\n# Erros de duplicatas e pontos nao existindo\n# Mudar os parametros do extractor do overlap","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2024-05-29T00:01:29.772575Z","iopub.execute_input":"2024-05-29T00:01:29.773316Z","iopub.status.idle":"2024-05-29T00:01:29.785543Z","shell.execute_reply.started":"2024-05-29T00:01:29.773277Z","shell.execute_reply":"2024-05-29T00:01:29.784023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cat submission.csv","metadata":{"execution":{"iopub.status.busy":"2024-05-29T00:01:29.787338Z","iopub.execute_input":"2024-05-29T00:01:29.787767Z","iopub.status.idle":"2024-05-29T00:01:30.861499Z","shell.execute_reply.started":"2024-05-29T00:01:29.787722Z","shell.execute_reply":"2024-05-29T00:01:30.860450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Score\n#pred_df = pd.read_csv('submission.csv')\n#mAA = round(score(gt_df, pred_df),4) # Debugar aqui dentro pra ver se ele da um sort (provavel)\n\n#train_df = pd.read_csv(f'{IMC_PATH}/train/train_labels.csv')\n#train_df = train_df.apply(image_path,axis=1).drop_duplicates(subset=['image_path'])\n\n#print('*** Total mean Average Accuracy ***')\n#print(f\"mAA: {mAA}\")","metadata":{"execution":{"iopub.status.busy":"2024-05-29T00:01:30.863023Z","iopub.execute_input":"2024-05-29T00:01:30.863346Z","iopub.status.idle":"2024-05-29T00:01:30.868323Z","shell.execute_reply.started":"2024-05-29T00:01:30.863317Z","shell.execute_reply":"2024-05-29T00:01:30.867287Z"},"trusted":true},"execution_count":null,"outputs":[]}]}