Skip to content

Commit

Permalink
Formatting and Style (#53)
Browse files Browse the repository at this point in the history
* updated pre-commit hooks

* initial formatting

* fix typo

* style changes

* reverted
  • Loading branch information
kozlov721 authored Dec 19, 2023
1 parent 40f4b36 commit 4e8ca1c
Show file tree
Hide file tree
Showing 51 changed files with 890 additions and 2,399 deletions.
27 changes: 23 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
repos:
- repo: https://github.com/ambv/black
rev: 23.3.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.2
hooks:
- id: black
language_version: python3.8
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
types_or: [python, pyi, jupyter]
- id: ruff-format
types_or: [python, pyi, jupyter]

- repo: https://github.com/PyCQA/docformatter
rev: v1.7.5
hooks:
- id: docformatter
additional_dependencies: [tomli]
args: [--in-place]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: no-commit-to-branch
args: ['--branch', 'main', '--branch', 'dev']

- repo: https://github.com/executablebooks/mdformat
rev: 0.7.10
hooks:
- id: mdformat
additional_dependencies:
- mdformat-gfm
- mdformat-toc
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ You could see that this configuration could also be used for any OAK-D-like prod

Some more definitions:

* `HType`\: The type of the component. Right now, there's really only `IMAGE`. But eventually, we will have video and point cloud.
* `IType`\: For an image component, the type of the image. `BGR` is for any 3-channel image, `MONO` is for single-channel images, and `DEPTH` and `DISPARITY` can be uint16 single-channel images for subpixel disparity. The only difference between `DISPARITY` and `DEPTH` is a semantic difference.
- `HType`: The type of the component. Right now, there's really only `IMAGE`. But eventually, we will have video and point cloud.
- `IType`: For an image component, the type of the image. `BGR` is for any 3-channel image, `MONO` is for single-channel images, and `DEPTH` and `DISPARITY` can be uint16 single-channel images for subpixel disparity. The only difference between `DISPARITY` and `DEPTH` is a semantic difference.

#### Adding Data

Expand Down Expand Up @@ -177,8 +177,8 @@ with LuxonisDataset(team_name, dataset_name) as dataset:

The first element in the loaded tuple is the image(s) and the second is a dictionary where the keys may provide annotations in different formats.

* `imgs` is (batch size x number of channels x height x width)
* `dict['class']` is (batch size x number of classes)
* `dict['bbox']` is (number of boxes in batch x 6 [image ID, class, x, y, width, height])
* `dict['segmentation']` is (batch size x number of classes x height x width)
* `dict['keypoints']` is (batch size x (number of points*2 + 1))
- `imgs` is (batch size x number of channels x height x width)
- `dict['class']` is (batch size x number of classes)
- `dict['bbox']` is (number of boxes in batch x 6 \[image ID, class, x, y, width, height\])
- `dict['segmentation']` is (batch size x number of classes x height x width)
- `dict['keypoints']` is (batch size x (number of points\*2 + 1))
137 changes: 79 additions & 58 deletions examples/COCO_people_subset.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@
"metadata": {},
"outputs": [],
"source": [
"import glob, json, os\n",
"import glob\n",
"import json\n",
"import numpy as np\n",
"import cv2\n",
"from copy import deepcopy\n",
"from tqdm import tqdm\n",
"import matplotlib.pyplot as plt\n",
"from pycocotools import mask as mask_utils\n",
"import os\n",
"import zipfile\n",
"import gdown\n",
"\n",
"from luxonis_ml.data import *\n",
"from luxonis_ml.data import LuxonisDataset, LuxonisLoader\n",
"from luxonis_ml.enums import LabelType"
]
},
Expand Down Expand Up @@ -59,9 +61,22 @@
},
"outputs": [],
"source": [
"! pip install gdown\n",
"! gdown 1XlvFK7aRmt8op6-hHkWVKIJQeDtOwoRT -O ../data/COCO_people_subset.zip\n",
"! unzip ../data/COCO_people_subset.zip -d ../data/"
"url = \"https://drive.google.com/uc?id=1XlvFK7aRmt8op6-hHkWVKIJQeDtOwoRT\"\n",
"output_zip = \"../data/COCO_people_subset.zip\"\n",
"output_folder = \"../data/\"\n",
"\n",
"# Check if the data already exists\n",
"if not os.path.exists(output_zip) and not os.path.exists(\n",
" os.path.join(output_folder, \"COCO_people_subset\")\n",
"):\n",
" # Download the file\n",
" gdown.download(url, output_zip, quiet=False)\n",
"\n",
" # Unzip the file\n",
" with zipfile.ZipFile(output_zip, \"r\") as zip_ref:\n",
" zip_ref.extractall(output_folder)\n",
"else:\n",
" print(\"Data already exists. Exiting.\")"
]
},
{
Expand Down Expand Up @@ -104,88 +119,86 @@
"# splits = ['train' for _ in range(20)] + ['val' for _ in range(10)]\n",
"\n",
"def COCO_people_subset_generator():\n",
"\n",
" # find image paths and load COCO annotations\n",
" img_dir = '../data/person_val2017_subset'\n",
" annot_file = '../data/person_keypoints_val2017.json'\n",
" img_dir = \"../data/person_val2017_subset\"\n",
" annot_file = \"../data/person_keypoints_val2017.json\"\n",
" # get paths to images sorted by number\n",
" im_paths = glob.glob(img_dir+'/*.jpg')\n",
" nums = np.array([int(path.split('/')[-1].split('.')[0]) for path in im_paths])\n",
" im_paths = glob.glob(img_dir + \"/*.jpg\")\n",
" nums = np.array([int(path.split(\"/\")[-1].split(\".\")[0]) for path in im_paths])\n",
" idxs = np.argsort(nums)\n",
" im_paths = list(np.array(im_paths)[idxs])\n",
" # load \n",
" # load\n",
" with open(annot_file) as file:\n",
" data = json.load(file)\n",
" imgs = data['images']\n",
" anns = data['annotations']\n",
" \n",
" imgs = data[\"images\"]\n",
" anns = data[\"annotations\"]\n",
"\n",
" for i, path in tqdm(enumerate(im_paths)):\n",
" # find annotations matching the COCO image\n",
" gran = path.split('/')[-1]\n",
" img = [img for img in imgs if img['file_name']==gran][0]\n",
" img_id = img['id']\n",
" img_anns = [ann for ann in anns if ann['image_id'] == img_id]\n",
" \n",
" gran = path.split(\"/\")[-1]\n",
" img = [img for img in imgs if img[\"file_name\"] == gran][0]\n",
" img_id = img[\"id\"]\n",
" img_anns = [ann for ann in anns if ann[\"image_id\"] == img_id]\n",
"\n",
" # load the image\n",
" im = cv2.imread(path)\n",
" height, width, _ = im.shape\n",
" \n",
" # initialize annotations for LDF\n",
" mask = np.zeros((height, width)) # segmentation mask is always a HxW numpy array\n",
" boxes = [] # bounding boxes are a list of [class, x, y, width, height] of the box\n",
" keypoints = [] # keypoints are a list of classes and (x,y) points\n",
" \n",
"\n",
" if len(img_anns):\n",
" yield {\n",
" \"file\": path,\n",
" \"class\": \"person\",\n",
" \"type\": \"classification\",\n",
" \"value\": True\n",
" \"value\": True,\n",
" }\n",
" \n",
"\n",
" for ann in img_anns:\n",
" # COCO-specific conversion for segmentation\n",
" seg = ann['segmentation']\n",
" if isinstance(seg, list): # polyline format\n",
" seg = ann[\"segmentation\"]\n",
" if isinstance(seg, list): # polyline format\n",
" poly = []\n",
" for s in seg:\n",
" poly_arr = np.array(s).reshape(-1,2)\n",
" poly += [(poly_arr[i,0]/width, poly_arr[i,1]/height) for i in range(len(poly_arr))]\n",
" poly_arr = np.array(s).reshape(-1, 2)\n",
" poly += [\n",
" (poly_arr[i, 0] / width, poly_arr[i, 1] / height)\n",
" for i in range(len(poly_arr))\n",
" ]\n",
" yield {\n",
" \"file\": path,\n",
" \"class\": \"person\",\n",
" \"type\": \"polyline\",\n",
" \"value\": poly\n",
" \"value\": poly,\n",
" }\n",
" else: # RLE format\n",
" else: # RLE format\n",
" value = (seg[\"size\"][0], seg[\"size\"][1], seg[\"counts\"])\n",
" yield {\n",
" \"file\": path,\n",
" \"class\": \"person\",\n",
" \"type\": \"segmentation\",\n",
" \"value\": value\n",
" \"value\": value,\n",
" }\n",
" \n",
" \n",
"\n",
" # COCO-specific conversion for bounding boxes\n",
" x, y, w, h = ann['bbox']\n",
" x, y, w, h = ann[\"bbox\"]\n",
" yield {\n",
" \"file\": path,\n",
" \"class\": \"person\",\n",
" \"type\": \"box\",\n",
" \"value\": (x/width, y/height, w/width, h/height)\n",
" \"value\": (x / width, y / height, w / width, h / height),\n",
" }\n",
" \n",
"\n",
" # COCO-specific conversion for keypoints\n",
" kps = np.array(ann['keypoints']).reshape(-1, 3)\n",
" kps = np.array(ann[\"keypoints\"]).reshape(-1, 3)\n",
" keypoint = []\n",
" for kp in kps:\n",
" keypoint.append((float(kp[0]/width), float(kp[1]/height), int(kp[2]))) \n",
" keypoint.append(\n",
" (float(kp[0] / width), float(kp[1] / height), int(kp[2]))\n",
" )\n",
" yield {\n",
" \"file\": path,\n",
" \"class\": \"person\",\n",
" \"type\": \"keypoints\",\n",
" \"value\": keypoint\n",
" \"value\": keypoint,\n",
" }"
]
},
Expand All @@ -199,15 +212,17 @@
"dataset = LuxonisDataset(dataset_name)\n",
"dataset.set_classes([\"person\"])\n",
"\n",
"annot_file = '../data/person_keypoints_val2017.json'\n",
"annot_file = \"../data/person_keypoints_val2017.json\"\n",
"with open(annot_file) as file:\n",
" data = json.load(file)\n",
"dataset.set_skeletons({\n",
" \"person\": {\n",
" \"labels\": data[\"categories\"][0]['keypoints'],\n",
" \"edges\": (np.array(data[\"categories\"][0][\"skeleton\"])-1).tolist()\n",
"dataset.set_skeletons(\n",
" {\n",
" \"person\": {\n",
" \"labels\": data[\"categories\"][0][\"keypoints\"],\n",
" \"edges\": (np.array(data[\"categories\"][0][\"skeleton\"]) - 1).tolist(),\n",
" }\n",
" }\n",
"})\n",
")\n",
"dataset.add(COCO_people_subset_generator)"
]
},
Expand Down Expand Up @@ -251,7 +266,7 @@
" box = ann[LabelType.BOUNDINGBOX]\n",
" seg = ann[LabelType.SEGMENTATION]\n",
" kps = ann[LabelType.KEYPOINT]\n",
" \n",
"\n",
" # print(\"Sample classification tensor\")\n",
" # print(cls)\n",
" # print()\n",
Expand All @@ -270,19 +285,25 @@
"\n",
" h, w, _ = image.shape\n",
" for b in box:\n",
" cv2.rectangle(image, (int(b[1]*w),int(b[2]*h)), (int(b[1]*w+b[3]*w),int(b[2]*h+b[4]*h)), (255,0,0), 2)\n",
" mask_viz = np.zeros((h,w,3)).astype(np.uint8)\n",
" cv2.rectangle(\n",
" image,\n",
" (int(b[1] * w), int(b[2] * h)),\n",
" (int(b[1] * w + b[3] * w), int(b[2] * h + b[4] * h)),\n",
" (255, 0, 0),\n",
" 2,\n",
" )\n",
" mask_viz = np.zeros((h, w, 3)).astype(np.uint8)\n",
" for mask in seg:\n",
" mask_viz[mask==1, 2] = 255\n",
" mask_viz[mask == 1, 2] = 255\n",
" image = cv2.addWeighted(image, 0.5, mask_viz, 0.5, 0)\n",
"\n",
" for kp in kps:\n",
" kp = kp[1:].reshape(-1,3)\n",
" kp = kp[1:].reshape(-1, 3)\n",
" for k in kp:\n",
" cv2.circle(image, (int(k[0]*w),int(k[1]*h)), 2, (0,255,0), 2)\n",
" \n",
" cv2.circle(image, (int(k[0] * w), int(k[1] * h)), 2, (0, 255, 0), 2)\n",
"\n",
" plt.imshow(image)\n",
" plt.axis('off') # Optional: Hide axis\n",
" plt.axis(\"off\") # Optional: Hide axis\n",
" plt.show()\n",
" # break"
]
Expand Down
Loading

0 comments on commit 4e8ca1c

Please sign in to comment.