{"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":"code","source":"!pip install -q ffmpeg-python","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:43:08.366246Z","iopub.execute_input":"2023-11-07T13:43:08.366543Z","iopub.status.idle":"2023-11-07T13:43:15.654130Z","shell.execute_reply.started":"2023-11-07T13:43:08.366498Z","shell.execute_reply":"2023-11-07T13:43:15.653118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')\nimport cv2\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport random\nimport ffmpeg\nfrom IPython.display import Video\nfrom tqdm import tqdm\nimport tensorflow as tf\nimport tensorflow_addons as tfa\nimport logging\nfrom itertools import cycle\n\nlogging.disable(logging.WARNING)\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' \n\n\nplt.style.use('ggplot')\ncm = sns.light_palette(\"green\", as_cmap=True)\npd.option_context('display.max_colwidth', 100)\ncolor_pal = plt.rcParams[\"axes.prop_cycle\"].by_key()[\"color\"]\ncolor_cycle = cycle(plt.rcParams[\"axes.prop_cycle\"].by_key()[\"color\"])","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:35.267158Z","iopub.execute_input":"2023-11-07T13:26:35.267452Z","iopub.status.idle":"2023-11-07T13:26:35.278173Z","shell.execute_reply.started":"2023-11-07T13:26:35.267417Z","shell.execute_reply":"2023-11-07T13:26:35.276971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SEED EVERYTHING\nrandom.seed(hash(\"setting random seeds\") % 2**32 - 1)\nnp.random.seed(hash(\"improves reproducibility\") % 2**32 - 1)\n\n# config\nclass config:\n    BASE_DIR = \"../input/tensorflow-great-barrier-reef/train_images/\"","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:35.279778Z","iopub.execute_input":"2023-11-07T13:26:35.279984Z","iopub.status.idle":"2023-11-07T13:26:35.295250Z","shell.execute_reply.started":"2023-11-07T13:26:35.279961Z","shell.execute_reply":"2023-11-07T13:26:35.293733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_og = plt.imread('../input/tensorflow-great-barrier-reef/train_images/video_1/9101.jpg')\nimg_9101 = cv2.imread('../input/tensorflow-great-barrier-reef/train_images/video_1/9101.jpg')","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:35.296948Z","iopub.execute_input":"2023-11-07T13:26:35.297259Z","iopub.status.idle":"2023-11-07T13:26:35.416946Z","shell.execute_reply.started":"2023-11-07T13:26:35.297224Z","shell.execute_reply":"2023-11-07T13:26:35.416030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('../input/tensorflow-great-barrier-reef/train.csv')\ntrain_dir = \"../input/tensorflow-great-barrier-reef/train_images\"\ndf['image_path'] = train_dir + \"/video_\" + df['video_id'].astype(str) + \"/\" + df['video_frame'].astype(str) + \".jpg\"\ndf.head().style.set_properties(**{'background-color': 'black',\n                           'color': 'lawngreen',\n                           'border-color': 'white'})","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:35.418979Z","iopub.execute_input":"2023-11-07T13:26:35.419199Z","iopub.status.idle":"2023-11-07T13:26:35.592968Z","shell.execute_reply.started":"2023-11-07T13:26:35.419173Z","shell.execute_reply":"2023-11-07T13:26:35.591827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.info() # lets check more details about the data","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:35.594003Z","iopub.execute_input":"2023-11-07T13:26:35.594202Z","iopub.status.idle":"2023-11-07T13:26:35.617285Z","shell.execute_reply.started":"2023-11-07T13:26:35.594176Z","shell.execute_reply":"2023-11-07T13:26:35.616357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[df.annotations.str.len() > 2].head(5).style.background_gradient(cmap=cm) # filling up the annotation column","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:35.618813Z","iopub.execute_input":"2023-11-07T13:26:35.619072Z","iopub.status.idle":"2023-11-07T13:26:35.652202Z","shell.execute_reply.started":"2023-11-07T13:26:35.619041Z","shell.execute_reply":"2023-11-07T13:26:35.651284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['annotations'] = df['annotations'].apply(eval)\ndf_train_v2 = df[df.annotations.str.len() > 0 ].reset_index(drop=True)\ndf_train_v2.head(5).style.background_gradient(cmap='Reds')","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:35.653398Z","iopub.execute_input":"2023-11-07T13:26:35.654436Z","iopub.status.idle":"2023-11-07T13:26:36.111502Z","shell.execute_reply.started":"2023-11-07T13:26:35.654370Z","shell.execute_reply":"2023-11-07T13:26:36.110842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# What is Sequence and its properties:","metadata":{}},{"cell_type":"code","source":"df_train_v2[\"no_of_bbox\"] = df_train_v2[\"annotations\"].apply(lambda x: len(x))\ndf_train_v2[\"sequence\"].value_counts(), len(df_train_v2[\"sequence\"].value_counts())","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:36.113007Z","iopub.execute_input":"2023-11-07T13:26:36.113493Z","iopub.status.idle":"2023-11-07T13:26:36.125800Z","shell.execute_reply.started":"2023-11-07T13:26:36.113456Z","shell.execute_reply":"2023-11-07T13:26:36.125122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(3):\n    print(df_train_v2[\"sequence\"][df_train_v2[\"video_id\"] == i].unique(), \n          df_train_v2[\"sequence\"][df_train_v2[\"video_id\"] == i].nunique())","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:36.127695Z","iopub.execute_input":"2023-11-07T13:26:36.128203Z","iopub.status.idle":"2023-11-07T13:26:36.145378Z","shell.execute_reply.started":"2023-11-07T13:26:36.128167Z","shell.execute_reply":"2023-11-07T13:26:36.144277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Bounding box analysis in each video:","metadata":{}},{"cell_type":"code","source":"def plot_with_count(df,vid):\n    names = df[\"bbox_typ\"].to_list()\n    values = df[\"counts\"].to_list()\n\n    N = len(names)\n    menMeans = values\n    ind = np.arange(N)\n\n    plt.rcParams[\"figure.figsize\"] = [7.00, 3.50]\n    plt.rcParams[\"figure.autolayout\"] = True\n    fig, ax = plt.subplots(figsize=(15,6))\n\n    ax.bar(ind,menMeans,width=0.4)\n    plt.xticks(np.arange(0, N, step=1))\n    plt.title(f\"Number of bounding box VS Count of Bounding Box: Video{vid} \",fontsize=20)\n\n    plt.xlabel('Number of bounding box', fontsize=18)\n    plt.ylabel('Count', fontsize=16)\n\n    for index,data in enumerate(menMeans):\n        plt.text(x=index , y =data+1 , s=f\"{data}\" , fontdict=dict(fontsize=15))","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:36.146885Z","iopub.execute_input":"2023-11-07T13:26:36.147281Z","iopub.status.idle":"2023-11-07T13:26:36.156022Z","shell.execute_reply.started":"2023-11-07T13:26:36.147247Z","shell.execute_reply":"2023-11-07T13:26:36.155398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vid = 0\ndf_vod0_bbox_cnt = df_train_v2[\"no_of_bbox\"][df_train_v2[\"video_id\"] == vid].value_counts().reset_index() # LEARNING .to_frame() and .reset_index()\ndf_vod0_bbox_cnt.columns = ['bbox_typ', 'counts']\nplot_with_count(df_vod0_bbox_cnt,vid)","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:36.157993Z","iopub.execute_input":"2023-11-07T13:26:36.158551Z","iopub.status.idle":"2023-11-07T13:26:36.502217Z","shell.execute_reply.started":"2023-11-07T13:26:36.158495Z","shell.execute_reply":"2023-11-07T13:26:36.501285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vid = 1\ndf_vod1_bbox_cnt = df_train_v2[\"no_of_bbox\"][df_train_v2[\"video_id\"] == vid].value_counts().reset_index() # LEARNING .to_frame() and .reset_index()\ndf_vod1_bbox_cnt.columns = ['bbox_typ', 'counts']\nplot_with_count(df_vod1_bbox_cnt,vid)","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:36.503428Z","iopub.execute_input":"2023-11-07T13:26:36.503711Z","iopub.status.idle":"2023-11-07T13:26:36.874918Z","shell.execute_reply.started":"2023-11-07T13:26:36.503676Z","shell.execute_reply":"2023-11-07T13:26:36.873918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vid = 2\ndf_vod2_bbox_cnt = df_train_v2[\"no_of_bbox\"][df_train_v2[\"video_id\"] == vid].value_counts().reset_index() # LEARNING .to_frame() and .reset_index()\ndf_vod2_bbox_cnt.columns = ['bbox_typ', 'counts']\nplot_with_count(df_vod2_bbox_cnt,vid)","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:36.879520Z","iopub.execute_input":"2023-11-07T13:26:36.881055Z","iopub.status.idle":"2023-11-07T13:26:37.279056Z","shell.execute_reply.started":"2023-11-07T13:26:36.881000Z","shell.execute_reply":"2023-11-07T13:26:37.278500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# https://www.kaggle.com/julian3833/reef-a-cv-strategy-subsequences\ndf = pd.read_csv(\"/kaggle/input/tensorflow-great-barrier-reef/train.csv\")\ndf['annotations'] = df['annotations'].apply(eval)\ndf['n_annotations'] = df['annotations'].str.len()\ndf['has_annotations'] = df['annotations'].str.len() > 0\ndf['has_2_or_more_annotations'] = df['annotations'].str.len() >= 2\ndf['doesnt_have_annotations'] = df['annotations'].str.len() == 0\ndf['image_path'] = config.BASE_DIR + \"video_\" + df['video_id'].astype(str) + \"/\" + df['video_frame'].astype(str) + \".jpg\"","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:37.280024Z","iopub.execute_input":"2023-11-07T13:26:37.281022Z","iopub.status.idle":"2023-11-07T13:26:37.561070Z","shell.execute_reply.started":"2023-11-07T13:26:37.280991Z","shell.execute_reply":"2023-11-07T13:26:37.560216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_agg = df.groupby([\"video_id\", 'sequence']).agg({'sequence_frame': 'count', 'has_annotations': 'sum', 'doesnt_have_annotations': 'sum'})\\\n           .rename(columns={'sequence_frame': 'Total Frames', 'has_annotations': 'Frames with at least 1 object', 'doesnt_have_annotations': \"Frames with no object\"})\ndf_agg","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:26:37.562362Z","iopub.execute_input":"2023-11-07T13:26:37.562619Z","iopub.status.idle":"2023-11-07T13:26:37.591653Z","shell.execute_reply.started":"2023-11-07T13:26:37.562589Z","shell.execute_reply":"2023-11-07T13:26:37.590612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The point I want to make over here is that, In the pipeline we need to add more images with no lables, because there are many images in the private test case which has zero objects associated with it. But we cant actually infuse some unlabeled/no object image into the pipeline coz there are 80% of the total dataset present in that unlabeled/no object iamge categoury. So to do that we first need to choose a percentage in which we want to make the combiniation of both labeled and unlabeled image. So, say we deceide to take 6k img where 5k has object and 1k has not. Now the problem comes down to how to choose these 1k images. I would say choose few sequence and keep all of the unlabeled/no object images in the dataset and do that untill you get near 1k images. You might need to hand pich for each fold. I was thinking about using the fold CSVs generated from julian's NB and instade of filtering out all the unlabeled/no object images, keep some of them and train the whole network using that.","metadata":{}},{"cell_type":"markdown","source":"### Future work:\n- Add plots on distribution of height and width of the bbox provided\n- Add plots on distribution of area of the bbox provided","metadata":{}},{"cell_type":"markdown","source":"# 🎨 **Some Data Preparation:**","metadata":{}},{"cell_type":"code","source":"def RecoverCLAHE(sceneRadiance):\n    clahe = cv2.createCLAHE(clipLimit=7, tileGridSize=(14, 14))\n    for i in range(3):\n        sceneRadiance[:, :, i] = clahe.apply((sceneRadiance[:, :, i]))\n    return sceneRadiance\n\ndest_path1 = \"./clahe_img\"\nos.mkdir(dest_path1)\n\nfor img_path in tqdm(df_train_v2[\"image_path\"][0:400]):\n\n    image = plt.imread(img_path)\n    image_cv = cv2.imread(img_path)\n    img_clahe = RecoverCLAHE(image_cv)\n    file_name = img_path.split(\"/\")[-1]\n    \n    cv2.imwrite(dest_path1+\"/\"+file_name, img_clahe)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-11-07T13:26:37.593272Z","iopub.execute_input":"2023-11-07T13:26:37.593643Z","iopub.status.idle":"2023-11-07T13:27:15.115375Z","shell.execute_reply.started":"2023-11-07T13:26:37.593613Z","shell.execute_reply":"2023-11-07T13:27:15.114403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dest_path1 = \"./annot_img\"\nos.mkdir(dest_path1)\n\nidx = 0\nfor img_idx in tqdm(df_train_v2[\"image_path\"][0:400]):\n    file_name = img_idx.split(\"/\")[-1] \n    img_path = os.path.join(\"./clahe_img\",file_name)\n    image = plt.imread(img_path)\n\n\n    for i in range(len(df_train_v2[\"annotations\"][idx])):\n        file_name = img_path.split('/')[-1]\n        b_boxs = df_train_v2[\"annotations\"][idx][i]\n        x,y,w,h = b_boxs[\"x\"],b_boxs[\"y\"],b_boxs[\"width\"],b_boxs[\"height\"]\n\n        image = cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 3)\n        image = cv2.putText(image, 'starfish', (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36,255,12), 2)\n\n    cv2.imwrite(dest_path1+\"/\"+file_name, image)\n    idx +=1","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-11-07T13:27:15.116687Z","iopub.execute_input":"2023-11-07T13:27:15.116940Z","iopub.status.idle":"2023-11-07T13:27:30.817120Z","shell.execute_reply.started":"2023-11-07T13:27:15.116907Z","shell.execute_reply":"2023-11-07T13:27:30.816578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🧽 **Lets see that SpongeBob thinks about the images:**","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize = (12,15))\n\n\nplt.rcParams[\"figure.figsize\"] = [20.00, 10.50]\nplt.rcParams[\"figure.autolayout\"] = True\nim = plt.imread('../input/random-images-dataset/Wow (1).png') # insert local path of the image.\nfig, ax = plt.subplots(figsize=(20,6))\n\nax.imshow(plt.imread(\"../input/tensorflow-great-barrier-reef/train_images/video_0/40.jpg\"));\nnewax = fig.add_axes([0.3,0.3,0.6,0.7], anchor='NE', zorder=1)\nnewax.imshow(im);\n\nnewax.axis('off')\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:27:30.818118Z","iopub.execute_input":"2023-11-07T13:27:30.818296Z","iopub.status.idle":"2023-11-07T13:27:31.390221Z","shell.execute_reply.started":"2023-11-07T13:27:30.818270Z","shell.execute_reply":"2023-11-07T13:27:31.389467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Lets check we have images with same size or not:","metadata":{}},{"cell_type":"code","source":"img_sizes = []\nfor i in df_train_v2[\"image_path\"]:\n    img_sizes.append(plt.imread(i).shape)\n\nnp.unique(img_sizes)","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:27:31.391308Z","iopub.execute_input":"2023-11-07T13:27:31.391518Z","iopub.status.idle":"2023-11-07T13:30:31.843285Z","shell.execute_reply.started":"2023-11-07T13:27:31.391491Z","shell.execute_reply":"2023-11-07T13:30:31.842117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# lets check total number of images with annotations\nlen(df_train_v2)","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:31.844562Z","iopub.execute_input":"2023-11-07T13:30:31.844832Z","iopub.status.idle":"2023-11-07T13:30:31.849488Z","shell.execute_reply.started":"2023-11-07T13:30:31.844801Z","shell.execute_reply":"2023-11-07T13:30:31.848892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🦀 **Lets see what Mr: krabe has to say about the annotations:** ","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize = (12,15))\n\n\nplt.figure(figsize = (12,15))\n\n\nplt.rcParams[\"figure.figsize\"] = [20.00, 10.50]\nplt.rcParams[\"figure.autolayout\"] = True\nim = plt.imread('../input/random-images-dataset/Wow.png') # insert local path of the image.\nfig, ax = plt.subplots(figsize=(20,6))\n\nax.imshow(plt.imread(\"./annot_img/40.jpg\"))\n\nnewax = fig.add_axes([0.26,0.2,0.6,0.6], anchor='NE', zorder=1)\nnewax.imshow(im)\n\nnewax.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:31.850327Z","iopub.execute_input":"2023-11-07T13:30:31.851016Z","iopub.status.idle":"2023-11-07T13:30:32.423366Z","shell.execute_reply.started":"2023-11-07T13:30:31.850989Z","shell.execute_reply":"2023-11-07T13:30:32.422655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 📪 **80% of the data has not objects:** ","metadata":{}},{"cell_type":"code","source":"count_bbox = []\nfor i in df[\"annotations\"]:\n    count_bbox.append(len(i))\n    \nfrom collections import defaultdict\n\n\nbbox_dict = defaultdict(int)\n\nfor val in count_bbox:\n    bbox_dict[val] += 1\n    \n\nnames = list(bbox_dict.keys())\nvalues = list(bbox_dict.values())\n\nN = len(list(bbox_dict.values()))\nmenMeans = list(bbox_dict.values())\nind = np.arange(N)\n\nplt.rcParams[\"figure.figsize\"] = [20.00, 10.50]\nplt.rcParams[\"figure.autolayout\"] = True\nim = plt.imread('../input/random-images-dataset/Number of bounding box VS Count of Bounding Boxlittle one.png') # insert local path of the image.\nfig, ax = plt.subplots(figsize=(20,6))\n\nax.bar(ind,menMeans,width=0.4)\nplt.xticks(np.arange(0, N, step=1))\nplt.title(\"Number of bounding box VS Count of Bounding Box\",fontsize=20)\n\nplt.xlabel('Number of bounding box', fontsize=18)\nplt.ylabel('Count', fontsize=16)\nfor index,data in enumerate(menMeans):\n    plt.text(x=index , y =data+1 , s=f\"{data}\" , fontdict=dict(fontsize=20))\nnewax = fig.add_axes([0.3,0.35,0.6,0.5], anchor='NE', zorder=1)\nnewax.imshow(im)\n\nnewax.axis('off')\n\nplt.show()","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-11-07T13:30:32.424336Z","iopub.execute_input":"2023-11-07T13:30:32.424546Z","iopub.status.idle":"2023-11-07T13:30:32.870373Z","shell.execute_reply.started":"2023-11-07T13:30:32.424503Z","shell.execute_reply":"2023-11-07T13:30:32.869877Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> <font size=\"4\" face=\"verdana\">\n            <b>\"professor\" Squidward:</b>  Well seem like there are more empty bounding boxes, the fill ones.\n        </font>\n        \n<center><div class=\"alert alert-block alert-warning\" style=\"margin: 2em; line-height: 1.7em; font-family: Verdana;\">\n    There are alot of things to discover from this dataset. So keep a eye on the EDA part Im surely going to update that.\n</div></center>","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 📊 **How to perform histogram equalization?**\nHistogram Equalization is a method of contrast adjustment based on the image's histogram.\n\n> In this image the pixel values are are between 0-255, but we will not find any pixel values which are exactly 0 or 255, it does not have any image which is pure white or pure black.If we apply the histogram equalization then it will reduce the color depth.Currently the minimum pixel value is 52 and the highest is 255.\nAfter you apply histogram equalization, you will find the the min pixel value now got transformed to zero and the max got converted to 255. So, notice again how the min and max values are equalized between 0 and 255, we also see less shade of gray.(view fig1 to 2)\n\n<img src=\"https://i.imgur.com/mWTXqZ4.png\" style=\"width:500px;height:250px;\">\n<center><p style=\"padding-left:380px;color:red\">Fig1:before applying histogram equalization</p></center>\n\n<img src=\"https://i.imgur.com/5diUO7c.png\" style=\"width:500px;height:250px;\">\n<center><p style=\"padding-left:380px;color:red\">Fig2: After applying histogram equalization</p></center>\n\n> Again, now we have a image on the left hand side and it's coresponding histogram(in red) on the right the black line is nothing but the cumulative of the pixel values.So, after we apply the Histogram equalizer that cumulative changes to linear step function. Notice that we don't literally flatten out the histogram we only just focus on the cumulative linear. And the real mathematics behind the Histogram equalization is just like that.(view fig 3 to 5)\n<img src=\"https://i.imgur.com/uIBnzbu.png\" style=\"width:500px;height:250px;\">\n\n<center><p style=\"padding-left:380px;color:red\">Fig3:before applying histogram equalization</p></center>\n\n<img src=\"https://i.imgur.com/fuIGrCi.png\" style=\"width:500px;height:250px;\">\n\n<center><p style=\"padding-left:380px;color:red\">Fig4: After applying histogram equalization</p></center>\n\n<img src=\"https://i.imgur.com/9q3NVIg.png\" style=\"width:500px;height:250px;\">\n<center><p style=\"padding-left:380px;color:red\">Fig5:Main difference </p></center>\n\nWe mainly use histogram equalization when we need to increase the contrast of the image.","metadata":{}},{"cell_type":"code","source":"def he_hsv(img_demo):\n    img_hsv = cv2.cvtColor(img_demo, cv2.COLOR_RGB2HSV)\n\n    # Histogram equalisation on the V-channel\n    img_hsv[:, :, 2] = cv2.equalizeHist(img_hsv[:, :, 2])\n\n    # convert image back from HSV to RGB\n    image_hsv = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2RGB)\n    \n    return image_hsv","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:32.871231Z","iopub.execute_input":"2023-11-07T13:30:32.871929Z","iopub.status.idle":"2023-11-07T13:30:32.877298Z","shell.execute_reply.started":"2023-11-07T13:30:32.871903Z","shell.execute_reply":"2023-11-07T13:30:32.875934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_img(img_dir,num_items,func,mode):\n    img_list = random.sample(os.listdir(img_dir), num_items)\n\n    for i in range(len(img_list)):\n        full_path = img_dir + '/' + img_list[i]\n        img_temp1 = plt.imread(full_path)\n        img_temp_cv = cv2.imread(full_path)\n        plt.figure(figsize=(20,15))\n        plt.subplot(1,2,1)\n        plt.imshow(img_temp1);\n        plt.subplot(1,2,2)\n        if mode == 'plt':\n            plt.imshow(func(img_temp1));\n        elif mode == 'cv2':\n            plt.imshow(func(img_temp_cv));","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:32.878424Z","iopub.execute_input":"2023-11-07T13:30:32.878689Z","iopub.status.idle":"2023-11-07T13:30:32.890675Z","shell.execute_reply.started":"2023-11-07T13:30:32.878662Z","shell.execute_reply":"2023-11-07T13:30:32.889139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vid_0_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\nnum_items1 = 4\nplot_img(vid_0_dir,num_items1,he_hsv,\"plt\")","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:32.892335Z","iopub.execute_input":"2023-11-07T13:30:32.893683Z","iopub.status.idle":"2023-11-07T13:30:37.991514Z","shell.execute_reply.started":"2023-11-07T13:30:32.893632Z","shell.execute_reply":"2023-11-07T13:30:37.990573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🧩 **HE code from the repo:**\n\n- below is the code from the repo\n- check out the Code from the repo [here](https://github.com/wangyanckxx/Single-Underwater-Image-Enhancement-and-Color-Restoration/tree/master/Underwater%20Image%20Enhancement/HE )\n- It is basically allpying Histogram Equalizers in each channel","metadata":{}},{"cell_type":"code","source":"def RecoverHE(sceneRadiance):\n    for i in range(3):\n        sceneRadiance[:, :, i] =  cv2.equalizeHist(sceneRadiance[:, :, i])\n    return sceneRadiance\n\nvid_0_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\nnum_items1 = 4\nplot_img(vid_0_dir,num_items1,RecoverHE,\"cv2\")","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:37.992949Z","iopub.execute_input":"2023-11-07T13:30:37.993199Z","iopub.status.idle":"2023-11-07T13:30:42.101916Z","shell.execute_reply.started":"2023-11-07T13:30:37.993172Z","shell.execute_reply":"2023-11-07T13:30:42.100596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🔮 **CLAHE: without repo code:**\n\n> Contrast Limited AHE (CLAHE) differs from adaptive histogram equalization in its contrast limiting. In the case of CLAHE, the contrast limiting procedure is applied to each neighborhood from which a transformation function is derived. CLAHE was developed to prevent the over amplification of noise that adaptive histogram equalization can give rise to.\n\n> We apply CLAHE to color images, where usually it is applied on the luminance channel and the results after equalizing only the luminance channel of an HSV image are much better than equalizing all the channels of the BGR image. \n\n<div class=\"alert alert-block alert-info\">\n<b>Note:</b> Each pixel in a image has brightness level, called luminance. This value is between 0 to 1, where 0 means complete darkness (black), and 1 is brightest (white)\n</div>\n\n","metadata":{}},{"cell_type":"code","source":"def clahe_hsv(img):\n    hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)\n\n    h, s, v = hsv_img[:,:,0], hsv_img[:,:,1], hsv_img[:,:,2]\n    clahe = cv2.createCLAHE(clipLimit = 15.0, tileGridSize = (20,20))\n    v = clahe.apply(v)\n\n    hsv_img = np.dstack((h,s,v))\n\n    rgb = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)\n    \n    return rgb\n\n\nvid_0_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\nnum_items1 = 4\nplot_img(vid_0_dir,num_items1,clahe_hsv,\"cv2\")","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:42.103387Z","iopub.execute_input":"2023-11-07T13:30:42.103632Z","iopub.status.idle":"2023-11-07T13:30:46.079231Z","shell.execute_reply.started":"2023-11-07T13:30:42.103603Z","shell.execute_reply":"2023-11-07T13:30:46.078397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🥏 **CLAHE: with repo code:**","metadata":{}},{"cell_type":"code","source":"def RecoverCLAHE(sceneRadiance):\n    clahe = cv2.createCLAHE(clipLimit=7, tileGridSize=(14, 14))\n    for i in range(3):\n\n        \n        sceneRadiance[:, :, i] = clahe.apply((sceneRadiance[:, :, i]))\n\n\n    return sceneRadiance\n\nvid_0_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\nnum_items1 = 4\nplot_img(vid_0_dir,num_items1,RecoverCLAHE,\"cv2\")","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:46.080388Z","iopub.execute_input":"2023-11-07T13:30:46.080986Z","iopub.status.idle":"2023-11-07T13:30:49.953739Z","shell.execute_reply.started":"2023-11-07T13:30:46.080957Z","shell.execute_reply":"2023-11-07T13:30:49.952293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"> <font size=\"4\" face=\"verdana\">\n            From the image, it seems like all the rocks, plants, and other underwater objects are on the ground and sunlight falling upon them, not inside a sea.\n        </font>","metadata":{}},{"cell_type":"markdown","source":"# 🪀 **GC: without repo code:**\n\n> Different camera or video recorder devices do not correctly capture luminance. (they are not linear) Different display devices (monitor, phone screen, TV) do not display luminance correctly neither. So, one needs to correct them, therefore the gamma correction function. Gamma correction function is a function that maps luminance levels to compensate the non-linear luminance effect of display devices (or sync it to human perceptive bias on brightness). For example check out the below image,\n\n\n<p align=\"center\">\n    <img width=\"600\" src=\"https://i.imgur.com/2GLA50Q.png\">\n</p>\n\n\n<div class=\"alert alert-block alert-info\">\n<b>Source:</b> https://medium.com/giscle/how-we-utilized-gamma-correction-for-increasing-our-training-data-47c16a040adc\n<br>\n<b>Check out more about GC, here :</b> https://en.wikipedia.org/wiki/Gamma_correction\n</div>\n","metadata":{}},{"cell_type":"code","source":"def gamma_enhancement(image,gamma):\n    R = 255.0\n    return (R * np.power(image.astype(np.uint32)/R, gamma)).astype(np.uint8)\n\nplt.figure(figsize=(20,15))\nplt.subplot(2,2,1)\nplt.imshow(img_og);\nplt.subplot(2,2,2)\nplt.imshow(gamma_enhancement(img_9101,1/0.6))\n\nplt.subplot(2,2,3)\nplt.imshow(img_og);\nplt.subplot(2,2,4)\nplt.imshow(gamma_enhancement(img_og,1/0.6))\n","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:49.955559Z","iopub.execute_input":"2023-11-07T13:30:49.956240Z","iopub.status.idle":"2023-11-07T13:30:52.066662Z","shell.execute_reply.started":"2023-11-07T13:30:49.956202Z","shell.execute_reply":"2023-11-07T13:30:52.065564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🖌 **GC: with repo code:**","metadata":{}},{"cell_type":"code","source":"def RecoverGC(sceneRadiance):\n    sceneRadiance = sceneRadiance/255.0\n    \n    for i in range(3):\n        sceneRadiance[:, :, i] =  np.power(sceneRadiance[:, :, i] / float(np.max(sceneRadiance[:, :, i])), 3.2)\n    sceneRadiance = np.clip(sceneRadiance*255, 0, 255)\n    sceneRadiance = np.uint8(sceneRadiance)\n    return sceneRadiance\n\nvid_0_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\nnum_items1 = 4\nplot_img(vid_0_dir,num_items1,RecoverGC,\"cv2\")","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:30:52.067934Z","iopub.execute_input":"2023-11-07T13:30:52.068115Z","iopub.status.idle":"2023-11-07T13:30:57.255090Z","shell.execute_reply.started":"2023-11-07T13:30:52.068091Z","shell.execute_reply":"2023-11-07T13:30:57.254459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 📍 **ICM: with repo code**","metadata":{}},{"cell_type":"code","source":"import numpy as np\n\ndef global_stretching(img_L,height, width):\n    I_min = np.min(img_L)\n    I_max = np.max(img_L)\n    I_mean = np.mean(img_L)\n\n    array_Global_histogram_stretching_L = np.zeros((height, width))\n    for i in range(0, height):\n        for j in range(0, width):\n            p_out = (img_L[i][j] - I_min) * ((1) / (I_max - I_min))\n            array_Global_histogram_stretching_L[i][j] = p_out\n\n    return array_Global_histogram_stretching_L\n\ndef stretching(img):\n    height = len(img)\n    width = len(img[0])\n    for k in range(0, 3):\n        Max_channel  = np.max(img[:,:,k])\n        Min_channel  = np.min(img[:,:,k])\n        for i in range(height):\n            for j in range(width):\n                img[i,j,k] = (img[i,j,k] - Min_channel) * (255 - 0) / (Max_channel - Min_channel)+ 0\n    return img\n\nfrom skimage.color import rgb2hsv,hsv2rgb\nimport numpy as np\n\n\n\ndef  HSVStretching(sceneRadiance):\n    height = len(sceneRadiance)\n    width = len(sceneRadiance[0])\n    img_hsv = rgb2hsv(sceneRadiance)\n    h, s, v = cv2.split(img_hsv)\n    img_s_stretching = global_stretching(s, height, width)\n\n    img_v_stretching = global_stretching(v, height, width)\n\n    labArray = np.zeros((height, width, 3), 'float64')\n    labArray[:, :, 0] = h\n    labArray[:, :, 1] = img_s_stretching\n    labArray[:, :, 2] = img_v_stretching\n    img_rgb = hsv2rgb(labArray) * 255\n\n    \n\n    return img_rgb\n\ndef sceneRadianceRGB(sceneRadiance):\n\n    sceneRadiance = np.clip(sceneRadiance, 0, 255)\n    sceneRadiance = np.uint8(sceneRadiance)\n\n    return sceneRadiance","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-11-07T13:30:57.256203Z","iopub.execute_input":"2023-11-07T13:30:57.261135Z","iopub.status.idle":"2023-11-07T13:30:57.488047Z","shell.execute_reply.started":"2023-11-07T13:30:57.261076Z","shell.execute_reply":"2023-11-07T13:30:57.486115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def RecoverICM(img1):\n    img = stretching(img1)\n    sceneRadiance = sceneRadianceRGB(img)\n    sceneRadiance = HSVStretching(sceneRadiance)\n    sceneRadiance = sceneRadianceRGB(sceneRadiance)\n    \n    return sceneRadiance\n\n\nvid_0_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\nnum_items1 = 4\nplot_img(vid_0_dir,num_items1,RecoverICM,\"cv2\")","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-11-07T13:30:57.489461Z","iopub.execute_input":"2023-11-07T13:30:57.489815Z","iopub.status.idle":"2023-11-07T13:31:39.930474Z","shell.execute_reply.started":"2023-11-07T13:30:57.489779Z","shell.execute_reply":"2023-11-07T13:31:39.929345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🎯 **Main Working Code:**\n> I am using **`tfa.image.equalize`** for the preprocessing. You can also add this like that in the data augmentation pipeline. Im passing this as a function in the **`plot_img_tf`** function.","metadata":{}},{"cell_type":"code","source":"def plot_img_tf(img_dir,num_items,func,mode):\n    img_list = random.sample(os.listdir(img_dir), num_items)\n    full_path = img_dir + '/' + img_list[0]\n    img_temp_plt = plt.imread(full_path)\n    img_temp_cv = cv2.imread(full_path)\n    if mode==\"plt\":\n        \n        img_stack = np.hstack((img_temp_plt,func(img_temp_plt)))\n        plt.figure(figsize=(20,15))\n        plt.imshow(img_stack);\n        plt.title(\"Original Image VS Enhanced Image\",fontsize=25)\n        plt.axis(\"off\")\n        plt.show()\n    if mode==\"cv2\":\n        \n        img_stack = np.hstack((img_temp_cv,func(img_temp_cv)))\n        plt.figure(figsize=(20,15))\n        plt.imshow(img_stack);\n        plt.title(\"Original Image VS Enhanced Image\",fontsize=25)\n        plt.axis(\"off\")\n        plt.show()\n    \n    \n    for i in range(1, len(img_list)):\n        full_path = img_dir + '/' + img_list[i]\n        img_temp_plt = plt.imread(full_path)\n        img_temp_cv = cv2.imread(full_path)\n        if mode==\"plt\":\n            img_stack = np.hstack((img_temp_plt,func(img_temp_plt)));\n            plt.figure(figsize=(20,15))\n            plt.imshow(img_stack);\n            plt.axis(\"off\")\n            plt.show()\n        if mode==\"cv2\":\n            img_stack = np.hstack((img_temp_cv,func(img_temp_cv)));\n            plt.figure(figsize=(20,15))\n            plt.imshow(img_stack);\n            plt.axis(\"off\")\n            plt.show()\n\nimg_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\nnum_items = 4\nplot_img_tf(img_dir,num_items,tfa.image.equalize,\"plt\")","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:42:18.331090Z","iopub.execute_input":"2023-11-07T13:42:18.331380Z","iopub.status.idle":"2023-11-07T13:42:21.158566Z","shell.execute_reply.started":"2023-11-07T13:42:18.331349Z","shell.execute_reply":"2023-11-07T13:42:21.157579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# (\n#     ffmpeg.input('./clahe_img/*.jpg', pattern_type='glob', framerate=25)\n#     .output('img_movie.mp4')\n#     .run()\n# )","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-11-07T13:44:24.493419Z","iopub.execute_input":"2023-11-07T13:44:24.493691Z","iopub.status.idle":"2023-11-07T13:44:24.497608Z","shell.execute_reply.started":"2023-11-07T13:44:24.493665Z","shell.execute_reply":"2023-11-07T13:44:24.496770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# (\n#     ffmpeg.input('./annot_img/*.jpg', pattern_type='glob', framerate=25)\n#     .output('annot_movie.mp4')\n#     .run()\n# )","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-11-07T13:44:09.538118Z","iopub.execute_input":"2023-11-07T13:44:09.538953Z","iopub.status.idle":"2023-11-07T13:44:09.543574Z","shell.execute_reply.started":"2023-11-07T13:44:09.538906Z","shell.execute_reply":"2023-11-07T13:44:09.542446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Video(\"./img_movie.mp4\")","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:44:14.743853Z","iopub.execute_input":"2023-11-07T13:44:14.744161Z","iopub.status.idle":"2023-11-07T13:44:14.750020Z","shell.execute_reply.started":"2023-11-07T13:44:14.744117Z","shell.execute_reply":"2023-11-07T13:44:14.748587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Video(\"./annot_movie.mp4\")                   ","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:44:15.541501Z","iopub.execute_input":"2023-11-07T13:44:15.541836Z","iopub.status.idle":"2023-11-07T13:44:15.545822Z","shell.execute_reply.started":"2023-11-07T13:44:15.541796Z","shell.execute_reply":"2023-11-07T13:44:15.544916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport math\nimport numpy as np\nimport matplotlib.pyplot as plt\n\ndef DarkChannel(im, sz):\n    b, g, r = cv2.split(im)\n    dc = cv2.min(cv2.min(r, g), b)\n    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (sz, sz))\n    dark = cv2.erode(dc, kernel)\n    return dark\n\ndef AtmLight(im, dark):\n    [h, w] = im.shape[:2]\n    imsz = h * w\n    numpx = int(max(math.floor(imsz / 1000), 1))\n    darkvec = dark.reshape(imsz)\n    imvec = im.reshape(imsz, 3)\n\n    indices = darkvec.argsort()\n    indices = indices[imsz - numpx::]\n\n    atmsum = np.zeros([1, 3])\n    for ind in range(1, numpx):\n        atmsum = atmsum + imvec[indices[ind]]\n\n    A = atmsum / numpx\n    return A\n\ndef TransmissionEstimate(im, A, sz):\n    omega = 0.95\n    im3 = np.empty(im.shape, im.dtype)\n\n    for ind in range(0, 3):\n        im3[:, :, ind] = im[:, :, ind] / A[0, ind]\n\n    transmission = 1 - omega * DarkChannel(im3, sz)\n    return transmission\n\ndef Guidedfilter(im, p, r, eps):\n    mean_I = cv2.boxFilter(im, cv2.CV_64F, (r, r))\n    mean_p = cv2.boxFilter(p, cv2.CV_64F, (r, r))\n    mean_Ip = cv2.boxFilter(im * p, cv2.CV_64F, (r, r))\n    cov_Ip = mean_Ip - mean_I * mean_p\n\n    mean_II = cv2.boxFilter(im * im, cv2.CV_64F, (r, r))\n    var_I = mean_II - mean_I * mean_I\n\n    a = cov_Ip / (var_I + eps)\n    b = mean_p - a * mean_I\n\n    mean_a = cv2.boxFilter(a, cv2.CV_64F, (r, r))\n    mean_b = cv2.boxFilter(b, cv2.CV_64F, (r, r))\n\n    q = mean_a * im + mean_b\n    return q\n\ndef TransmissionRefine(im, et):\n    gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)\n    gray = np.float64(gray) / 255\n    r = 60\n    eps = 0.0001\n    t = Guidedfilter(gray, et, r, eps)\n\n    return t\n\ndef Recover(im, t, A, tx=0.1):\n    res = np.empty(im.shape, im.dtype)\n    t = cv2.max(t, tx)\n\n    for ind in range(0, 3):\n        res[:, :, ind] = (im[:, :, ind] - A[0, ind]) / t + A[0, ind]\n\n    return res\n\ndef ImageEnhancementWithDarkChannel(input_filename):\n    src = cv2.imread(input_filename)\n    I = src.astype('float64') / 255\n\n    dark = DarkChannel(I, 15)\n    A = AtmLight(I, dark)\n    te = TransmissionEstimate(I, A, 15)\n    t = TransmissionRefine(src, te)\n    J = Recover(I, t, A, 0.1)\n\n    # Resize the enhanced image to the desired dimensions\n    desired_height = 1080  # Replace with your desired height\n    desired_width = 1920  # Replace with your desired width\n    resized_image = cv2.resize(J * 255, (desired_width, desired_height))\n\n    # Display the resized image\n    plt.figure(figsize=(12, 6))\n    plt.subplot(131), plt.imshow(src), plt.title('Original Image')\n    plt.subplot(132), plt.imshow(dark, cmap='gray'), plt.title('Dark Channel')\n    plt.subplot(133), plt.imshow(resized_image), plt.title('Enhanced Image (Resized)')\n    plt.show()\n\n    # Save the resized image\n    cv2.imwrite(\"enhanced_image_resized.png\", resized_image)\n\nif __name__ == '__main__':\n    ImageEnhancementWithDarkChannel('../input/own-dark/input.png') ","metadata":{"execution":{"iopub.status.busy":"2023-11-07T14:59:04.156689Z","iopub.execute_input":"2023-11-07T14:59:04.156961Z","iopub.status.idle":"2023-11-07T14:59:05.179197Z","shell.execute_reply.started":"2023-11-07T14:59:04.156928Z","shell.execute_reply":"2023-11-07T14:59:05.178141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport random\nimport tensorflow_addons as tfa\n\n# Image Enhancement Functions\ndef he_hsv(img_demo):\n    img_hsv = cv2.cvtColor(img_demo, cv2.COLOR_RGB2HSV)\n    img_hsv[:, :, 2] = cv2.equalizeHist(img_hsv[:, :, 2])\n    image_hsv = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2RGB)\n    return image_hsv\n\ndef clahe_hsv(img):\n    hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)\n    h, s, v = hsv_img[:, :, 0], hsv_img[:, :, 1], hsv_img[:, :, 2]\n    clahe = cv2.createCLAHE(clipLimit=15.0, tileGridSize=(20, 20))\n    v = clahe.apply(v)\n    hsv_img = np.dstack((h, s, v))\n    rgb = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)\n    return rgb\n\ndef gamma_enhancement(image, gamma):\n    R = 255.0\n    return (R * np.power(image.astype(np.uint32) / R, gamma)).astype(np.uint8)\n\ndef image_enhancement_pipeline(image_path):\n    img = plt.imread(image_path)\n    \n    he_enhanced = he_hsv(img)\n    clahe_enhanced = clahe_hsv(img)\n    gc_enhanced = gamma_enhancement(img, 1/0.6)\n    \n    return img, he_enhanced, clahe_enhanced, gc_enhanced\n\n# Example usage:\nimage_path = '../input/tensorflow-great-barrier-reef/train_images/video_0/100.jpg'\noriginal, he_enhanced, clahe_enhanced, gc_enhanced = image_enhancement_pipeline(image_path)\n\n# Display the images\nplt.figure(figsize=(15, 5))\nplt.subplot(141), plt.imshow(original), plt.title('Original Image')\nplt.subplot(142), plt.imshow(he_enhanced), plt.title('HE Enhanced Image')\nplt.subplot(143), plt.imshow(clahe_enhanced), plt.title('CLAHE Enhanced Image')\nplt.subplot(144), plt.imshow(gc_enhanced), plt.title('Gamma Corrected Image')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-11-07T13:56:44.689378Z","iopub.execute_input":"2023-11-07T13:56:44.689637Z","iopub.status.idle":"2023-11-07T13:56:45.687585Z","shell.execute_reply.started":"2023-11-07T13:56:44.689612Z","shell.execute_reply":"2023-11-07T13:56:45.686550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport cv2\nfrom skimage import color\nimport matplotlib.pyplot as plt\n\ndef show(img, title):\n    plt.title(title)\n    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n    plt.savefig(title + '.jpg')\n    plt.show()\n\ndef color_compensation(img):\n    B, G, R = cv2.split(img)  # Split the image into B, G, R channels\n\n    Irm = np.mean(R) / 256.0\n    Igm = np.mean(G) / 256.0\n    Ibm = np.mean(B) / 256.0\n    a = 1\n    Irc = R + a * (Igm - Irm) * (1 - Irm) * G  # Compensate the red channel\n    Ibc = B + a * (Igm - Ibm) * (1 - Ibm) * G  # Compensate the blue channel\n\n    Irc = np.array(Irc, np.uint8)\n    Ibc = np.array(Ibc, np.uint8)\n\n    img_compensated = cv2.merge([Ibc, G, Irc])\n    show(img_compensated, \"color_compensation\")\n    return img_compensated\n\ndef gray_world(img):\n    R, G, B = cv2.split(img)\n\n    avg_R = np.mean(R)\n    avg_G = np.mean(G)\n    avg_B = np.mean(B)\n    avg_gray = (avg_R + avg_G + avg_B) / 3.0\n\n    scale_R = avg_gray / avg_R\n    scale_G = avg_gray / avg_G\n    scale_B = avg_gray / avg_B\n\n    R = cv2.convertScaleAbs(R * scale_R)\n    G = cv2.convertScaleAbs(G * scale_G)\n    B = cv2.convertScaleAbs(B * scale_B)\n\n    img_gray_world = cv2.merge([B, G, R])\n    show(img_gray_world, \"gray_world\")\n    return img_gray_world\n\ndef gamma_correction(img, gamma=1.3):\n    img = np.array(256 * (img / 256) ** gamma, np.uint8)\n    show(img, \"gamma_correction\")\n    return img\n\ndef sharpen(img):\n    filter1 = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])\n    img = cv2.filter2D(img, -1, filter1)\n    show(img, \"sharpen\")\n    return img\n\ndef gauss(shape=(3, 3), sigma=0.5):\n    # Define the Gaussian kernel for smoothing\n    m, n = [(ss-1.) / 2. for ss in shape]\n    y, x = np.ogrid[-m:m + 1, -n:n + 1]\n    h = np.exp(-(x * x + y * y) / (2. * sigma * sigma))\n    h[h < np.finfo(h.dtype).eps * h.max()] = 0\n    sumh = h.sum()\n    if sumh != 0:\n        h /= sumh\n    return h\n\ndef saliency_weight(img):\n    kernel = np.array(gauss((3, 3), 1))\n    gfrgb = cv2.filter2D(img, -1, kernel, borderType=cv2.BORDER_WRAP)\n    lab = color.rgb2lab(gfrgb)\n    l = np.double(lab[:, :, 0])\n    a = np.double(lab[:, :, 1])\n    b = np.double(lab[:, :, 2])\n    lm = np.mean(l)\n    am = np.mean(a)\n    bm = np.mean(b)\n    w = np.square(l - lm) + np.square(a - am) + np.square(b - bm)\n    return w\n\ndef laplacian_weight(img):\n    w = cv2.Laplacian(img, cv2.CV_64F)\n    w = cv2.convertScaleAbs(w)\n    return w\n\ndef saturation_weight(img, sigma=0.25, avg_=0.5):\n    w = np.exp(-(img - avg_)**2 / (2 * np.square(sigma))\n    return w\n\ndef weight_maps(img):\n    R = np.double(img[:, :, 2]) / 256  # Use the red channel for weight maps\n    WL = laplacian_weight(R)\n    WS = saliency_weight(img)\n    WSat = saturation_weight(R)\n    return WL, WS, WSat\n\ndef iexpand(image):\n    h = np.array([1, 4, 6, 4, 1]) / 16\n    filt = (h.T).dot(h)\n    outimage = np.zeros((image.shape[0] * 2, image.shape[1] * 2), dtype=np.float64)\n    outimage[::2, ::2] = image[:, :]\n    out = cv2.filter2D(outimage, cv2.CV_64F, filt)\n    return out\n\ndef ireduce(image):\n    h = np.array([1, 4, 6, 4, 1]) / 16\n    filt = (h.T).dot(h)\n    outimage = cv2.filter2D(image, cv2.CV_64F, filt)\n    out = outimage[::2, ::2]\n    return out\n\ndef gaussian_pyramid(image, depth=5):\n    output = []\n    output.append(image)\n    tmp = image\n    for i in range(0, depth):\n        tmp = ireduce(tmp)\n        output.append(tmp)\n    return output\n\ndef lapl_pyramid(img_pyr):\n    output = []\n    k = len(img_pyr)\n    for i in range(0, k - 1):\n        gu = img_pyr[i]\n        egu = iexpand(img_pyr[i + 1])\n        if egu.shape[0] > gu.shape[0]:\n            egu = np.delete(egu, (-1), axis=0)\n        if egu.shape[1] > gu.shape[1]:\n            egu = np.delete(egu, (-1), axis=1)\n        output.append(gu - egu)\n    output.append(img_pyr.pop())\n    return output\n\ndef collapse(img_pyr):\n    for i in range(len(img_pyr) - 1, 0, -1):\n        lap = iexpand(img_pyr[i])\n        lap_last_dim = img_pyr[i - 1]\n        if lap.shape[0] > lap_last_dim.shape[0]:\n            lap = np.delete(lap, (-1), axis=0)\n        if lap.shape[1] > lap_last_dim.shape[1]:\n            lap = np.delete(lap, (-1), axis=1)\n        tmp = lap + lap_last_dim\n    output = tmp\n    return output\n\ndef split_rgb(img):\n    (blue, green, red) = cv2.split(img)\n    return red, green, blue\n\ndef pyramid_op(img):\n    (R, G, B) = split_rgb(img)\n    R = gaussian_pyramid(R)\n    G = gaussian_pyramid(G)\n    B = gaussian_pyramid(B)\n    R = lapl_pyramid(R)\n    G = lapl_pyramid(G)\n    B = lapl_pyramid(B)\n    return R, G, B\n\nif __name__ == '__main__':\n    import sys\n    try:\n        input_filename = sys.argv[1]\n    except:\n        input_filename = '../input/tensorflow-great-barrier-reef/train_images/video_0/100.jpg'\n\n    img = cv2.imread(input_filename)\n    if img is None:\n        print(\"Error: Unable to load the image.\")\n    else:\n        print(f\"Image shape: {img.shape}\")\n        print(f\"Image data type: {img.dtype}\")\n\n        img = color_compensation(img)\n        img = gray_world(img)\n        img = gamma_correction(img)\n        img = sharpen(img)\n\n        (WL1, WS1, WSat1) = weight_maps(img)\n        (WL2, WS2, WSat2) = weight_maps(img)\n\n        W1 = (WL1 + WS1 + WSat1) / (WL1 + WS1 + WSat1 + WL2 + WS2 + WSat2)\n        W2 = (WL2 + WS2 + WSat2) / (WL1 + WS1 + WSat1 + WL2 + WS2 + WSat2)\n\n        W1 = gaussian_pyramid(W1, 5)\n        W2 = gaussian_pyramid(W2, 5)\n\n        img1 = cv2.imread(\"path_to_image1.jpg\")  # Replace with the actual path to image1\n        img2 = cv2.imread(\"path_to_image2.jpg\")  # Replace with the actual path to image2\n\n        # Perform pyramid operations on image 1 (img1)\n        r1, g1, b1 = pyramid_op(img1)\n\n        # Perform pyramid operations on image 2 (img2)\n        r2, g2, b2 = pyramid_op(img2)\n\n        R = np.array(W1) * r1 + np.array(W2) * r2\n        G = np.array(W1) * g1 + np.array(W2) * g2\n        B = np.array(W1) * b1 + np.array(W2) * b2\n\n        R = collapse(R)\n        G = collapse(G)\n        B = collapse(B)\n\n        R[R < 0] = 0\n        R[R > 255] = 255\n        R = np.array(R, np.uint8)\n\n        G[G < 0] = 0\n        G[G > 255] = 255\n        G = np.array(G, np.uint8)\n\n        B[B < 0] = 0\n        B[B > 255] = 255\n        B = np.array(B, np.uint8)\n\n        result = cv2.merge([B, G, R])\n\n        show(result, \"result\")\n        cv2.imwrite(\"enhanced_image.png\", result)\n","metadata":{"execution":{"iopub.status.busy":"2023-11-07T14:34:47.183284Z","iopub.execute_input":"2023-11-07T14:34:47.183553Z","iopub.status.idle":"2023-11-07T14:34:47.217666Z","shell.execute_reply.started":"2023-11-07T14:34:47.183502Z","shell.execute_reply":"2023-11-07T14:34:47.216753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport math\nimport numpy as np\nimport matplotlib.pyplot as plt\n\ndef DarkChannel(im, sz):\n    b, g, r = cv2.split(im)\n    dc = cv2.min(cv2.min(r, g), b)\n    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (sz, sz))\n    dark = cv2.erode(dc, kernel)\n    return dark\n\ndef AtmLight(im, dark):\n    [h, w] = im.shape[:2]\n    imsz = h * w\n    numpx = int(max(math.floor(imsz / 1000), 1))\n    darkvec = dark.reshape(imsz)\n    imvec = im.reshape(imsz, 3)\n\n    indices = darkvec.argsort()\n    indices = indices[imsz - numpx::]\n\n    atmsum = np.zeros([1, 3])\n    for ind in range(1, numpx):\n        atmsum = atmsum + imvec[indices[ind]]\n\n    A = atmsum / numpx\n    return A\n\ndef TransmissionEstimate(im, A, sz):\n    omega = 0.95\n    im3 = np.empty(im.shape, im.dtype)\n\n    for ind in range(0, 3):\n        im3[:, :, ind] = im[:, :, ind] / A[0, ind]\n\n    transmission = 1 - omega * DarkChannel(im3, sz)\n    return transmission\n\ndef Guidedfilter(im, p, r, eps):\n    mean_I = cv2.boxFilter(im, cv2.CV_64F, (r, r))\n    mean_p = cv2.boxFilter(p, cv2.CV_64F, (r, r))\n    mean_Ip = cv2.boxFilter(im * p, cv2.CV_64F, (r, r))\n    cov_Ip = mean_Ip - mean_I * mean_p\n\n    mean_II = cv2.boxFilter(im * im, cv2.CV_64F, (r, r))\n    var_I = mean_II - mean_I * mean_I\n\n    a = cov_Ip / (var_I + eps)\n    b = mean_p - a * mean_I\n\n    mean_a = cv2.boxFilter(a, cv2.CV_64F, (r, r))\n    mean_b = cv2.boxFilter(b, cv2.CV_64F, (r, r))\n\n    q = mean_a * im + mean_b\n    return q\n\ndef TransmissionRefine(im, et):\n    gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)\n    gray = np.float64(gray) / 255\n    r = 60\n    eps = 0.0001\n    t = Guidedfilter(gray, et, r, eps)\n\n    return t\n\ndef Recover(im, t, A, tx=0.1):\n    res = np.empty(im.shape, im.dtype)\n    t = cv2.max(t, tx)\n\n    for ind in range(0, 3):\n        res[:, :, ind] = (im[:, :, ind] - A[0, ind]) / t + A[0, ind]\n\n    return res\n\nif __name__ == '__main':\n    input_filename = '../input/own-dark/input.png'\n\n    src = cv2.imread(input_filename)\n\n    I = src.astype('float64') / 255\n\n    dark = DarkChannel(I, 15)\n    A = AtmLight(I, dark)\n    te = TransmissionEstimate(I, A, 15)\n    t = TransmissionRefine(src, te)\n    J = Recover(I, t, A, 0.1)\n\n    plt.imshow(cv2.cvtColor(dark, cv2.COLOR_BGR2RGB))\n    plt.title(\"Dark Channel\")\n    plt.show()\n\n    plt.imshow(t, cmap='gray')\n    plt.title(\"Transmission\")\n    plt.show()\n\n    plt.imshow(cv2.cvtColor(src, cv2.COLOR_BGR2RGB))\n    plt.title(\"Original Image\")\n    plt.show()\n\n    plt.imshow(cv2.cvtColor((J * 255).astype('uint8'), cv2.COLOR_BGR2RGB))\n    plt.title(\"Enhanced Image\")\n    plt.show()\n\n    cv2.imwrite(\"output.png\", J * 255)\n","metadata":{"execution":{"iopub.status.busy":"2023-11-07T15:04:34.354222Z","iopub.execute_input":"2023-11-07T15:04:34.354945Z","iopub.status.idle":"2023-11-07T15:04:34.377240Z","shell.execute_reply.started":"2023-11-07T15:04:34.354891Z","shell.execute_reply":"2023-11-07T15:04:34.375872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}