{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91498,"databundleVersionId":11655853,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Импорт библиотек\nimport numpy as np\nimport pandas as pd\nimport os\nimport cv2\nimport matplotlib.pyplot as plt\nfrom sklearn.cluster import DBSCAN\n\n# Проверка содержимого директории\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Пути к данным\ndata_dir = '/kaggle/input/image-matching-challenge-2025/'\ntrain_dir = os.path.join(data_dir, 'train')\ntest_dir = os.path.join(data_dir, 'test')\nsubmission_file = os.path.join(data_dir, 'sample_submission.csv')\n\n# Содержимое на sample_submission.csv\nprint(\"\\nСодержимое sample_submission.csv:\")\nsample_submission = pd.read_csv(submission_file)\nprint(sample_submission.head())\n\n# Класс для загрузки изображений\nclass ImageDataset:\n    def __init__(self, img_dir, img_size=(640, 480)):\n        self.img_paths = []\n        for root, _, files in os.walk(img_dir):\n            for f in files:\n                if f.endswith(('.jpg', '.png')):\n                    self.img_paths.append(os.path.join(root, f))\n        self.img_size = img_size\n\n    def __len__(self):\n        return len(self.img_paths)\n\n    def __getitem__(self, idx):\n        img = cv2.imread(self.img_paths[idx], cv2.IMREAD_GRAYSCALE)\n        img = cv2.resize(img, self.img_size)\n        return img, self.img_paths[idx]\n\n# Функция для извлечения признаков и сопоставления с SIFT\ndef match_images_sift(img1_path, img2_path):\n    sift = cv2.SIFT_create()\n    \n    img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)\n    img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)\n    \n    kp1, desc1 = sift.detectAndCompute(img1, None)\n    kp2, desc2 = sift.detectAndCompute(img2, None)\n    \n    if desc1 is None or desc2 is None:\n        return np.array([]), np.array([])\n    \n    bf = cv2.BFMatcher()\n    matches = bf.knnMatch(desc1, desc2, k=2)\n    \n    # Применяем тест отношения Лоу\n    good = [m for m, n in matches if m.distance < 0.75 * n.distance]\n    mkpts0 = np.array([kp1[m.queryIdx].pt for m in good])\n    mkpts1 = np.array([kp2[m.trainIdx].pt for m in good])\n    \n    return mkpts0, mkpts1\n\n# Функция для вычисления фундаментальной матрицы\ndef compute_fundamental_matrix(mkpts0, mkpts1):\n    if len(mkpts0) < 8:  # Минимум 8 точек для RANSAC\n        return None\n    F, mask = cv2.findFundamentalMat(mkpts0, mkpts1, cv2.FM_RANSAC)\n    return F\n\n# Подготовка тестовых данных\ntest_dataset = ImageDataset(test_dir)\n\n# Извлечение дескрипторов для кластеризации (упрощённо)\nsift = cv2.SIFT_create()\ndescriptors = []\nimg_paths = []\nfor idx in range(len(test_dataset)):\n    img, path = test_dataset[idx]\n    _, desc = sift.detectAndCompute(img, None)\n    if desc is not None:\n        desc_mean = desc.mean(axis=0)  # Усредняем дескрипторы\n        descriptors.append(desc_mean)\n        img_paths.append(path)\n    else:\n        descriptors.append(np.zeros(128))  # Заглушка для пустых дескрипторов\ndescriptors = np.array(descriptors)\n\n# Кластеризация с DBSCAN\ndbscan = DBSCAN(eps=0.5, min_samples=2, metric='euclidean')\nclusters = dbscan.fit_predict(descriptors)\n\n# Группировка изображений по кластерам\ncluster_dict = {}\nfor idx, cluster_id in enumerate(clusters):\n    if cluster_id != -1:  # Игнорируем шум (-1)\n        if cluster_id not in cluster_dict:\n            cluster_dict[cluster_id] = []\n        cluster_dict[cluster_id].append(img_paths[idx])\n\n# Обработка парного соответствия внутри кластеров\nmatches_dict = {}\nfor cluster_id, img_list in cluster_dict.items():\n    for i in range(len(img_list)):\n        for j in range(i + 1, len(img_list)):\n            mkpts0, mkpts1 = match_images_sift(img_list[i], img_list[j])\n            F = compute_fundamental_matrix(mkpts0, mkpts1)\n            \n            if F is not None:\n                pair_key = f\"{os.path.basename(img_list[i])};{os.path.basename(img_list[j])}\"\n                matches_dict[pair_key] = F.flatten().tolist()\n\n# Создание submission.csv\nsubmission_data = []\nfor pair, F in matches_dict.items():\n    submission_data.append({\n        'image_pair': pair,\n        'fundamental_matrix': ' '.join(map(str, F))\n    })\n\nsubmission = pd.DataFrame(submission_data)\nsubmission.to_csv('/kaggle/working/submission.csv', index=False)\nprint(\"Файл submission.csv успешно создан!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T05:40:46.037759Z","iopub.execute_input":"2025-04-05T05:40:46.038128Z","iopub.status.idle":"2025-04-05T05:40:58.668265Z","shell.execute_reply.started":"2025-04-05T05:40:46.038100Z","shell.execute_reply":"2025-04-05T05:40:58.667146Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}