{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['d:\\\\Users\\\\user\\\\Downloads\\\\Research\\\\Video3D', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP\\\\python311.zip', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP\\\\DLLs', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP\\\\Lib', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP', '', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP\\\\Lib\\\\site-packages', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP\\\\Lib\\\\site-packages\\\\win32', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP\\\\Lib\\\\site-packages\\\\win32\\\\lib', 'c:\\\\Users\\\\user\\\\anaconda3\\\\envs\\\\pyRARP\\\\Lib\\\\site-packages\\\\Pythonwin', 'd:\\\\Users\\\\user\\\\Documents\\\\postata\\\\RARP\\\\Clasification', 'D:\\\\Users\\\\user\\\\Downloads\\\\Research']\n",
      "LR= 0.0001, L1= None\n",
      "LR= 0.0001, L1= None\n"
     ]
    }
   ],
   "source": [
    "import decord\n",
    "from pathlib import Path\n",
    "import torch\n",
    "import cv2\n",
    "import numpy as np\n",
    "from inflateDEMO import I3DResNet50\n",
    "import torchvision.transforms as T\n",
    "import sys\n",
    "from tqdm.notebook import tqdm\n",
    "\n",
    "try:\n",
    "    print (sys.path.index(\"D:\\\\Users\\\\user\\\\Downloads\\\\Research\"))\n",
    "except:\n",
    "    sys.path.append(\"D:\\\\Users\\\\user\\\\Downloads\\\\Research\")\n",
    "    \n",
    "print(sys.path)\n",
    "from Models import RARP_NVB_ResNet50\n",
    "\n",
    "\n",
    "def _removeBlackBorder(image):\n",
    "    image = np.array(image)\n",
    "    \n",
    "    copyImg = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2HSV)\n",
    "    h = copyImg[:,:,0]\n",
    "    mask = np.ones(h.shape, dtype=np.uint8) * 255\n",
    "    th = (25, 175)\n",
    "    mask[(h > th[0]) & (h < th[1])] = 0\n",
    "    copyImg = cv2.cvtColor(copyImg, cv2.COLOR_HSV2BGR)\n",
    "    resROI = cv2.bitwise_and(copyImg, copyImg, mask=mask)\n",
    "        \n",
    "    image_gray = cv2.cvtColor(resROI, cv2.COLOR_BGR2GRAY)\n",
    "    _, thresh = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY)\n",
    "    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))\n",
    "    morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)\n",
    "    contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "    contours = contours[0] if len(contours) == 2 else contours[1]\n",
    "    bigCont = max(contours, key=cv2.contourArea)\n",
    "    x, y, w, h = cv2.boundingRect(bigCont)\n",
    "    crop = image[y : y + h, x : x + w]\n",
    "    return crop\n",
    "\n",
    "def VideoPrePros_BackBars(VideoIN_Path:str, VideoOUT_Path:str, demoVideo:int = None):\n",
    "    size = (1269, 1007)\n",
    "    fourcc = cv2.VideoWriter_fourcc(*'mp4v')\n",
    "    video = cv2.VideoWriter(VideoOUT_Path, fourcc, 30, size)\n",
    "    \n",
    "    if demoVideo is not None:\n",
    "        demoVideoOut = cv2.VideoWriter(\"demo.mp4\", fourcc, demoVideo, size)\n",
    "\n",
    "    cap = cv2.VideoCapture(VideoIN_Path)\n",
    "    while (True):\n",
    "        ret, frame = cap.read()\n",
    "        if not ret:\n",
    "            break\n",
    "        \n",
    "        img = _removeBlackBorder(frame)\n",
    "        img = cv2.resize(img, size, interpolation=cv2.INTER_CUBIC)\n",
    "        video.write(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n",
    "        #video.write(img)\n",
    "        if demoVideo is not None:\n",
    "            demoVideoOut.write(img)\n",
    "        \n",
    "    video.release()\n",
    "    if demoVideo is not None:\n",
    "        demoVideoOut.release()\n",
    "    cap.release()\n",
    "    \n",
    "RN50Model = RARP_NVB_ResNet50.load_from_checkpoint(\"../log_ResNet50_X10/lightning_logs/version_8/checkpoints/RARP-epoch=5.ckpt\")\n",
    "RN50ModelToEval = RARP_NVB_ResNet50.load_from_checkpoint(\"../log_ResNet50_X10/lightning_logs/version_8/checkpoints/RARP-epoch=5.ckpt\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "torch.save(RN50Model.model.state_dict(), \"Pre-trainRN50.pth\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ffmpeg\n",
    "\n",
    "def extract_frames_ffmpeg(video_path, start_frame, end_frame, width=None, height=None, fps=30):\n",
    "    # Construir el comando ffmpeg\n",
    "    stream = (\n",
    "        ffmpeg\n",
    "        .input(video_path, ss=start_frame / fps, t=end_frame / fps, hwaccel='cuda')  # Suponiendo 30 fps, ajusta según el FPS del video\n",
    "        .output('pipe:', format='rawvideo', pix_fmt='rgb24')\n",
    "        .run(capture_stdout=True)\n",
    "    )\n",
    "    \n",
    "    # Convertir el stream en un array de NumPy\n",
    "    video = np.frombuffer(stream[0], np.uint8)\n",
    "    # Asumiendo que conocemos el ancho y el alto del video\n",
    "    if width and height:\n",
    "        video = video.reshape((-1, height, width, 3))  # Num_frames, altura, anchura, canales\n",
    "    return video"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "videoPathLong = Path(\"./dataset/NVB/350Full.mp4\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "decord.bridge.set_bridge('native')\n",
    "vr = decord.VideoReader(str(videoPathLong.absolute()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from nested_lookup import nested_lookup\n",
    "\n",
    "viodeoInfo = ffmpeg.probe(str(videoPathLong.absolute()))\n",
    "fps =  eval (nested_lookup(\"avg_frame_rate\", viodeoInfo)[0])\n",
    "w = int(nested_lookup(\"width\", viodeoInfo)[0])\n",
    "h = int(nested_lookup(\"height\", viodeoInfo)[0])\n",
    "total_frames = int(nested_lookup(\"nb_frames\", viodeoInfo)[0])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "total_frames"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "def show_picture(im):\n",
    "    plt.imshow(im)\n",
    "    plt.xticks([])\n",
    "    plt.yticks([])\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fps = vr.get_avg_fps()\n",
    "print (f\"FPS:{vr.get_avg_fps()}\")\n",
    "segs = len(vr)/fps\n",
    "print (f\"Video Length: {segs} seg.\")\n",
    "print (f\"Video Length: {round(segs*fps)} frames.\")\n",
    "print (f\"Chuks of 15 seg: {segs//15} chunks\")\n",
    "print (f\"Chuks of 30 seg: {segs//30} chunks\")\n",
    "print (f\"Chuks of 35 seg: {segs//35} chunks\")\n",
    "print (f\"Chuks of 40 seg: {segs//40} chunks\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "start_frame = 0  # Fotograma de inicio\n",
    "num_frames = 450  # Número de fotogramas que quieres extraer\n",
    "  # Ancho y alto del video (ajusta según el video)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "frames_batch = extract_frames_ffmpeg(str(videoPathLong.absolute()), start_frame, num_frames, width=w, height=h, fps=fps)\n",
    "\n",
    "print(f'Frames extraídos: {frames_batch.shape}')\n",
    "\n",
    "bgrFramesBatch = frames_batch[..., ::-1].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "chunk_frames = vr.get_batch(range(start_frame, num_frames)).asnumpy()\n",
    "        \n",
    "chunk_frames_bgr = chunk_frames[..., ::-1].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "show_picture(chunk_frames_bgr[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "mean, std = ([30.38144216, 42.03988769, 97.8896116], [40.63141752, 44.26910074, 50.29294373])\n",
    "transforms = T.Compose([\n",
    "    T.Resize((256,256), antialias=True, interpolation=T.InterpolationMode.BICUBIC),\n",
    "    T.CenterCrop(224),\n",
    "    T.Normalize(mean, std)\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "frameToFind = cv2.imread(str(Path(\"../DataSet_Ando_All/NVB/350.tiff\")), cv2.IMREAD_COLOR)\n",
    "#frameToFind = _removeBlackBorder(frameToFind)\n",
    "frameToFind = torch.Tensor(frameToFind)\n",
    "frameToFind = frameToFind.permute(2, 0, 1).float()\n",
    "\n",
    "frameToFind = transforms(frameToFind)\n",
    "\n",
    "frameToFind = frameToFind.repeat(1, 1, 1, 1)\n",
    "\n",
    "torch.set_float32_matmul_precision('medium')\n",
    "torch.backends.cudnn.deterministic = True\n",
    "\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "\n",
    "InfalteModel = I3DResNet50(RN50Model.model).to(device)\n",
    "InfalteModel.fc = torch.nn.Identity()\n",
    "InfalteModel.eval()\n",
    "\n",
    "RN50ModelToEval.model.fc = torch.nn.Identity()\n",
    "RN50ModelToEval.to(device)\n",
    "RN50ModelToEval.eval()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "framesChunk = np.array([15, 30, 35, 40]) * round(fps)\n",
    "\n",
    "chunk_size = framesChunk[0]\n",
    "total_frames = len(vr)\n",
    "\n",
    "with torch.no_grad():\n",
    "    frameToFind = frameToFind.to(device)\n",
    "    \n",
    "    Doutput = RN50ModelToEval(frameToFind)\n",
    "    Doutput = Doutput.squeeze()\n",
    "    \n",
    "    maxSim = 0\n",
    "    \n",
    "    ListSim = []\n",
    "    \n",
    "    initFrame = None\n",
    "    \n",
    "    for start_idx in tqdm(range(0, total_frames, chunk_size)):\n",
    "        end_idx = min(start_idx + chunk_size, total_frames)\n",
    "        chunk_frames = vr.get_batch(range(start_idx, end_idx)).asnumpy()\n",
    "        \n",
    "        chunk_frames_bgr = chunk_frames[..., ::-1].copy()\n",
    "        \n",
    "        frames = torch.from_numpy(chunk_frames_bgr).to(device)\n",
    "        frames = frames.permute(0, 3, 1, 2)\n",
    "        frames = frames.float()\n",
    "\n",
    "        frames = transforms(frames)\n",
    "\n",
    "        frames = frames.repeat(1, 1, 1, 1, 1)\n",
    "        frames = frames.permute(0, 2, 1, 3, 4)\n",
    "        \n",
    "        outPut = InfalteModel(frames)\n",
    "        outPut = outPut.squeeze()\n",
    "        \n",
    "        #print(outPut.shape, Doutput.shape)\n",
    "           \n",
    "        cos_sim = torch.nn.functional.cosine_similarity(outPut, Doutput, dim=0)\n",
    "        \n",
    "        #maxSim = cos_sim if cos_sim > maxSim else maxSim\n",
    "        if cos_sim > maxSim:\n",
    "            print(cos_sim)\n",
    "            maxSim = cos_sim\n",
    "            initFrame = (start_idx, end_idx)\n",
    "            \n",
    "\n",
    "        ListSim.append(cos_sim)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def seconds_to_hms(seconds):\n",
    "    hours = seconds // 3600\n",
    "    minutes = (seconds % 3600) // 60\n",
    "    secs = seconds % 60\n",
    "    return f'{int(hours)}:{int(minutes):02}:{int(secs):02}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(seconds_to_hms(initFrame[0]/fps), seconds_to_hms(initFrame[1]/fps))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ffmpeg\n",
    "from pathlib import Path\n",
    "\n",
    "videoPathLong = Path(\"./dataset/NVB/350Full.mp4\")\n",
    "fileVideo = ffmpeg.input(str(videoPathLong.absolute()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "outPutVideo = ffmpeg.output(fileVideo.trim(start_frame=initFrame[0], end_frame=initFrame[1]), \"350_1.mp4\", vcodec='h264_nvenc')\n",
    "ffmpeg.run(outPutVideo)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from scipy.signal import savgol_filter\n",
    "\n",
    "Name = \"NVB/350.mp4\"\n",
    "chunks = range(0, total_frames, chunk_size)\n",
    "sim = torch.tensor(ListSim)\n",
    "\n",
    "smoothed_accuracy = savgol_filter(sim, window_length=5, polyorder=2)\n",
    "\n",
    "maxSim = sim.max()\n",
    "indexmax = sim.argmax()\n",
    "bestSim = chunks[indexmax]\n",
    "\n",
    "plt.figure(figsize=(15, 6))\n",
    "plt.plot(chunks, sim, marker='o', linestyle='-', color='b', label='Cosine similarity')\n",
    "plt.plot(chunks, smoothed_accuracy, color='g', linestyle='--', label='Smoothed Data')\n",
    "plt.title(f\"frames vs. Sim. [{Name}]\")\n",
    "plt.xlabel('frames')\n",
    "plt.ylabel('Cos Sim.')\n",
    "plt.grid(True)\n",
    "\n",
    "plt.scatter(bestSim, maxSim, zorder=5, marker=\"x\", color='r', label=f'Higth Sim: {maxSim:.4f} at {bestSim} start frame')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from scipy.signal import savgol_filter\n",
    "\n",
    "# Data from the table\n",
    "Name = \"NVB/349.mp4\"\n",
    "frames = [19,24,31,47,52,58,59,66,72,73,76,77,93,116,154,231,461]\n",
    "accuracy = [0.7166,0.7372,0.7518,0.7503,0.6988,0.713,0.7233,0.6932,0.6776,0.6842,0.6858,0.689,0.6887,0.6643,0.6811,0.6605,0.6827]\n",
    "\n",
    "smoothed_accuracy = savgol_filter(accuracy, window_length=5, polyorder=2)\n",
    "\n",
    "\n",
    "# Finding the best accuracy and corresponding number of frames\n",
    "max_acc = max(accuracy)\n",
    "max_acc_index = accuracy.index(max_acc)\n",
    "best_frames = frames[max_acc_index]\n",
    "\n",
    "# Plotting the data\n",
    "plt.figure(figsize=(8, 6))\n",
    "plt.plot(frames, accuracy, marker='o', linestyle='-', color='b', label='Original Data')\n",
    "plt.plot(frames, smoothed_accuracy, color='g', linestyle='--', label='Smoothed Data')\n",
    "plt.title(f\"No. Frames vs. Prob. NVB [{Name}]\")\n",
    "plt.xlabel('No. Frames')\n",
    "plt.ylabel('Prob. NVB')\n",
    "plt.grid(True)\n",
    "\n",
    "# Highlight the best accuracy point\n",
    "plt.scatter(best_frames, max_acc, zorder=5, marker=\"x\", color='r', label=f'Best Acc: {max_acc} at {best_frames} Frames')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from scipy.signal import savgol_filter\n",
    "\n",
    "# Data from the table\n",
    "Name = \"NOT_NVB/201.mp4\"\n",
    "frames = [18,23,30,45,50,57,59,65,72,73,75,76,90,113,150,224,450]\n",
    "accuracy = [0.4945,0.5124,0.5194,0.5173,0.501,0.5206,0.5222,0.5322,0.496,0.5042,0.5007,0.4977,0.5042,0.5139,0.51,0.5116,0.5123]\n",
    "\n",
    "smoothed_accuracy = savgol_filter(accuracy, window_length=5, polyorder=2)\n",
    "\n",
    "\n",
    "# Finding the best accuracy and corresponding number of frames\n",
    "max_acc = min(accuracy)\n",
    "max_acc_index = accuracy.index(max_acc)\n",
    "best_frames = frames[max_acc_index]\n",
    "\n",
    "# Plotting the data\n",
    "plt.figure(figsize=(8, 6))\n",
    "plt.plot(frames, accuracy, marker='o', linestyle='-', color='r', label='Original Data')\n",
    "plt.plot(frames, smoothed_accuracy, color='g', linestyle='--', label='Smoothed Data')\n",
    "plt.title(f\"No. Frames vs. Prob. NVB [{Name}]\")\n",
    "plt.xlabel('No. Frames')\n",
    "plt.ylabel('Prob. NVB')\n",
    "plt.grid(True)\n",
    "\n",
    "# Highlight the best accuracy point\n",
    "plt.scatter(best_frames, max_acc, zorder=5, marker=\"x\", color='b', label=f'Best Acc: {max_acc} at {best_frames} Frames')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LR= 0.0001, L1= None\n",
      "================ Diagnostic Run torch.onnx.export version 2.0.1 ================\n",
      "verbose: False, log level: Level.ERROR\n",
      "======================= 0 NONE 0 NOTE 0 WARNING 0 ERROR ========================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "from inflateDEMO import I3DResNet50\n",
    "from pathlib import Path\n",
    "import sys\n",
    "from tqdm import tqdm\n",
    "\n",
    "try:\n",
    "    print (sys.path.index(\"D:\\\\Users\\\\user\\\\Downloads\\\\Research\"))\n",
    "except:\n",
    "    sys.path.append(\"D:\\\\Users\\\\user\\\\Downloads\\\\Research\")\n",
    "    \n",
    "from Models import RARP_NVB_ResNet50\n",
    "\n",
    "RN50Model = RARP_NVB_ResNet50.load_from_checkpoint(Path(\"../log_ResNet50_X10/lightning_logs/version_8/checkpoints/RARP-epoch=5.ckpt\"))\n",
    "#RN50ModelToEval = RARP_NVB_ResNet50.load_from_checkpoint(Path(\"../log_ResNet50_X10/lightning_logs/version_8/checkpoints/RARP-epoch=5.ckpt\"))\n",
    "\n",
    "input_sample = torch.randn((1, 3, 224, 224))\n",
    "RN50Model.model.fc = torch.nn.Identity()\n",
    "RN50Model.to_onnx(\"RN50Model.onnx\", input_sample, export_params=True, opset_version=12, do_constant_folding=True, input_names=[\"image\"], output_names=[\"output\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "LR= 0.0001, L1= None\n",
      "cpu cpu\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "from inflateDEMO import I3DResNet50\n",
    "from pathlib import Path\n",
    "import sys\n",
    "\n",
    "try:\n",
    "    print (sys.path.index(\"D:\\\\Users\\\\user\\\\Downloads\\\\Research\"))\n",
    "except:\n",
    "    sys.path.append(\"D:\\\\Users\\\\user\\\\Downloads\\\\Research\")\n",
    "    \n",
    "from Models import RARP_NVB_ResNet50\n",
    "\n",
    "RN50Model = RARP_NVB_ResNet50.load_from_checkpoint(Path(\"../log_ResNet50_X10/lightning_logs/version_8/checkpoints/RARP-epoch=5.ckpt\")).cpu()\n",
    "\n",
    "dummy_frames = 15\n",
    "input_sample = torch.randn((1, 3, dummy_frames, 224, 224))\n",
    "InfalteModel = I3DResNet50(RN50Model.model)\n",
    "InfalteModel.fc = torch.nn.Identity()\n",
    "print(InfalteModel.device, input_sample.device)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "torch.save(RN50Model.model.state_dict(), \"Pre-trainRN50.pth\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================ Diagnostic Run torch.onnx.export version 2.0.1 ================\n",
      "verbose: False, log level: Level.ERROR\n",
      "======================= 0 NONE 0 NOTE 0 WARNING 0 ERROR ========================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "\n",
    "InfalteModel.to_onnx(\n",
    "    \"RN50_3D_Model.onnx\", \n",
    "    input_sample, \n",
    "    export_params=True, \n",
    "    opset_version=12, \n",
    "    do_constant_folding=True,\n",
    "    input_names=[\"image\"], \n",
    "    output_names=[\"output\"],\n",
    "    dynamic_axes={\"image\": {0: \"batch_size\", 2: \"num_frames\"}, \"output\": {0: \"batch_size\"}}\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 87488 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 1. Load and preprocess\n",
    "img = cv2.imread('download.png')\n",
    "# Optional: resize for faster processing\n",
    "\n",
    "gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
    "blur = cv2.GaussianBlur(gray, (5, 5), 0)\n",
    "\n",
    "# 2. Edge detection (Canny) or thresholding\n",
    "edges = cv2.Canny(blur, 200, 200)\n",
    "\n",
    "plt.imshow(edges, cmap=\"gray\")\n",
    "plt.axis('off')\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 418532 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# Alternative: simple threshold\n",
    "# _, edges = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)\n",
    "\n",
    "# 3. Morphological closing to fill gaps\n",
    "kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))\n",
    "closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)\n",
    "\n",
    "# 4. Find contours\n",
    "contours, hierarchy = cv2.findContours(\n",
    "    closed, \n",
    "    cv2.RETR_EXTERNAL, \n",
    "    cv2.CHAIN_APPROX_SIMPLE\n",
    ")\n",
    "\n",
    "\n",
    "min_area = 1000\n",
    "#large_contours = [c for c in contours if cv2.contourArea(c) > min_area]\n",
    "\n",
    "large_contours = max(contours, key=cv2.contourArea)\n",
    "# 5. Draw contours and approximate polygon\n",
    "output = img.copy()\n",
    "for cnt in large_contours:\n",
    "    # Approximate to reduce number of points (optional)\n",
    "    epsilon = 0.01 * cv2.arcLength(cnt, True)\n",
    "    approx = cv2.approxPolyDP(cnt, epsilon, True)\n",
    "    # Draw in green, thickness=2\n",
    "    cv2.drawContours(output, [approx], -1, (0, 255, 0), 2)\n",
    "\n",
    "# Show result\n",
    "plt.imshow(output)\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [],
   "source": [
    "algo = [\n",
    "    (\"SLIC\", cv2.ximgproc.SLIC),\n",
    "    (\"SLICO\", cv2.ximgproc.SLICO),\n",
    "    (\"MSLIC\", cv2.ximgproc.MSLIC),\n",
    "    (\"LSC\", None),\n",
    "    (\"SEED\", None)\n",
    "]\n",
    "def SuperPX_SLIC(img, label=\"\", ColorSpace=cv2.COLOR_HSV2RGB):\n",
    "    _, ax = plt.subplots(5, 3, figsize=(15, 20))\n",
    "    region_size = 20\n",
    "    ruler = 30.0\n",
    "    min_ele_size = 10\n",
    "    mum_iterarions = 4\n",
    "    res = []\n",
    "    for i, a in enumerate(algo):\n",
    "        match a[0]:\n",
    "            case \"LSC\":\n",
    "                slic = cv2.ximgproc.createSuperpixelLSC(img, region_size, 0.1)\n",
    "            case \"SEED\":\n",
    "                h, w, c = img.shape\n",
    "                mum_iterarions = 10\n",
    "                slic = cv2.ximgproc.createSuperpixelSEEDS(w, h, c, num_superpixels=250, num_levels=5, prior=2, double_step=True, histogram_bins=6)\n",
    "            case _:\n",
    "                slic = cv2.ximgproc.createSuperpixelSLIC(img, a[1], region_size, ruler)\n",
    "                \n",
    "        if isinstance(slic, cv2.ximgproc.SuperpixelSEEDS):\n",
    "            slic.iterate(img, mum_iterarions)\n",
    "        else:\n",
    "            slic.iterate(mum_iterarions)\n",
    "            slic.enforceLabelConnectivity(min_ele_size)\n",
    "        rgbImg = cv2.cvtColor(img.copy(), ColorSpace)\n",
    "        \n",
    "        contour_mask = slic.getLabelContourMask(thick_line=False)\n",
    "        Lables = slic.getLabels()\n",
    "        \n",
    "        rgbImg[0 < contour_mask] = (0, 255, 255)\n",
    "        ax[i][0].imshow(rgbImg)\n",
    "        ax[i][0].set_title(a[0])\n",
    "        ax[i][1].imshow(cv2.cvtColor(img, ColorSpace))\n",
    "        #ax[i][2].imshow(contour_mask, cmap = \"gray\")\n",
    "        w, h, c = img.shape\n",
    "        img_1D = img.reshape((w * h, c))\n",
    "        label_1D = np.reshape(Lables, -1)\n",
    "        mask1D = np.zeros(img_1D.shape, dtype=\"uint8\")\n",
    "        for segVal in np.unique(Lables):\n",
    "            Sp_1D = np.where(label_1D == segVal)[0] # conver as list\n",
    "            mask1D[Sp_1D, :] = np.mean(img_1D[Sp_1D, :], axis=0).astype('uint8')\n",
    "        mask2D = np.reshape(mask1D, [w, h, c])\n",
    "        mask2D = cv2.cvtColor(mask2D, ColorSpace)\n",
    "        ax[i][2].imshow(mask2D)\n",
    "        res += [[a[0], Lables, contour_mask, mask2D]]\n",
    "        ax[i][0].axis('off')\n",
    "        ax[i][1].axis('off')\n",
    "        ax[i][2].axis('off')\n",
    "        #ax[i][3].imshow(slic.getLabels())\n",
    "        #cv2.imwrite(f\"OutPut/SP_{a[0]}{label}.png\", cv2.cvtColor(rgbImg, cv2.COLOR_RGB2BGR))\n",
    "        \n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[203, 219, 225],\n",
       "        [203, 219, 225],\n",
       "        [203, 219, 225],\n",
       "        ...,\n",
       "        [ 75,  71,  74],\n",
       "        [ 75,  71,  74],\n",
       "        [ 75,  71,  74]],\n",
       "\n",
       "       [[203, 219, 225],\n",
       "        [203, 219, 225],\n",
       "        [203, 219, 225],\n",
       "        ...,\n",
       "        [ 75,  71,  74],\n",
       "        [ 75,  71,  74],\n",
       "        [ 75,  71,  74]],\n",
       "\n",
       "       [[203, 219, 225],\n",
       "        [203, 219, 225],\n",
       "        [203, 219, 225],\n",
       "        ...,\n",
       "        [ 75,  71,  74],\n",
       "        [ 75,  71,  74],\n",
       "        [ 75,  71,  74]],\n",
       "\n",
       "       ...,\n",
       "\n",
       "       [[ 90,  89,  88],\n",
       "        [ 90,  89,  88],\n",
       "        [ 90,  89,  88],\n",
       "        ...,\n",
       "        [118, 111, 102],\n",
       "        [118, 111, 102],\n",
       "        [118, 111, 102]],\n",
       "\n",
       "       [[ 90,  89,  88],\n",
       "        [ 90,  89,  88],\n",
       "        [ 90,  89,  88],\n",
       "        ...,\n",
       "        [118, 111, 102],\n",
       "        [118, 111, 102],\n",
       "        [118, 111, 102]],\n",
       "\n",
       "       [[ 90,  89,  88],\n",
       "        [ 90,  89,  88],\n",
       "        [ 90,  89,  88],\n",
       "        ...,\n",
       "        [118, 111, 102],\n",
       "        [118, 111, 102],\n",
       "        [118, 111, 102]]], dtype=uint8)"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 2320160 characters]",
      "text/plain": [
       "<Figure size 1500x2000 with 15 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "imgLAB = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) \n",
    "twmp = SuperPX_SLIC(imgLAB, \"_YoloROI\", cv2.COLOR_LAB2RGB)\n",
    "twmp[4][3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "def MaskedImge (input_img, K = 4, gray_thresh:float = None):\n",
    "    if isinstance(input_img, str):\n",
    "        img = cv2.imread('download.png')\n",
    "        img = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)\n",
    "    else:\n",
    "        img = input_img.copy()\n",
    "        \n",
    "    h, w, c = img.shape\n",
    "\n",
    "    seeds = cv2.ximgproc.createSuperpixelSEEDS(\n",
    "        image_width=w,\n",
    "        image_height=h,\n",
    "        image_channels=c,\n",
    "        num_superpixels=250, num_levels=5,\n",
    "        prior=3,\n",
    "        histogram_bins=6\n",
    "    )\n",
    "    seeds.iterate(img, 10)\n",
    "    labels = seeds.getLabels()            # shape = (h, w)\n",
    "    n_labels = seeds.getNumberOfSuperpixels()\n",
    "\n",
    "    # --- 2. & 3. Compute avg color & cluster with K-means into 2 groups ---\n",
    "    # 2. average color per label\n",
    "    sum_color = np.zeros((n_labels, 3), dtype=np.float32)\n",
    "    counts    = np.zeros(n_labels,       dtype=np.int32)\n",
    "\n",
    "    for y in range(h):\n",
    "        for x in range(w):\n",
    "            l = labels[y, x]\n",
    "            sum_color[l] += img[y, x]\n",
    "            counts[l]  += 1\n",
    "    avg_color = sum_color / counts[:, None]  # shape = (n_labels, 3)\n",
    "    \n",
    "    \n",
    "    criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)\n",
    "    _, lm, centers = cv2.kmeans(\n",
    "        avg_color.astype(np.float32),\n",
    "        K,\n",
    "        None,\n",
    "        criteria,\n",
    "        10,\n",
    "        cv2.KMEANS_PP_CENTERS\n",
    "    )\n",
    "    \n",
    "    mask = np.zeros((h, w), np.uint8)\n",
    "    \n",
    "    if gray_thresh is not None:\n",
    "        chroma = np.linalg.norm(centers[:,1:3], axis=1)  # sqrt(a² + b²)\n",
    "        gray_clusters = np.where(chroma < gray_thresh)[0]\n",
    "        \n",
    "        for spix in gray_clusters:\n",
    "            mask[labels == spix] = 255\n",
    "    else:\n",
    "        # pick the cluster whose center is “darker” (sum of BGR smallest)\n",
    "        fg_cluster = int(np.argmin(centers.sum(axis=1)))\n",
    "        for lbl in range(n_labels):\n",
    "            if lm[lbl] == fg_cluster:\n",
    "                mask[labels == lbl] = 255\n",
    "            \n",
    "    kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15,15))\n",
    "    kernel_open  = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))\n",
    "    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel_close)\n",
    "    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN,  kernel_open)\n",
    "\n",
    "    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "    if contours:\n",
    "        cnt = max(contours, key=cv2.contourArea)\n",
    "        output_mask = np.zeros((h, w), np.uint8)\n",
    "        output_mask = cv2.fillPoly(output_mask, [cnt], 255)\n",
    "        \n",
    "        out = cv2.cvtColor(img.copy(), cv2.COLOR_Lab2RGB)\n",
    "        #cv2.drawContours(out, [cnt], -1, (0,255,0), 3)\n",
    "        outimg = cv2.bitwise_and(out, out, mask=output_mask)\n",
    "        return output_mask, outimg\n",
    "    else:\n",
    "        print(\"No contours found!\")\n",
    "        return np.zeros((h, w), np.uint8), cv2.cvtColor(img, cv2.COLOR_Lab2RGB)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x2412bfda390>"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 75620 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(twmp[4][3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27420 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gray = cv2.cvtColor(twmp[4][3], cv2.COLOR_RGB2GRAY)\n",
    "blur = cv2.GaussianBlur(gray, (5, 5), 0)\n",
    "\n",
    "# 2. Edge detection (Canny) or thresholding\n",
    "edges = cv2.Canny(blur, 200, 200)\n",
    "\n",
    "plt.imshow(edges, cmap=\"gray\")\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 76960 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))\n",
    "closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)\n",
    "\n",
    "# 4. Find contours\n",
    "contours, hierarchy = cv2.findContours(\n",
    "    closed, \n",
    "    cv2.RETR_EXTERNAL, \n",
    "    cv2.CHAIN_APPROX_SIMPLE\n",
    ")\n",
    "\n",
    "\n",
    "min_area = 10\n",
    "large_contours = [c for c in contours if cv2.contourArea(c) > min_area]\n",
    "\n",
    "#large_contours = max(contours, key=cv2.contourArea)\n",
    "# 5. Draw contours and approximate polygon\n",
    "output = twmp[4][3].copy()\n",
    "for cnt in large_contours:\n",
    "    # Approximate to reduce number of points (optional)\n",
    "    epsilon = 0.01 * cv2.arcLength(cnt, True)\n",
    "    approx = cv2.approxPolyDP(cnt, epsilon, True)\n",
    "    # Draw in green, thickness=2\n",
    "    cv2.drawContours(output, [approx], -1, (0, 255, 0), 2)\n",
    "\n",
    "# Show result\n",
    "plt.imshow(output)\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 28156 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "_, img = MaskedImge(cv2.cvtColor(twmp[4][3], cv2.COLOR_RGB2Lab), K=5)\n",
    "\n",
    "plt.imshow(img)\n",
    "plt.axis('off')\n",
    "plt.show()\n",
    "\n",
    "#MaskedImge(cv2.cvtColor(img, cv2.COLOR_RGB2BGR))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 5892 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "_, img = MaskedImge(cv2.cvtColor(img, cv2.COLOR_RGB2Lab), K=3)\n",
    "\n",
    "plt.imshow(img)\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# --- 1. Load & super-pixel (SEEDS in this example) ---\n",
    "img = cv2.imread('download.png')\n",
    "img = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)\n",
    "h, w, c = img.shape\n",
    "\n",
    "seeds = cv2.ximgproc.createSuperpixelSEEDS(\n",
    "    image_width=w,\n",
    "    image_height=h,\n",
    "    image_channels=c,\n",
    "    num_superpixels=250, num_levels=5,\n",
    "    prior=3,\n",
    "    histogram_bins=6\n",
    ")\n",
    "seeds.iterate(img, 10)\n",
    "labels = seeds.getLabels()            # shape = (h, w)\n",
    "n_labels = seeds.getNumberOfSuperpixels()\n",
    "\n",
    "# --- 2. & 3. Compute avg color & cluster with K-means into 2 groups ---\n",
    "# 2. average color per label\n",
    "sum_color = np.zeros((n_labels, 3), dtype=np.float32)\n",
    "counts    = np.zeros(n_labels,       dtype=np.int32)\n",
    "\n",
    "for y in range(h):\n",
    "    for x in range(w):\n",
    "        l = labels[y, x]\n",
    "        sum_color[l] += img[y, x]\n",
    "        counts[l]  += 1\n",
    "avg_color = sum_color / counts[:, None]  # shape = (n_labels, 3)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 61800 characters]",
      "text/plain": [
       "<Figure size 600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# 3. K-means on those 3-dim colors\n",
    "criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)\n",
    "K = 2\n",
    "_, lm, centers = cv2.kmeans(\n",
    "    avg_color.astype(np.float32),\n",
    "    K,\n",
    "    None,\n",
    "    criteria,\n",
    "    10,\n",
    "    cv2.KMEANS_PP_CENTERS\n",
    ")\n",
    "# pick the cluster whose center is “darker” (sum of BGR smallest)\n",
    "fg_cluster = int(np.argmin(centers.sum(axis=1)))\n",
    "\n",
    "a_vals = avg_color[:, 1]\n",
    "b_vals = avg_color[:, 2]\n",
    "\n",
    "plt.figure(figsize=(6,6))\n",
    "for cluster_id in np.unique(lm):\n",
    "    idx = np.where(lm.ravel() == cluster_id)\n",
    "    plt.scatter(a_vals[idx], b_vals[idx], label=f\"cluster {cluster_id}\", alpha=0.6, s=50)\n",
    "    \n",
    "plt.scatter(centers[:, 1], centers[:, 2], c=\"k\", marker=\"X\", s=200, label=\"Centers\")\n",
    "plt.xlabel('a channel')\n",
    "plt.ylabel('b channel')\n",
    "plt.title('Super-pixel colors clustered by K-means')\n",
    "plt.legend()\n",
    "plt.grid(True)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20428 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "\n",
    "# --- 4. Build binary mask of foreground super-pixels ---\n",
    "mask = np.zeros((h, w), np.uint8)\n",
    "for lbl in range(n_labels):\n",
    "    if lm[lbl] == fg_cluster:\n",
    "        mask[labels == lbl] = 255\n",
    "        \n",
    "        \n",
    "plt.imshow(mask)\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 16936 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# --- 5. Morphological clean-up ---\n",
    "kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15,15))\n",
    "kernel_open  = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))\n",
    "mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel_close)\n",
    "mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN,  kernel_open)\n",
    "\n",
    "plt.imshow(mask)\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 393444 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# --- 6. findContours & draw the largest one ---\n",
    "contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "if contours:\n",
    "    cnt = max(contours, key=cv2.contourArea)\n",
    "    out = img.copy()\n",
    "    cv2.drawContours(out, [cnt], -1, (0,255,0), 3)\n",
    "    plt.imshow(cv2.cvtColor(out, cv2.COLOR_Lab2RGB))\n",
    "    plt.axis('off')\n",
    "    plt.show()\n",
    "else:\n",
    "    print(\"No contours found!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 356876 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "maked = cv2.bitwise_and(img, img, mask=mask)\n",
    "plt.imshow(cv2.cvtColor(maked, cv2.COLOR_Lab2RGB))\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(224, 224)\n"
     ]
    }
   ],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from pathlib import Path\n",
    "import time\n",
    "from tqdm.notebook import tqdm\n",
    "\n",
    "org = cv2.ORB_create(nfeatures=500, scoreType=cv2.ORB_FAST_SCORE, patchSize=31)\n",
    "\n",
    "start_time = time.time()\n",
    "img = cv2.imread(str(Path(\"../DataSet_Ando_All_no20/NVB/459.tiff\")), cv2.IMREAD_COLOR)\n",
    "img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
    "img = cv2.resize(img, (224, 224))\n",
    "print(img.shape)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken to detect and compute keypoints: 1.3306 seconds\n"
     ]
    }
   ],
   "source": [
    "\n",
    "kp1, des1 = org.detectAndCompute(img, None)\n",
    "\n",
    "end_time = time.time()\n",
    "print(f\"Time taken to detect and compute keypoints: {end_time - start_time:.4f} seconds\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 102504 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "img_with_keypoints = cv2.drawKeypoints(img, kp1, None, color=(0, 255, 0)) #flags=cv2.DrawMatchesFlags_DRAW_RICH_KEYPOINTS\n",
    "plt.imshow(img_with_keypoints)\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(224, 224, 3)\n"
     ]
    }
   ],
   "source": [
    "img2 = cv2.imread(str(Path(\"459.bmp\")), cv2.IMREAD_COLOR)\n",
    "#img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)\n",
    "img2 = cv2.resize(img2, (224, 224))/255\n",
    "print(img2.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 107720 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(img2)\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mse(img1, img2):\n",
    "   h, w, _ = img1.shape\n",
    "   diff = cv2.subtract(img1, img2)\n",
    "   err = np.sum(diff**2)\n",
    "   mse = err/(float(h*w))\n",
    "   return mse"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.021009214347503708"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mse(img, img2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Video FPS: 59.94, Total frames: 327660, Video length: 5466.46 seg\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d68ac51233a8434ab9c76e61668b68eb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "aFPS: 0.00"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "ename": "error",
     "evalue": "OpenCV(4.11.0) D:\\a\\opencv-python\\opencv-python\\opencv\\modules\\core\\src\\batch_distance.cpp:275: error: (-215:Assertion failed) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function 'cv::batchDistance'\n",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31merror\u001b[0m                                     Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[3], line 31\u001b[0m\n\u001b[0;32m     28\u001b[0m frame \u001b[38;5;241m=\u001b[39m cv2\u001b[38;5;241m.\u001b[39mresize(frame, (\u001b[38;5;241m224\u001b[39m, \u001b[38;5;241m224\u001b[39m))\n\u001b[0;32m     30\u001b[0m kp2, des2 \u001b[38;5;241m=\u001b[39m org\u001b[38;5;241m.\u001b[39mdetectAndCompute(frame, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m---> 31\u001b[0m matches \u001b[38;5;241m=\u001b[39m \u001b[43mbf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmatch\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdes1\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdes2\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     33\u001b[0m avg \u001b[38;5;241m=\u001b[39m \u001b[38;5;28msum\u001b[39m(m\u001b[38;5;241m.\u001b[39mdistance \u001b[38;5;28;01mfor\u001b[39;00m m \u001b[38;5;129;01min\u001b[39;00m matches) \u001b[38;5;241m/\u001b[39m \u001b[38;5;28mlen\u001b[39m(matches)\n\u001b[0;32m     34\u001b[0m best_match \u001b[38;5;241m=\u001b[39m avg \u001b[38;5;28;01mif\u001b[39;00m avg \u001b[38;5;241m<\u001b[39m best_match \u001b[38;5;28;01melse\u001b[39;00m best_match\n",
      "\u001b[1;31merror\u001b[0m: OpenCV(4.11.0) D:\\a\\opencv-python\\opencv-python\\opencv\\modules\\core\\src\\batch_distance.cpp:275: error: (-215:Assertion failed) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function 'cv::batchDistance'\n"
     ]
    }
   ],
   "source": [
    "# Load the video and process it frame by frame\n",
    "\n",
    "video_path = \"459.MP4\"\n",
    "cap = cv2.VideoCapture(video_path)\n",
    "total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n",
    "video_fps = cap.get(cv2.CAP_PROP_FPS)\n",
    "print(f\"Video FPS: {video_fps:.2f}, Total frames: {total_frames}, Video length: {(total_frames / video_fps):.2f} seg\")\n",
    "\n",
    "pbar = tqdm(\n",
    "    total=total_frames,\n",
    "    bar_format=\"{desc}\",      # only render the description\n",
    "    desc=\"aFPS: 0.00\"          # initial text\n",
    ")\n",
    "\n",
    "# Create a Brute-Force Matcher with Hamming distance.\n",
    "bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)\n",
    "\n",
    "orb = cv2.ORB_create()\n",
    "\n",
    "prev = time.perf_counter()\n",
    "best_match = float('inf')\n",
    "while cap.isOpened():\n",
    "    ret, frame = cap.read()\n",
    "    if not ret:\n",
    "        break\n",
    "    \n",
    "    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n",
    "    frame = cv2.resize(frame, (224, 224))\n",
    "    \n",
    "    kp2, des2 = org.detectAndCompute(frame, None)\n",
    "    matches = bf.match(des1, des2)\n",
    "    \n",
    "    avg = sum(m.distance for m in matches) / len(matches)\n",
    "    best_match = avg if avg < best_match else best_match\n",
    "        \n",
    "    now = time.perf_counter()\n",
    "    fps = 1.0 / (now - prev)\n",
    "    prev = now\n",
    "    \n",
    "    pbar.set_description(f\"aFPS: {fps:.2f}, best Match. {best_match:.2f}\")\n",
    "    pbar.update(1)\n",
    "    \n",
    "pbar.close()\n",
    "cap.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "def seconds_to_hms(seconds):\n",
    "    hours = seconds // 3600\n",
    "    minutes = (seconds % 3600) // 60\n",
    "    secs = seconds % 60\n",
    "    return f'{int(hours)}:{int(minutes):02}:{int(secs):02}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'0:15:11'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seconds_to_hms(911.7731)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pyRARP",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
