{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":90095,"databundleVersionId":10627580,"sourceType":"competition"}],"dockerImageVersionId":30804,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport glob\nimport json\n\nimport base64\nfrom PIL import Image\nimport cv2\nimport io\nimport matplotlib.pyplot as plt\nfrom matplotlib.patches import Polygon\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-12-16T02:32:17.742018Z","iopub.execute_input":"2024-12-16T02:32:17.743282Z","iopub.status.idle":"2024-12-16T02:32:17.748041Z","shell.execute_reply.started":"2024-12-16T02:32:17.743238Z","shell.execute_reply":"2024-12-16T02:32:17.746991Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ts_paths = glob.glob(\"/kaggle/input/glioma-mcd-2025/Data_122824/Glioma_MDC_2025_test/*.jpg\")\ntest = pd.DataFrame({\"img_path\": ts_paths})\ntest[\"json_path\"] = test[\"img_path\"].str.replace(\".jpg\", \".json\")\ntest","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T02:35:55.671771Z","iopub.execute_input":"2024-12-16T02:35:55.672862Z","iopub.status.idle":"2024-12-16T02:35:55.697219Z","shell.execute_reply.started":"2024-12-16T02:35:55.67278Z","shell.execute_reply":"2024-12-16T02:35:55.69624Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tr_paths = glob.glob(\"/kaggle/input/glioma-mcd-2025/Data_122824/Glioma_MDC_2025_training/*.jpg\")\ntrain = pd.DataFrame({\"img_path\": tr_paths})\ntrain[\"json_path\"] = train[\"img_path\"].str.replace(\".jpg\", \".json\")\ntrain","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T02:32:18.113091Z","iopub.execute_input":"2024-12-16T02:32:18.113477Z","iopub.status.idle":"2024-12-16T02:32:18.13178Z","shell.execute_reply.started":"2024-12-16T02:32:18.11344Z","shell.execute_reply":"2024-12-16T02:32:18.130804Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"json_path = train.loc[2, 'json_path'] \n\nwith open(json_path, 'r') as f:\n    data = json.load(f)\n\n# print(json.dumps(data, indent=2))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T02:32:18.510075Z","iopub.execute_input":"2024-12-16T02:32:18.510441Z","iopub.status.idle":"2024-12-16T02:32:18.516501Z","shell.execute_reply.started":"2024-12-16T02:32:18.510408Z","shell.execute_reply":"2024-12-16T02:32:18.51564Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# JSONデータから画像のBase64文字列を取得\nwith open(json_path, 'r') as f:\n    data = json.load(f)\n    img_data = data['imageData']\n    points = data['shapes'][0]['points']  # ポリゴンの頂点座標\n\n# Base64をデコードして画像を読み込み\nimg_bytes = base64.b64decode(img_data)\nimg = Image.open(io.BytesIO(img_bytes))\nimg_array = np.array(img)\n\n# プロット\nplt.figure(figsize=(10, 10))\nplt.imshow(img_array)\n\n# ポリゴンを描画\npolygon = Polygon(points, fill=False, edgecolor='r', linewidth=2)\nplt.gca().add_patch(polygon)\n\nplt.axis('off')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T02:32:18.898083Z","iopub.execute_input":"2024-12-16T02:32:18.898975Z","iopub.status.idle":"2024-12-16T02:32:19.662064Z","shell.execute_reply.started":"2024-12-16T02:32:18.898937Z","shell.execute_reply":"2024-12-16T02:32:19.660928Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_and_save_regions(json_path, margin=20, output_dir='extracted_regions/'):\n    \"\"\"\n    JSONファイルからアノテーション領域を切り出して保存する関数\n    \n    Parameters:\n    -----------\n    json_path : str\n        JSONファイルのパス\n    margin : int\n        切り出し領域の周りに追加するマージン（ピクセル）\n    output_dir : str\n        保存先ディレクトリ\n    \"\"\"\n    import os\n    from pathlib import Path\n\n    # 出力ディレクトリの作成\n    Path(output_dir).mkdir(parents=True, exist_ok=True)\n    \n    # JSONファイルの読み込み\n    with open(json_path, 'r') as f:\n        data = json.load(f)\n    \n    # 画像の読み込み\n    img_bytes = base64.b64decode(data['imageData'])\n    img = Image.open(io.BytesIO(img_bytes))\n    \n    # 各アノテーション領域について処理\n    for i, shape in enumerate(data['shapes']):\n        points = np.array(shape['points'])\n        label = shape['label']\n        \n        # バウンディングボックスの計算\n        min_x, min_y = np.floor(points.min(axis=0)).astype(int)\n        max_x, max_y = np.ceil(points.max(axis=0)).astype(int)\n        \n        # マージンの追加（画像サイズを超えないように調整）\n        min_x = max(0, min_x - margin)\n        min_y = max(0, min_y - margin)\n        max_x = min(img.width, max_x + margin)\n        max_y = min(img.height, max_y + margin)\n        \n        # 領域の切り出し\n        region = img.crop((min_x, min_y, max_x, max_y))\n        \n        # ファイル名の生成と保存\n        filename = f\"{label}_{i:03d}.jpg\"\n        save_path = os.path.join(output_dir, filename)\n        region.save(save_path, quality=95)\n        \n        print(f\"Saved region {i+1} ({label}) to {save_path}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T02:32:19.663954Z","iopub.execute_input":"2024-12-16T02:32:19.664299Z","iopub.status.idle":"2024-12-16T02:32:19.676384Z","shell.execute_reply.started":"2024-12-16T02:32:19.664264Z","shell.execute_reply":"2024-12-16T02:32:19.675242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import json\nimport base64\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\nimport io\nfrom pathlib import Path\n\ndef process_dataset(df, output_dir='processed_data/'):\n    \"\"\"\n    Process entire dataset from DataFrame containing image and json paths\n    \n    Parameters:\n    -----------\n    df : pandas.DataFrame\n        DataFrame with columns 'img_path' and 'json_path'\n    output_dir : str\n        Directory to save processed data\n    \n    Returns:\n    --------\n    pandas.DataFrame\n        DataFrame with processed data information\n    \"\"\"\n    # Create output directory\n    Path(output_dir).mkdir(parents=True, exist_ok=True)\n    \n    # Initialize lists for new DataFrame\n    processed_data = []\n    \n    # Process each entry in DataFrame\n    for idx, row in df.iterrows():\n        # Load JSON data\n        with open(row['json_path'], 'r') as f:\n            data = json.load(f)\n        \n        # Get base filename from json_path (remove .json extension)\n        base_filename = Path(row['json_path']).stem\n        \n        # Generate output filename with sequential number\n        output_filename = f\"{base_filename}_{idx:04d}.png\"\n        output_path = Path(output_dir) / output_filename\n        \n        # Process image\n        if 'imageData' in data:\n            # Decode base64 image data\n            img_bytes = base64.b64decode(data['imageData'])\n            img = Image.open(io.BytesIO(img_bytes))\n            \n            # Save image as PNG with full quality\n            img.save(output_path, format='PNG')\n            \n            # Extract annotation information\n            for shape in data['shapes']:\n                processed_data.append({\n                    'filename': output_filename,\n                    'label': shape['label'],\n                    'is_mitosis': 1 if 'mitosis' in shape['label'].lower() else 0,\n                    'points': shape['points'],\n                    'shape_type': shape['shape_type']\n                })\n    \n    # Create new DataFrame with processed information\n    result_df = pd.DataFrame(processed_data)\n    \n    # Save DataFrame to CSV\n    result_df.to_csv(Path(output_dir) / 'annotations.csv', index=False)\n    \n    return result_df\n\n# Example usage\n# df should have columns 'img_path' and 'json_path'\n# processed_df = process_dataset(df, output_dir='processed_data/')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T02:34:54.009004Z","iopub.execute_input":"2024-12-16T02:34:54.009714Z","iopub.status.idle":"2024-12-16T02:34:54.019723Z","shell.execute_reply.started":"2024-12-16T02:34:54.009674Z","shell.execute_reply":"2024-12-16T02:34:54.018637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_and_save_regions(df, margin=20, output_dir='extracted_regions/'):\n    \"\"\"\n    Extract and save annotated regions from dataset with associated metadata\n    \n    Parameters:\n    -----------\n    df : pandas.DataFrame\n        DataFrame containing image and json paths\n    margin : int\n        Margin to add around the annotated region (in pixels)\n    output_dir : str\n        Directory to save extracted regions\n    \n    Returns:\n    --------\n    pandas.DataFrame\n        DataFrame containing information about extracted regions\n    \"\"\"\n    import os\n    from pathlib import Path\n    \n    # Create output directory\n    Path(output_dir).mkdir(parents=True, exist_ok=True)\n    \n    # Initialize list for storing region information\n    regions_data = []\n    \n    # Process each entry in DataFrame\n    for idx, row in df.iterrows():\n        # Load JSON data\n        with open(row['json_path'], 'r') as f:\n            data = json.load(f)\n            \n        # Get base name from json path (without .json extension)\n        base_name = Path(row['json_path']).stem\n        \n        # Decode image\n        img_bytes = base64.b64decode(data['imageData'])\n        img = Image.open(io.BytesIO(img_bytes))\n        \n        # Process each annotation\n        for shape_idx, shape in enumerate(data['shapes']):\n            points = np.array(shape['points'])\n            label = shape['label']\n            \n            # Calculate bounding box\n            min_x, min_y = np.floor(points.min(axis=0)).astype(int)\n            max_x, max_y = np.ceil(points.max(axis=0)).astype(int)\n            \n            # Add margin (ensure within image bounds)\n            min_x = max(0, min_x - margin)\n            min_y = max(0, min_y - margin)\n            max_x = min(img.width, max_x + margin)\n            max_y = min(img.height, max_y + margin)\n            \n            # Extract region\n            region = img.crop((min_x, min_y, max_x, max_y))\n            \n            # Generate filename using json name and number\n            filename = f\"{base_name}_{shape_idx}.png\"\n            save_path = os.path.join(output_dir, filename)\n            region.save(save_path, format='PNG')\n            \n            # Store region information\n            regions_data.append({\n                'filename': filename,\n                'original_json': row['json_path'],\n                'label': label,\n                'is_mitosis': 1 if 'mitosis' in label.lower() else 0,\n                'bbox': [min_x, min_y, max_x, max_y],\n                'region_size': (max_x - min_x, max_y - min_y)\n            })\n    \n    # Create and save DataFrame\n    result_df = pd.DataFrame(regions_data)\n    result_df.to_csv(os.path.join(output_dir, 'regions_metadata.csv'), index=False)\n    \n    return result_df\n\n# Example usage\n# result_df = extract_and_save_regions(df, margin=20, output_dir='extracted_regions')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Assuming df is your input DataFrame\noutput_dir = 'train_pngs'\nresult_df = extract_and_save_regions(train, margin=5,output_dir=output_dir)\n# result_df.to_csv(\"train.csv\", index=False)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}