{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# <B> Mayo Clinic - STRIP AI</B>\n\n![](https://cdn.pixabay.com/photo/2022/04/08/01/01/blood-clot-7118517_960_720.png)\n\n## <u>EDA , 기본적인 이미지 탐색 및 변환</u>\n\n**Organiser:** Mayo Clinic은 통합 의료, 교육 및 연구에 중점을 둔 비영리 미국 학술 의료 센터입니다. 3개의 주요 캠퍼스에서 4,500명 이상의 의사 및 과학자와 58,400명의 관리 및 관련 보건 직원을 고용하고 있습니다.\n\n* Rochester, Minnesota\n* Jacksonville, Florida\n* Phoenix/Scottsdale, Arizona.\n\n진료는 3차 진료 및 대상 의학을 통해 어려운 경우를 치료하는 것을 전문으로 합니다. 연구에 연간 6억 6천만 달러 이상을 지출하고 3,000명 이상의 전임 연구 인력을 보유하고 있습니다.\n대회 후원 웹사이트: https://www.mayoclinic.org/\n\n**대회 개요:**\n* 문제 유형 : 분류\n* 대상 : 이진분류(2가지)\n* 주제 : 혈전\n\n혈전에 대해 참고할만한 정보 [here](https://www.hematology.org/education/patients/blood-clots).\n\n이 노트북에서는 다음 라이브러리를 사용하여 몇 가지 방법으로 .tiff 파일을 여는 방법을 보여 드리겠습니다.\n\n* PIL\n* Matplotlib\n* CV2\n* Scikit-image\n* OpenSlide  \n\n탐색해보고 가장 편리한 것을 선택할 수 있습니다. 먼저 원본 세트를 로드하고 탐색한 다음 나중에 Rob Mula(https://www.kaggle.com/robikscube)가 준비한 데이터베이스의 슬라이스 버전을 노트북에 첨부합니다.\n\n거기에서 탐색적 데이터 분석을 수행합니다.","metadata":{}},{"cell_type":"markdown","source":"[](http://)","metadata":{}},{"cell_type":"markdown","source":"## 라이브러리 불러오기","metadata":{}},{"cell_type":"code","source":"import os\nimport sys\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport cv2\n\nfrom glob import glob\nfrom pprint import pprint\nfrom collections import defaultdict\nimport gc","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-17T03:59:39.621104Z","iopub.execute_input":"2022-07-17T03:59:39.62158Z","iopub.status.idle":"2022-07-17T03:59:39.629008Z","shell.execute_reply.started":"2022-07-17T03:59:39.621546Z","shell.execute_reply":"2022-07-17T03:59:39.627809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. 이미지 메타데이터\n\n테이블 데이터 살펴보기\n\ncenter_id는 이미지 및 데이터가 수집된 센터의 ID 입니다. \n\nimage_num은 각 환자별 이미지의 개수입니다.\n\n\n","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv('../input/mayo-clinic-strip-ai/train.csv')\ntest_df = pd.read_csv('../input/mayo-clinic-strip-ai/test.csv')\nother_df = pd.read_csv('../input/mayo-clinic-strip-ai/other.csv')","metadata":{"execution":{"iopub.status.busy":"2022-07-17T03:59:39.634456Z","iopub.execute_input":"2022-07-17T03:59:39.635598Z","iopub.status.idle":"2022-07-17T03:59:39.690336Z","shell.execute_reply.started":"2022-07-17T03:59:39.635532Z","shell.execute_reply":"2022-07-17T03:59:39.688816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T03:59:39.692871Z","iopub.execute_input":"2022-07-17T03:59:39.693839Z","iopub.status.idle":"2022-07-17T03:59:39.720068Z","shell.execute_reply.started":"2022-07-17T03:59:39.693785Z","shell.execute_reply":"2022-07-17T03:59:39.719188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T03:59:39.721084Z","iopub.execute_input":"2022-07-17T03:59:39.721569Z","iopub.status.idle":"2022-07-17T03:59:39.73388Z","shell.execute_reply.started":"2022-07-17T03:59:39.721526Z","shell.execute_reply":"2022-07-17T03:59:39.732476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 센터정보는 없는 환자의 이미지 정보입니다.\n\nother_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T03:59:39.736669Z","iopub.execute_input":"2022-07-17T03:59:39.737092Z","iopub.status.idle":"2022-07-17T03:59:39.754319Z","shell.execute_reply.started":"2022-07-17T03:59:39.737058Z","shell.execute_reply":"2022-07-17T03:59:39.75337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"각각의 데이터셋 별로 중복되지 않은 환자수 계산하겠습니다.","metadata":{}},{"cell_type":"code","source":"patients_train = train_df['patient_id'].nunique()\npatients_test = test_df['patient_id'].nunique()\npatients_other = other_df['patient_id'].nunique()\n\nprint(f\"Number of unique patients in train set: {patients_train}\")\nprint(f\"Number of unique patients in test set: {patients_test}\")\nprint(f\"Number of unique patients in the 'other' set: {patients_other}\")","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-07-17T03:59:39.75604Z","iopub.execute_input":"2022-07-17T03:59:39.757231Z","iopub.status.idle":"2022-07-17T03:59:39.771945Z","shell.execute_reply.started":"2022-07-17T03:59:39.757194Z","shell.execute_reply":"2022-07-17T03:59:39.770947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('Solarize_Light2')\nlabels = train_df.groupby('label')['label'].count().div(len(train_df)).mul(100)\ncenters = train_df.groupby(\"center_id\")['center_id'].count().div(len(train_df)).mul(100)\n\nfig, ax = plt.subplots(1,2, figsize=(16,5))\nsns.barplot(x=labels.index, y=labels.values, ax=ax[0])\nax[0].set_title(\"Distribution of a target variable\"), ax[0].set_ylabel(\"%\")\nsns.barplot(x=centers.index, y=centers.values, ax=ax[1])\nax[1].set_title(\"Patients per clinic center\"), ax[1].set_ylabel(\"%\")\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T03:59:39.773472Z","iopub.execute_input":"2022-07-17T03:59:39.774119Z","iopub.status.idle":"2022-07-17T03:59:40.183582Z","shell.execute_reply.started":"2022-07-17T03:59:39.774076Z","shell.execute_reply":"2022-07-17T03:59:40.18222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"아래의 2가지 타입을 제외한 혈전은 이번 대회의 고려 대상이 아닙니다:\")\nprint(list(other_df['other_specified'].unique()))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:21:32.053691Z","iopub.execute_input":"2022-07-17T04:21:32.054269Z","iopub.status.idle":"2022-07-17T04:21:32.061415Z","shell.execute_reply.started":"2022-07-17T04:21:32.054225Z","shell.execute_reply":"2022-07-17T04:21:32.060061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. 이미지 - 탐색 및 전처리\n\n이미지의 개수부터 탐색","metadata":{}},{"cell_type":"code","source":"train_images = glob(\"/kaggle/input/mayo-clinic-strip-ai/train/*\")\ntest_images = glob(\"/kaggle/input/mayo-clinic-strip-ai/test/*\")\nother_images = glob(\"/kaggle/input/mayo-clinic-strip-ai/other/*\")\nprint(f\"훈련 데이터셋 이미지 개수: {len(train_images)}\")\nprint(f\"테스트 데이터셋 이미지 개수: {len(test_images)}\")\nprint(f\"기타 데이터셋 이미지 개수: {len(other_images)}\")","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:22:31.577712Z","iopub.execute_input":"2022-07-17T04:22:31.578171Z","iopub.status.idle":"2022-07-17T04:22:31.719621Z","shell.execute_reply.started":"2022-07-17T04:22:31.578137Z","shell.execute_reply":"2022-07-17T04:22:31.718376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2.1 OpenSlide package를 이용한 이미지 탐색\n\nOpenSlide는 디지털 병리학에 사용되는 고해상도 사진을 읽기 위해 만든 라이브러리입니다. 이러한 특정 무거운 이미지를 처리할 때 사용되는 몇 가지 실용적인 기능이 있습니다.\n\nDocs: https://openslide.org/api/python/","metadata":{}},{"cell_type":"code","source":"from openslide import OpenSlide","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T03:59:40.45376Z","iopub.execute_input":"2022-07-17T03:59:40.454293Z","iopub.status.idle":"2022-07-17T03:59:40.566567Z","shell.execute_reply.started":"2022-07-17T03:59:40.454261Z","shell.execute_reply":"2022-07-17T03:59:40.565507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_prop = defaultdict(list)\n\nfor i, path in enumerate(train_images):\n    img_path = train_images[i]\n    slide = OpenSlide(img_path)    \n    img_prop['image_id'].append(img_path[-12:-4])\n    img_prop['width'].append(slide.dimensions[0])\n    img_prop['height'].append(slide.dimensions[1])\n    img_prop['size'].append(round(os.path.getsize(img_path) / 1e6, 2))\n    img_prop['path'].append(img_path)\n\nimage_data = pd.DataFrame(img_prop)\nimage_data['img_aspect_ratio'] = image_data['width']/image_data['height']\nimage_data.sort_values(by='image_id', inplace=True)\nimage_data.reset_index(inplace=True, drop=True)\n\nimage_data = image_data.merge(train_df, on='image_id')\nimage_data.head()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T03:59:40.571438Z","iopub.execute_input":"2022-07-17T03:59:40.571786Z","iopub.status.idle":"2022-07-17T03:59:59.900385Z","shell.execute_reply.started":"2022-07-17T03:59:40.571755Z","shell.execute_reply":"2022-07-17T03:59:59.899052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.displot(image_data[\"size\"], stat='percent')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T03:59:59.902024Z","iopub.execute_input":"2022-07-17T03:59:59.90248Z","iopub.status.idle":"2022-07-17T04:00:00.278931Z","shell.execute_reply.started":"2022-07-17T03:59:59.902434Z","shell.execute_reply":"2022-07-17T04:00:00.277786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2.2 이미지 살펴보기\n\n여러개의 이미지를 살펴보고 기본적인 이미지 변형을 해보겠습니다.\n\n## 2.2.1 PIL을 사용하여 이미지 살펴보기  \n\nPIL은 *Python Imaging Library*의 약자이며 이미지 열기 및 처리를 위한 가장 인기 있는 Python 라이브러리 중 하나입니다(*베개*라고도 함). 무작위 이미지 몇 개를 열어 보겠습니다. \n\nRAM을 죽이지 않고 이미지를 여는 PIL의 thumbnail 기능을 사용할 수 있습니다. `thumbnail()`.","metadata":{}},{"cell_type":"code","source":"from PIL import Image\nImage.MAX_IMAGE_PIXELS = None  # 고해상도의 이미지를 원한다면 이 설정을 True로 설정해주세요.","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:00:00.280758Z","iopub.execute_input":"2022-07-17T04:00:00.28112Z","iopub.status.idle":"2022-07-17T04:00:00.285911Z","shell.execute_reply.started":"2022-07-17T04:00:00.281088Z","shell.execute_reply":"2022-07-17T04:00:00.284814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CE_imgs = image_data.loc[image_data['label']=='CE','path']\nLAA_imgs = image_data.loc[image_data['label']=='LAA','path']","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:00:00.287311Z","iopub.execute_input":"2022-07-17T04:00:00.287891Z","iopub.status.idle":"2022-07-17T04:00:00.305393Z","shell.execute_reply.started":"2022-07-17T04:00:00.287856Z","shell.execute_reply":"2022-07-17T04:00:00.304292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('default')\nfig, axes = plt.subplots(1,5, figsize=(16,16))\ntrain_images\nfor ax in axes.reshape(-1):\n    img_path = np.random.choice(CE_imgs)\n    img = Image.open(img_path)   \n    img.thumbnail((300,300), Image.Resampling.LANCZOS)\n    ax.imshow(img), ax.set_title(\"target: CE\")\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:00:00.30701Z","iopub.execute_input":"2022-07-17T04:00:00.307385Z","iopub.status.idle":"2022-07-17T04:03:02.641092Z","shell.execute_reply.started":"2022-07-17T04:00:00.307346Z","shell.execute_reply":"2022-07-17T04:03:02.63773Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1,5, figsize=(16,16))\ntrain_images\nfor ax in axes.reshape(-1):\n    img_path = np.random.choice(LAA_imgs)\n    img = Image.open(img_path)   \n    img.thumbnail((300,300), Image.Resampling.LANCZOS)\n    ax.imshow(img), ax.set_title(\"target: LAA\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:03:02.645324Z","iopub.execute_input":"2022-07-17T04:03:02.64581Z","iopub.status.idle":"2022-07-17T04:03:53.542628Z","shell.execute_reply.started":"2022-07-17T04:03:02.645765Z","shell.execute_reply":"2022-07-17T04:03:53.541247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(img)","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:03:53.54452Z","iopub.execute_input":"2022-07-17T04:03:53.545503Z","iopub.status.idle":"2022-07-17T04:03:53.55254Z","shell.execute_reply.started":"2022-07-17T04:03:53.545454Z","shell.execute_reply":"2022-07-17T04:03:53.551429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"PIL은 이미지를 PIL 객체로 저장합니다. 이것은 이미지를 numpy 배열로 저장하는 CV2 및 skimage와 다릅니다. 이는 이미지 후처리를 편하게 해줍니다.\n\n**이미지에 대한 대략적인 감상:**\n1. 이미지 크기가 중구난방이다... 작은것도 있고 고해상도도 있고\n2. 이미지의 비율이 제각각이다. 세로가 긴것도 가로가 긴것도..\n3. 실제 혈전 이미지의 영역보다 배경이 훨씬 많다.\n4. 배경색깔이 다양하다.\n5. 혈관 이미지가 다양하고 작은 조각들로 구성되어 있다.\n6. 혈관 이미지의 색깔이 다양하다.","metadata":{"execution":{"iopub.status.busy":"2022-07-09T10:43:16.533119Z","iopub.execute_input":"2022-07-09T10:43:16.533551Z","iopub.status.idle":"2022-07-09T10:43:16.721438Z","shell.execute_reply.started":"2022-07-09T10:43:16.533516Z","shell.execute_reply":"2022-07-09T10:43:16.72019Z"}}},{"cell_type":"markdown","source":"가장 큰 이미지 메타데이터를 살펴보겠습니다. 또한 표준 Kaggle 노트북에서 확장 없이 PIL, CV2 또는 Matplotlib를 사용하여 열려고 하면 메모리가 부족해집니다.","metadata":{}},{"cell_type":"code","source":"biggest_img_path = image_data.iloc[image_data[\"size\"].idxmax(),:]['path']\n\nimg = Image.open(biggest_img_path)\nimg.thumbnail((400,400), Image.Resampling.LANCZOS)\nplt.title(\"The biggest image\")\nplt.imshow(img)\nplt.axis('off'); plt.show()\ndel img","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:03:53.554209Z","iopub.execute_input":"2022-07-17T04:03:53.554645Z","iopub.status.idle":"2022-07-17T04:05:07.269181Z","shell.execute_reply.started":"2022-07-17T04:03:53.554602Z","shell.execute_reply":"2022-07-17T04:05:07.267436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"이제 가장 작은 3개의 이미지를 살펴보겠습니다. 여기서는 데모를 위해 matplotlib 라이브러리를 사용하겠습니다. 이미지 읽기에 관한 문서 및 자습서는 다음과 같습니다. [링크](https://matplotlib.org/stable/tutorials/introductory/images.html).","metadata":{}},{"cell_type":"code","source":"smallest_3img_data = image_data.sort_values(by=\"size\")[:3]\nsmallest_3img_paths = smallest_3img_data['path'].values","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:05:07.271313Z","iopub.execute_input":"2022-07-17T04:05:07.272036Z","iopub.status.idle":"2022-07-17T04:05:07.294223Z","shell.execute_reply.started":"2022-07-17T04:05:07.271979Z","shell.execute_reply":"2022-07-17T04:05:07.292631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.image as mpimg\n\nfig, axes = plt.subplots(1,3, figsize=(16,16))\nfor i, ax in enumerate(axes.reshape(-1)):\n    img = mpimg.imread(smallest_3img_paths[i])   \n    ax.imshow(img), plt.axis('off')\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:05:07.295856Z","iopub.execute_input":"2022-07-17T04:05:07.29651Z","iopub.status.idle":"2022-07-17T04:06:10.844414Z","shell.execute_reply.started":"2022-07-17T04:05:07.296476Z","shell.execute_reply":"2022-07-17T04:06:10.843232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2.2.2 CV2 및 skimage를 사용한 이미지 탐색, 크기 조정 및 조작\n\n여기에서는 *Computer Vision* 라이브러리 CV2를 사용하여 전체 이미지를 열 것입니다. 우리는 이 라이브러리를 사용하여 이미지 조작에 사용합니다. Canny 에지 검출기를 사용하여 에지도 검출해 보려고 합니다.\n참고: CV2 라이브러리에는 이미지 크기 제한이 있으며 데이터 세트의 일부 이미지에 오류가 발생합니다. 환경 변수를 변경하여 해결 방법이 있지만(섹션 0 참조) 그래도 일부 이미지는 메모리에 맞지 않습니다. \n\n\n이 이미지를 몇 가지 방법으로 조작할 수 있습니다. 이를 위해 아래 예시 이미지를 이용합니다.","metadata":{}},{"cell_type":"code","source":"img_path = train_images[261]\nimg_name = img_path[-12:-4]\nsel_img = image_data[image_data['image_id']==img_name]\nsel_img","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:06:10.845886Z","iopub.execute_input":"2022-07-17T04:06:10.846227Z","iopub.status.idle":"2022-07-17T04:06:10.874229Z","shell.execute_reply.started":"2022-07-17T04:06:10.846197Z","shell.execute_reply":"2022-07-17T04:06:10.872911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"matplotlib를 사용하여 어떻게 보이는지 살펴보겠습니다(나중에 CV2로 보면서 matplot과 차이점을 살펴보겠습니다).","metadata":{}},{"cell_type":"code","source":"img = mpimg.imread(img_path)   \nplt.imshow(img), plt.axis('off')\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:06:10.876027Z","iopub.execute_input":"2022-07-17T04:06:10.876404Z","iopub.status.idle":"2022-07-17T04:06:33.205577Z","shell.execute_reply.started":"2022-07-17T04:06:10.876373Z","shell.execute_reply":"2022-07-17T04:06:33.204294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"이제 CV2에서 이 이미지를 읽고 크기를 조정하겠습니다. 크기가 원래 크기의 10%로 축소됩니다. \n올바른 축을 보거나 단순히 두 번째 이미지의 모양을 플로팅하여 작동하는지 확인할 수 있습니다.","metadata":{}},{"cell_type":"code","source":"img = cv2.imread(img_path, cv2.IMREAD_COLOR)\nimage_resized = cv2.resize(img, (0,0), fx=0.05, fy=0.05)\n\nfig, ax = plt.subplots(1,2, figsize=(12,12))\nax[0].imshow(img)\nax[1].imshow(image_resized)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:06:33.20715Z","iopub.execute_input":"2022-07-17T04:06:33.207594Z","iopub.status.idle":"2022-07-17T04:06:53.805987Z","shell.execute_reply.started":"2022-07-17T04:06:33.207561Z","shell.execute_reply":"2022-07-17T04:06:53.80481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"RGB 컬러로 열려면 다음 작업을 수행해야 합니다.","metadata":{}},{"cell_type":"code","source":"img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:06:53.807559Z","iopub.execute_input":"2022-07-17T04:06:53.808677Z","iopub.status.idle":"2022-07-17T04:06:53.925011Z","shell.execute_reply.started":"2022-07-17T04:06:53.808636Z","shell.execute_reply":"2022-07-17T04:06:53.923823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_resized = cv2.resize(img, (0,0), fx=0.05, fy=0.05)\n\nfig, ax = plt.subplots(1,2, figsize=(12,12))\nax[0].imshow(img)\nax[1].imshow(image_resized)\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:06:53.926911Z","iopub.execute_input":"2022-07-17T04:06:53.927365Z","iopub.status.idle":"2022-07-17T04:07:11.059489Z","shell.execute_reply.started":"2022-07-17T04:06:53.927319Z","shell.execute_reply":"2022-07-17T04:07:11.05814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"CV2에서 연 이미지는 다른 라이브러리에서 연 이미지와 색상이 다르다는 것을 나중에 알 수 있습니다. CV2는 기본적으로 색상 채널을 RGB가 아닌 BGR(blue-gree-red)로 읽기 때문입니다.","metadata":{}},{"cell_type":"code","source":"print(f\"CV2 이미지 타입 : {type(img)}\")\nprint(f\"CV2 image 메모리 사용량: {sys.getsizeof(img)/1e6:.2f}MB\")\nprint(f\"CV2 image 메모리 사용량: {sys.getsizeof(image_resized)/1e6:.2f}MB\")\nprint(f'조정된 이미지의 사이즈: ({image_resized.shape[0]}, {image_resized.shape[1]}). Number of color channels: {image_resized.shape[2]}')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:47:17.270264Z","iopub.execute_input":"2022-07-17T04:47:17.271828Z","iopub.status.idle":"2022-07-17T04:47:17.280783Z","shell.execute_reply.started":"2022-07-17T04:47:17.271775Z","shell.execute_reply":"2022-07-17T04:47:17.279368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"CV2는 이미지를 numpy 배열로 저장합니다.\n\n다음은 CV2를 사용한 3가지 예시적인 변환입니다:\n* 색채 대비를 늘립니다. 이를 위해 addWeighted 함수를 사용해야 합니다.\n* 가장자리(엣지) 탐지. 이를 위해 우리는 Canny 방법을 사용합니다.\n* 회색조(흑백)으로 읽기. `cv2.COLOR_RGB2GRAY`를 사용하고 `.imshow()` 에 cmap에 gray 옵션을 추가합니다.","metadata":{}},{"cell_type":"code","source":"contrast_img = cv2.addWeighted(image_resized, 2.5, np.zeros(image_resized.shape, image_resized.dtype), 0, 0)\nimg_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n\nmin_intensity_grad, max_intensity_grad = 100, 200\nedge_img = cv2.Canny(image_resized, min_intensity_grad, max_intensity_grad)\n\nfig, ax = plt.subplots(1,3, figsize=(15,20))\nax[0].imshow(contrast_img); ax[0].set_title('increased contrast')\nax[1].imshow(img_gray, cmap='gray', vmin = 0, vmax = 255); ax[1].set_title('grayscale')\nax[2].imshow(edge_img); ax[2].set_title('detected edges')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:07:11.074986Z","iopub.execute_input":"2022-07-17T04:07:11.075822Z","iopub.status.idle":"2022-07-17T04:07:18.646693Z","shell.execute_reply.started":"2022-07-17T04:07:11.075774Z","shell.execute_reply":"2022-07-17T04:07:18.645254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect()\ndel contrast_img, edge_img, img_gray, image_resized","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:07:18.648299Z","iopub.execute_input":"2022-07-17T04:07:18.648753Z","iopub.status.idle":"2022-07-17T04:07:18.815926Z","shell.execute_reply.started":"2022-07-17T04:07:18.648689Z","shell.execute_reply":"2022-07-17T04:07:18.814508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2.2.3 scikit-image를 사용한 이미지 변환\n\nScikit-Image를 사용하여 동일한 이미지 변환을 수행합니다. Scikit-Image는 이미지 처리 기능을 포함하는 또 다른 인기 있는 파이썬 패키지입니다. Skimage는 이미지를 numpy 배열로 저장합니다.\n\n* 공식 페이지: https://scikit-image.org/ \n* 가장 흥미로운 섹션은 https://scikit-image.org/docs/stable/user_guide/transforming_image_data.html입니다.","metadata":{}},{"cell_type":"code","source":"from skimage import io, exposure, feature\nfrom skimage.transform import rescale\nfrom skimage.color import rgb2gray","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:07:18.818098Z","iopub.execute_input":"2022-07-17T04:07:18.819048Z","iopub.status.idle":"2022-07-17T04:07:20.198916Z","shell.execute_reply.started":"2022-07-17T04:07:18.819007Z","shell.execute_reply":"2022-07-17T04:07:20.197834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img = io.imread(img_path)\nimage_resized = rescale(img, 0.2, multichannel=True, anti_aliasing=True) # creating a scaled image\nincreased_contrast = exposure.adjust_gamma(image_resized, 2)\nimg_gray = rgb2gray(image_resized)\nedge_img = feature.canny(img_gray, sigma=3) # canny works only with grayscale images\n\nfig, ax = plt.subplots(1,4, figsize=(15,20))\nax[0].imshow(image_resized); ax[0].set_title('image resized')\nax[1].imshow(increased_contrast); ax[1].set_title('increased contrast')\nax[2].imshow(edge_img); ax[2].set_title('detected edges')\nax[3].imshow(img_gray, cmap='gray'); ax[3].set_title('grayscale')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:07:20.201902Z","iopub.execute_input":"2022-07-17T04:07:20.202785Z","iopub.status.idle":"2022-07-17T04:08:19.78413Z","shell.execute_reply.started":"2022-07-17T04:07:20.202707Z","shell.execute_reply":"2022-07-17T04:08:19.782785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2.2.4 오픈슬라이드 라이브러\n\n여기에서는 슬라이드(이미지)를 열고 확대된 영역만 플롯합니다. 이것은 `slide.read_region()` 함수를 사용하여 달성됩니다. OpenSlide는 메모리에 이미지를 Openslide 개체로 저장합니다.","metadata":{}},{"cell_type":"code","source":"slide = OpenSlide(img_path) # opening a full slide\n\nregion = (2500, 2000) # location of the top left pixel\nlevel = 0 # level of the picture (we have only 0)\nsize = (3500, 3500) # region size in pixels\n\nregion = slide.read_region(region, level, size)\n\nplt.figure(figsize=(15, 15))\nplt.imshow(region)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:08:19.786182Z","iopub.execute_input":"2022-07-17T04:08:19.787084Z","iopub.status.idle":"2022-07-17T04:08:22.81601Z","shell.execute_reply.started":"2022-07-17T04:08:19.787032Z","shell.execute_reply":"2022-07-17T04:08:22.814196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"위에 이미지의 내용에 대해 살펴보는데 저는 의사가 아니므로 위키피디아의 사진을 사용하겠습니다:\n\n<img src=\"https://upload.wikimedia.org/wikipedia/commons/0/06/Composition_of_a_fresh_thrombus.jpg\" width=\"648\" />","metadata":{}},{"cell_type":"code","source":"type(slide)","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:08:22.817884Z","iopub.execute_input":"2022-07-17T04:08:22.818257Z","iopub.status.idle":"2022-07-17T04:08:22.826077Z","shell.execute_reply.started":"2022-07-17T04:08:22.818223Z","shell.execute_reply":"2022-07-17T04:08:22.824789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3 데이터베이스의 슬라이스 버전\n\n데이터 세트 목록: https://www.kaggle.com/competitions/mayo-clinic-strip-ai/discussion/335755. \n\n노트북에 데이터베이스를 추가하려면 오른쪽 상단 모서리에 있는 \"+ 데이터 추가\" 옵션을 사용해야 합니다. 여기서는 skimage 라이브러리를 사용하겠습니다.","metadata":{}},{"cell_type":"code","source":"sliced_train_images = glob(\"../input/mayo-clinic-1024-jpg-part1/train/*\")","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:08:22.827417Z","iopub.execute_input":"2022-07-17T04:08:22.827837Z","iopub.status.idle":"2022-07-17T04:08:25.445568Z","shell.execute_reply.started":"2022-07-17T04:08:22.827789Z","shell.execute_reply":"2022-07-17T04:08:25.444107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(6,6, figsize=(20,20))\nfor i, ax in enumerate(axes.flat):\n    img = io.imread(sliced_train_images[i])\n    ax.imshow(img); ax.set_title(i)\nplt.tight_layout()\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:25.446989Z","iopub.execute_input":"2022-07-17T04:08:25.447339Z","iopub.status.idle":"2022-07-17T04:08:35.646124Z","shell.execute_reply.started":"2022-07-17T04:08:25.447308Z","shell.execute_reply":"2022-07-17T04:08:35.644778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"보시다시피 많은 사진에는 배경만 포함되어 있습니다. 배경을 전 처리하는 것도 하나의 과제입니다.\n다음은 skimage를 사용한 이미지 처리에 대한 보다 자세한 소개입니다. \n\n\n계속 지켜봐 주시고 지금까지 본 내용이 마음에 드시면 주저하지 말고 업보트 부탁드려요!","metadata":{}},{"cell_type":"code","source":"img_obj_ids = [1, 2, 4, 11, 12, 14]\nimg_bck_ids = [0, 3, 5, 6, 7, 8]\n\nimgs_object = []\nimgs_backgr = []\n\nfor i in img_obj_ids:\n    imgs_object.append(io.imread(sliced_train_images[i]))\n    \nfor i in img_bck_ids:\n    imgs_backgr.append(io.imread(sliced_train_images[i]))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:35.647847Z","iopub.execute_input":"2022-07-17T04:08:35.648446Z","iopub.status.idle":"2022-07-17T04:08:35.921619Z","shell.execute_reply.started":"2022-07-17T04:08:35.648412Z","shell.execute_reply":"2022-07-17T04:08:35.920519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 색상 채널 분석\n각 이미지에는 빨강, 녹색, 파랑의 3가지 색상 채널(RGB)이 있습니다. 아래에는 이러한 채널이 표시됩니다. 각 채널은 주어진 단일 색상의 강도만을 나타내므로 혼동을 피하기 위해 이러한 이미지를 회색조로 표시합니다(그렇지 않으면 표시되는 색상으로).\n\n참고: 각 색상 채널의 값은 0에서 255 사이입니다.","metadata":{}},{"cell_type":"code","source":"imgs_object[0].shape","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:08:35.923113Z","iopub.execute_input":"2022-07-17T04:08:35.92361Z","iopub.status.idle":"2022-07-17T04:08:35.930831Z","shell.execute_reply.started":"2022-07-17T04:08:35.92358Z","shell.execute_reply":"2022-07-17T04:08:35.929645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1,3, figsize=(12,12))\ncolors = ['red', 'green', 'blue']\nfor i, ax in enumerate(axes):\n    ax.imshow(imgs_object[0][:,:,i], cmap='gray')\n    ax.set_title(colors[i]+' channel'), ax.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:08:35.932475Z","iopub.execute_input":"2022-07-17T04:08:35.932851Z","iopub.status.idle":"2022-07-17T04:08:36.493882Z","shell.execute_reply.started":"2022-07-17T04:08:35.932809Z","shell.execute_reply":"2022-07-17T04:08:36.492515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_obj = imgs_object[0]\nimg_bck = imgs_backgr[0]\n\nimg_obj_channels = [img_obj[0], img_obj[1], img_obj[2]]\nimg_bck_channels = [img_bck[0], img_bck[1], img_bck[2]]","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:36.495553Z","iopub.execute_input":"2022-07-17T04:08:36.495963Z","iopub.status.idle":"2022-07-17T04:08:36.502619Z","shell.execute_reply.started":"2022-07-17T04:08:36.495928Z","shell.execute_reply":"2022-07-17T04:08:36.50115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"skimage의 이미지는 Numpy 배열로 저장되며 모든 Numpy 기능을 여기에 적용할 수 있습니다.","metadata":{}},{"cell_type":"code","source":"# 1024*1024\ntype(img_obj_channels[0])","metadata":{"execution":{"iopub.status.busy":"2022-07-17T04:08:36.504387Z","iopub.execute_input":"2022-07-17T04:08:36.504905Z","iopub.status.idle":"2022-07-17T04:08:36.517461Z","shell.execute_reply.started":"2022-07-17T04:08:36.504858Z","shell.execute_reply":"2022-07-17T04:08:36.516316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"대상(혈관)에 대한 이미지 슬라이드\")\nfor i, channel in enumerate(img_obj_channels):\n    print(f\"Channel {i} values: min: {channel.min()}, max: {channel.max()}, average: {channel.mean()}, std: {channel.std()}\")","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T05:05:05.474933Z","iopub.execute_input":"2022-07-17T05:05:05.475582Z","iopub.status.idle":"2022-07-17T05:05:05.483868Z","shell.execute_reply.started":"2022-07-17T05:05:05.475545Z","shell.execute_reply":"2022-07-17T05:05:05.482786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1,3, figsize=(18,6))\nfor i, ax in enumerate(axes):\n    df = img_obj_channels[i].ravel()\n    sns.histplot(df, bins=np.arange(0,255), ax=ax)\n    ax.set_title(colors[i]+' channel')\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:36.530192Z","iopub.execute_input":"2022-07-17T04:08:36.530932Z","iopub.status.idle":"2022-07-17T04:08:38.363076Z","shell.execute_reply.started":"2022-07-17T04:08:36.530894Z","shell.execute_reply":"2022-07-17T04:08:38.361932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"배경에 대한 이미지 슬라이드\")\nfor i, channel in enumerate(img_bck_channels):\n    print(f\"Channel {i} values: min: {channel.min()}, max: {channel.max()}, average: {channel.mean()}\")","metadata":{"execution":{"iopub.status.busy":"2022-07-17T05:05:13.317008Z","iopub.execute_input":"2022-07-17T05:05:13.318319Z","iopub.status.idle":"2022-07-17T05:05:13.325765Z","shell.execute_reply.started":"2022-07-17T05:05:13.31827Z","shell.execute_reply":"2022-07-17T05:05:13.324495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(1,3, figsize=(18,6))\nfor i, ax in enumerate(axes):\n    df = img_bck_channels[i].ravel()\n    sns.histplot(df, bins=np.arange(0,255), ax=ax)\n    ax.set_title(colors[i]+' channel')\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:38.376188Z","iopub.execute_input":"2022-07-17T04:08:38.376676Z","iopub.status.idle":"2022-07-17T04:08:40.44079Z","shell.execute_reply.started":"2022-07-17T04:08:38.376629Z","shell.execute_reply":"2022-07-17T04:08:40.439497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Centers.plot.bar(rot=0) \n\nplt.show()를 통해 본 대상과 배경의 차이 -> 색상 채널에서 대상이 있는 이미지의 값 범위가 넓고(표준 오차가 높음) 배경 채널의 값이 좁다고 가정하면 이 속성을 사용하여 이미지를 구분할 수 있습니다. 그들 사이에. 또한 우리는 3개의 색상 채널을 사용할 필요가 없습니다. 3개의 채널 모두에서 차이가 상당하다는 것을 알 수 있습니다. 따라서 회색조로 이미지를 읽는 것도 작업을 수행해야 합니다.\n\n참고: 회색조 이미지로 작업할 때 각 픽셀은 이제 0에서 1 사이의 강도 값입니다.","metadata":{}},{"cell_type":"code","source":"imgs_object = []\nimgs_backgr = []\n\nfor i in img_obj_ids:\n    img = io.imread(sliced_train_images[i])\n    imgs_object.append(rgb2gray(img))\n    \nfor i in img_bck_ids:\n    img = io.imread(sliced_train_images[i])\n    imgs_backgr.append(rgb2gray(img))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:40.442168Z","iopub.execute_input":"2022-07-17T04:08:40.442491Z","iopub.status.idle":"2022-07-17T04:08:40.826654Z","shell.execute_reply.started":"2022-07-17T04:08:40.442462Z","shell.execute_reply":"2022-07-17T04:08:40.825284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"std_dev_obj = []\nfig, axes = plt.subplots(2,3, figsize=(18,6))\nfor i, ax in enumerate(axes.flat):\n    img_matrix = imgs_object[i].ravel()\n    std_dev = np.std(img_matrix)\n    std_dev_obj.append(std_dev)\n    sns.histplot(img_matrix, bins=np.arange(0,1, 0.01), ax=ax)\n    ax.text(0.05,0.85, f'std dev: {std_dev:.2f}', size=15, transform = ax.transAxes)\n    ax.set_title(f'img {i}') \nplt.suptitle('Histograms for images w. object')\nplt.tight_layout()\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:40.828373Z","iopub.execute_input":"2022-07-17T04:08:40.828774Z","iopub.status.idle":"2022-07-17T04:08:48.653257Z","shell.execute_reply.started":"2022-07-17T04:08:40.828739Z","shell.execute_reply":"2022-07-17T04:08:48.65209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(2,3, figsize=(18,6))\nfor i, ax in enumerate(axes.flat):\n    img_matrix = imgs_backgr[i].ravel()\n    std_dev = np.std(img_matrix)\n    std_dev_obj.append(std_dev)\n    sns.histplot(img_matrix, bins=np.arange(0,1, 0.01), ax=ax)\n    ax.text(0.05,0.85, f'std_dev: {std_dev:.2f}', size=15, transform = ax.transAxes)\n    ax.set_title(f'img {i}')  \nplt.suptitle('Histogram for images wo. object')\nplt.tight_layout()\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-07-17T04:08:48.655015Z","iopub.execute_input":"2022-07-17T04:08:48.655392Z","iopub.status.idle":"2022-07-17T04:08:56.05926Z","shell.execute_reply.started":"2022-07-17T04:08:48.655359Z","shell.execute_reply":"2022-07-17T04:08:56.058101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}