{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31041,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# !pip install -q ultralytics\nprint(\"✅ \")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:13:19.790853Z","iopub.execute_input":"2025-06-01T16:13:19.791120Z","iopub.status.idle":"2025-06-01T16:14:35.804815Z","shell.execute_reply.started":"2025-06-01T16:13:19.791101Z","shell.execute_reply":"2025-06-01T16:14:35.803978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport random\nfrom tqdm.notebook import tqdm\nfrom ultralytics import YOLO\n\n\nprint(\"✅ \")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:14:44.430855Z","iopub.execute_input":"2025-06-01T16:14:44.431165Z","iopub.status.idle":"2025-06-01T16:14:47.603414Z","shell.execute_reply.started":"2025-06-01T16:14:44.431135Z","shell.execute_reply":"2025-06-01T16:14:47.602811Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # 预处理\n\n# import zipfile\n\n# # 定义解压目标目录（可自定义）\n# train_zip_path = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip'\n# test_zip_path = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip'\n\n# extract_dir = '/kaggle/working/'\n\n# # 解压 train.zip\n# with zipfile.ZipFile(train_zip_path, 'r') as zip_ref:\n#     zip_ref.extractall(extract_dir)\n\n# # 解压 test.zip\n# with zipfile.ZipFile(test_zip_path, 'r') as zip_ref:\n#     zip_ref.extractall(extract_dir)\n\n# print(\"✅ \")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:14:52.447952Z","iopub.execute_input":"2025-06-01T16:14:52.448343Z","iopub.status.idle":"2025-06-01T16:15:08.462257Z","shell.execute_reply.started":"2025-06-01T16:14:52.448319Z","shell.execute_reply":"2025-06-01T16:15:08.461490Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 设定参数\nimg_dir = \"/kaggle/working/train\"\nsave_dir = \"/kaggle/working/cropped_animals\"\nos.makedirs(save_dir, exist_ok=True)\nX = 1400          # 总共抽取的图像数\nCONF_THRES = 0.7  # 置信度阈值\n\nprint(\"✅ \")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:19:55.373304Z","iopub.execute_input":"2025-06-01T16:19:55.373913Z","iopub.status.idle":"2025-06-01T16:19:55.378332Z","shell.execute_reply.started":"2025-06-01T16:19:55.373888Z","shell.execute_reply":"2025-06-01T16:19:55.377675Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 加载官方预训练模型（支持猫狗检测）\nmodel = YOLO(\"yolov8n.pt\")  # 也可尝试 yolov8s.pt，n为nano，体积小速度快\n\nprint(\"✅ \")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:15:16.701942Z","iopub.execute_input":"2025-06-01T16:15:16.702228Z","iopub.status.idle":"2025-06-01T16:15:18.886054Z","shell.execute_reply.started":"2025-06-01T16:15:16.702207Z","shell.execute_reply":"2025-06-01T16:15:18.885551Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 加载所有图像路径\nall_imgs = [os.path.join(img_dir, f) for f in os.listdir(img_dir) if f.endswith('.jpg')]\nrandom.shuffle(all_imgs)\n\n# 分别抽取猫狗图片路径（按文件名判断）\ncat_imgs = [img for img in all_imgs if 'cat' in os.path.basename(img).lower()]\ndog_imgs = [img for img in all_imgs if 'dog' in os.path.basename(img).lower()]\n\n# 确保数据足够\ncat_count = X // 2\ndog_count = X - cat_count\n\nif len(cat_imgs) < cat_count or len(dog_imgs) < dog_count:\n    raise ValueError(\"猫或狗图片不足\")\n\n# 随机抽取不重复图片\nselected_imgs = random.sample(cat_imgs, cat_count) + random.sample(dog_imgs, dog_count)\nrandom.shuffle(selected_imgs)\nprint(f\"抽取图像总数：{len(selected_imgs)}（猫 {cat_count}，狗 {dog_count}）\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:19:57.594088Z","iopub.execute_input":"2025-06-01T16:19:57.594558Z","iopub.status.idle":"2025-06-01T16:19:57.664142Z","shell.execute_reply.started":"2025-06-01T16:19:57.594534Z","shell.execute_reply":"2025-06-01T16:19:57.663572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fail_list = []\ncount = 0\n\nfor img_path in tqdm(selected_imgs, desc=\"裁剪猫狗图像\"):\n    try:\n        img = cv2.imread(img_path)\n        if img is None:\n            fail_list.append(img_path)\n            continue\n\n        results = model(img, verbose=False)[0]\n\n        for box in results.boxes:\n            cls_id = int(box.cls)\n            if cls_id not in [15, 16]:\n                continue\n            if float(box.conf) < CONF_THRES:\n                continue\n\n            x1, y1, x2, y2 = map(int, box.xyxy[0])\n            cropped = img[y1:y2, x1:x2]\n            if cropped.size == 0:\n                continue\n\n            label = 'cat' if cls_id == 15 else 'dog'\n            orig_name = os.path.splitext(os.path.basename(img_path))[0]\n            save_path = os.path.join(save_dir, f\"{orig_name}_{label}.jpg\")\n            cv2.imwrite(save_path, cropped)\n            count += 1\n\n    except:\n        fail_list.append(img_path)\n\n# 简洁打印结果\nprint(f\"\\n✅ 裁剪完成，共保存图像数：{count}\")\nif fail_list:\n    print(f\"⚠️ 共处理失败 {len(fail_list)} 张图像，示例：\")\n    print(\"\\n\".join(fail_list[:5]))  # 只打印前5个","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:20:00.501570Z","iopub.execute_input":"2025-06-01T16:20:00.501873Z","iopub.status.idle":"2025-06-01T16:20:15.639119Z","shell.execute_reply.started":"2025-06-01T16:20:00.501852Z","shell.execute_reply":"2025-06-01T16:20:15.638397Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 类别检查\n\ncropped_dir = \"/kaggle/working/cropped_animals\"\ncropped_img = [f for f in os.listdir(cropped_dir) if f.endswith('.jpg')]\n\n# 分类统计\ncat_count = sum(1 for f in cropped_img if 'cat' in f.lower())\ndog_count = sum(1 for f in cropped_img if 'dog' in f.lower())\n\nprint(f\"🐱 猫图片数量：{cat_count}\")\nprint(f\"🐶 狗图片数量：{dog_count}\")\nprint(f\"🧮 总数量：{len(cropped_img)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:25:46.169544Z","iopub.execute_input":"2025-06-01T16:25:46.170121Z","iopub.status.idle":"2025-06-01T16:25:46.175961Z","shell.execute_reply.started":"2025-06-01T16:25:46.170094Z","shell.execute_reply":"2025-06-01T16:25:46.175379Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport random\nimport cv2\nimport matplotlib.pyplot as plt\n\n# 路径和参数设置\nvis_dir = \"/kaggle/working/cropped_animals\"\nvis_num = 20\nimage_paths = [os.path.join(vis_dir, f) for f in os.listdir(vis_dir) if f.endswith(\".jpg\")]\n\n# 随机抽取图像\nsampled_paths = random.sample(image_paths, k=min(vis_num, len(image_paths)))\n\n# 加载 YOLO 模型（获取置信度）\n# model = YOLO(\"yolov8n.pt\")\n\n# 可视化\nplt.figure(figsize=(20, 10))\n\nfor idx, img_path in enumerate(sampled_paths):\n    img = cv2.imread(img_path)\n    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n\n    # 用 YOLO 检测置信度（verbose=False 避免刷屏）\n    results = model(img, verbose=False)[0]\n    conf_score = \"-\"\n    label_str = os.path.basename(img_path).split(\"_\")[0]\n\n    # 获取最高置信度的猫/狗预测（排除其他）\n    for box in results.boxes:\n        cls_id = int(box.cls)\n        if cls_id not in [15, 16]:\n            continue\n        conf = float(box.conf)\n        conf_score = f\"{conf:.2f}\"\n        break  # 只取第一个（通常只有一个框）\n\n    # 绘图\n    plt.subplot(5, 4, idx + 1)\n    plt.imshow(img_rgb)\n    plt.title(f\"{label_str} ({conf_score})\", fontsize=10)\n    # plt.title(f\"{orig_name}\\n{label_str} (conf: {conf_score})\", fontsize=9)\n    plt.axis(\"off\")\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:21:56.152171Z","iopub.execute_input":"2025-06-01T16:21:56.152469Z","iopub.status.idle":"2025-06-01T16:21:57.754112Z","shell.execute_reply.started":"2025-06-01T16:21:56.152447Z","shell.execute_reply":"2025-06-01T16:21:57.753147Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport zipfile\nfrom IPython.display import FileLink, display\n\n# 1. 定义要压缩的文件夹和输出的zip文件名\nfolder_to_zip = \"/kaggle/working/cropped_animals\"  # 替换为你的文件夹名\nzip_filename = \"cropped_animals.zip\"  # 输出的zip文件名\n\n# 2. 压缩文件夹\ndef zip_folder(folder_path, output_path):\n    with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zipf:\n        for root, dirs, files in os.walk(folder_path):\n            for file in files:\n                file_path = os.path.join(root, file)\n                arcname = os.path.relpath(file_path, folder_path)\n                zipf.write(file_path, arcname)\n\n# 3. 检查文件夹是否存在，然后压缩并生成下载链接\nif os.path.exists(folder_to_zip):\n    zip_folder(folder_to_zip, zip_filename)  # 压缩\n    display(FileLink(zip_filename))  # 生成下载链接\n    print(f\"'{folder_to_zip}' 已压缩为 '{zip_filename}'，点击上方链接下载。\")\nelse:\n    print(f\"错误：文件夹 '{folder_to_zip}' 不存在！\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:22:50.144873Z","iopub.execute_input":"2025-06-01T16:22:50.145162Z","iopub.status.idle":"2025-06-01T16:22:51.251970Z","shell.execute_reply.started":"2025-06-01T16:22:50.145141Z","shell.execute_reply":"2025-06-01T16:22:51.251291Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport shutil\n\n# 指定要删除的文件夹路径\nfolder_path = '/kaggle/working/cropped_animals'\n\n# 删除文件夹中的所有文件\nfor filename in os.listdir(folder_path):\n    file_path = os.path.join(folder_path, filename)\n    try:\n        if os.path.isfile(file_path) or os.path.islink(file_path):\n            os.unlink(file_path)\n        elif os.path.isdir(file_path):\n            shutil.rmtree(file_path)\n    except Exception as e:\n        print(f'删除 {file_path} 失败。原因: {e}')\n\n# 删除文件夹\ntry:\n    os.rmdir(folder_path)\n    print(f\"文件夹 '{folder_path}' 已成功删除。\")\nexcept FileNotFoundError:\n    print(f\"文件夹 '{folder_path}' 不存在。\")\nexcept PermissionError:\n    print(f\"没有权限删除文件夹 '{folder_path}'。\")\nexcept OSError as e:\n    print(f\"删除文件夹时出错: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-01T16:19:23.920154Z","iopub.execute_input":"2025-06-01T16:19:23.920773Z","iopub.status.idle":"2025-06-01T16:19:24.228682Z","shell.execute_reply.started":"2025-06-01T16:19:23.920734Z","shell.execute_reply":"2025-06-01T16:19:24.228051Z"}},"outputs":[],"execution_count":null}]}