-
Notifications
You must be signed in to change notification settings - Fork 11
Feat/Improve Yolo-v4 Model #149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
hughjazzman
wants to merge
31
commits into
nandium:main
Choose a base branch
from
hughjazzman:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
f7928cd
feat: improve model with more images
hughjazzman 99c2c84
Merge branch 'main' of https://github.com/hughjazzman/yolo_bouldering…
hughjazzman 6ea6814
docs: apply prettier
hughjazzman 2153462
Merge branch 'yarkhinephyo:main' into main
hughjazzman 27e03dc
fix: clean up test data and code
hughjazzman f8d3996
docs: use pipenv instead of pip in local_prediction
hughjazzman 113ec04
fix: minor model improvement code fixes
hughjazzman b8d2770
docs: port API with swagger
hughjazzman 6a0a37e
Merge branch 'yarkhinephyo:main' into main
hughjazzman c595a2e
docs: fix doc bugs
hughjazzman 8b6e8eb
docs: update json api
hughjazzman b6b85a4
API definition transferred by SwaggerHub
hughjazzman 05aa2bd
Merge branch 'yarkhinephyo:main' into main
hughjazzman 230fa01
ci: add Swagger UI deployment to GitHub Pages
hughjazzman a971e19
fix: master to main
hughjazzman 03442a1
fix: file not found
hughjazzman fc766c6
ci: change to pjoc-team
hughjazzman 5743021
Merge branch 'main' into main
hughjazzman 8d14418
docs: remove old api and update names
hughjazzman 3baadb5
fix: merge from main
hughjazzman 0bf662e
Merge branch 'yarkhinephyo-main' into main
hughjazzman e1b8a9a
Merge from upstream
hughjazzman bb9b8e5
feat: improve model with more trained images
hughjazzman 75e6b27
Merge from upstream
hughjazzman 05dbdf9
docs: add instructions and help
hughjazzman 17583f5
refactor: expand out less readable functions
hughjazzman 2db6cd2
refactor: EOF and newlines
hughjazzman 45a77f6
refactor: factor out constants, add named params
hughjazzman 256bd82
refactor: apply code review suggestions
hughjazzman 8dc8f8e
Merge remote-tracking branch 'upstream/main' into main
hughjazzman 7232736
docs: remove train_test_split
hughjazzman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| import cv2 | ||
| import numpy as np | ||
| from configparser import RawConfigParser | ||
|
|
||
| CONFIDENCE_THRESHOLD = 0.3 | ||
| NMS_IOU_THRESHOLD = 0.4 | ||
| SCALE_FACTOR = 0.00392 | ||
|
|
||
| class BaseInference: | ||
| """ | ||
| Base Inference class for predictions | ||
|
|
||
| ... | ||
|
|
||
| Attributes | ||
| ---------- | ||
| weight_path : str | ||
| path to the .weights file | ||
| config_path : str | ||
| path to the .cfg file | ||
| classes : list | ||
| names of classes detected | ||
| score_threshold : float | ||
| threshold to classify object as detected | ||
| nms_threshold : float | ||
| threshold for non-max suppression | ||
|
|
||
| Methods | ||
| ------- | ||
| run() | ||
| Obtains predicted boxes | ||
| """ | ||
|
|
||
| def __init__(self, weight_path, config_path, classes, score_threshold=None, nms_thresh=None): | ||
| self.weight_path = weight_path | ||
| self.config_path = config_path | ||
| self.classes = classes | ||
| self.net = None | ||
| self.score_threshold = score_threshold if score_threshold is not None else CONFIDENCE_THRESHOLD | ||
| self.nms_thresh = nms_thresh if nms_thresh is not None else NMS_IOU_THRESHOLD | ||
|
|
||
| self._initialize_model() | ||
| self._read_config() | ||
|
|
||
| def _initialize_model(self): | ||
| # Load Yolo | ||
| self.net = cv2.dnn.readNet( | ||
| self.weight_path, | ||
| self.config_path | ||
| ) | ||
| layer_names = self.net.getLayerNames() | ||
| # Gets the indexes of layers with unconnected outputs, | ||
| # then stores the associated names into output_layers | ||
| self.output_layers = [layer_names[i[0] - 1] for i in self.net.getUnconnectedOutLayers()] | ||
hughjazzman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def _read_config(self): | ||
| cfg = RawConfigParser(strict=False) | ||
| cfg.read(self.config_path) | ||
|
|
||
| assert 'net' in cfg, 'No net section in config' | ||
|
|
||
| net_dict = dict(cfg.items('net')) | ||
|
|
||
| assert 'height' in net_dict and 'weight' in net_dict, 'No height and/or weight in config' | ||
| self.train_height_width = (int(net_dict['height']), int(net_dict['width'])) | ||
|
|
||
| def run(self, img, height=None, width=None): | ||
| """ | ||
| Parameters | ||
| ---------- | ||
| img : cv2.Mat | ||
| Image as a matrix | ||
| height : int, optional | ||
| Height of img (default is None) | ||
| width : int, optional | ||
| Width of img (default is None) | ||
|
|
||
| Returns | ||
| ------- | ||
| class_ids : list(int) | ||
| Class IDs of boxes | ||
| box_dims : list(list(int)) | ||
| Dimensions of boxes | ||
| box_confidences : list(float) | ||
| Confidence scores of boxes | ||
| box_dims_norm : list(list(float)) | ||
| Normalised dimensions of boxes | ||
| indexes : list(int) | ||
| Indexes of boxes that passed NMS | ||
| """ | ||
hughjazzman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # If run is called without height or width given | ||
| if height is None or width is None: | ||
| height, width, channels = img.shape | ||
|
|
||
| # Detecting objects | ||
| blob = cv2.dnn.blobFromImage( | ||
| image = img, | ||
| scalefactor = SCALE_FACTOR, | ||
| size = self.train_height_width, | ||
| mean = (0,0,0), | ||
| swapRB = True, | ||
| crop = False | ||
| ) | ||
|
|
||
| self.net.setInput(blob) | ||
| outs = self.net.forward(self.output_layers) | ||
|
|
||
| class_ids, box_dims, box_confidences, box_dims_norm, indexes = self._get_filtered_boxes(outs, height, width) | ||
|
|
||
| return class_ids, box_dims, box_confidences, box_dims_norm, indexes | ||
|
|
||
| def _get_filtered_boxes(self, output, height, width): | ||
| # Showing informations on the screen | ||
| class_ids = [] | ||
| box_confidences = [] | ||
| box_dims = [] | ||
| # Saving to txt | ||
| box_dims_norm = [] | ||
|
|
||
| for out in output: | ||
| for detection in out: | ||
|
|
||
| scores = detection[5:] | ||
| class_id = np.argmax(scores) | ||
| confidence = scores[class_id] | ||
| if confidence > self.score_threshold: | ||
| # Object detected | ||
| center_x = int(detection[0] * width) | ||
| center_y = int(detection[1] * height) | ||
| w = int(detection[2] * width) | ||
| h = int(detection[3] * height) | ||
|
|
||
| # Rectangle coordinates | ||
| x = int(center_x - w / 2) | ||
| y = int(center_y - h / 2) | ||
|
|
||
| box_dims.append([x, y, w, h]) | ||
| box_confidences.append(float(confidence)) | ||
| class_ids.append(class_id) | ||
|
|
||
| # Save normalised format | ||
| box_dims_norm.append(detection[:4]) | ||
|
|
||
| indexes = cv2.dnn.NMSBoxes(box_dims, box_confidences, self.score_threshold, self.nms_thresh) | ||
| indexes = [int(i) for i in indexes] | ||
|
|
||
| return class_ids, box_dims, box_confidences, box_dims_norm, indexes | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| from base_inference import BaseInference | ||
|
|
||
| class ServiceInference(BaseInference): | ||
| """ | ||
| Inference class for predictions on predict_microservice | ||
|
|
||
| ... | ||
|
|
||
| Methods | ||
| ------- | ||
| run(img, scaled_width) | ||
| Obtains predicted boxes for predict_microservice | ||
| """ | ||
hughjazzman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def run(self, img, scaled_width): | ||
| """ | ||
| Parameters | ||
| ---------- | ||
| img : cv2.Mat | ||
| Image as a matrix | ||
| scaled_width : int | ||
| Scaled width of images | ||
|
|
||
| Returns | ||
| ------- | ||
| scaled_height : int | ||
| Scaled height of img | ||
| scaled_width : int | ||
| Scaled width of img | ||
| boxes : list | ||
| List of predicted boxes in JSON format | ||
| """ | ||
|
|
||
| height, width = img.shape | ||
| # If given width is 0, do not scale | ||
| scaled_width = scaled_width if scaled_width != 0 else width | ||
| scaled_height = int((scaled_width / width) * height) | ||
|
|
||
| class_ids, box_dims, box_confidences, _, indexes = super().run(img, scaled_height, scaled_width) | ||
|
|
||
| boxes = self._get_boxes_dict(box_dims, box_confidences, class_ids, indexes) | ||
| return scaled_height, scaled_width, boxes | ||
|
|
||
| def _get_boxes_dict(self, box_dims, box_confidences, class_ids, indexes): | ||
| """ | ||
| Parameters | ||
| ---------- | ||
| box_dims : list | ||
| Dimensions of predicted boxes | ||
| box_confidences : list | ||
| Confidence scores of predicted boxes | ||
| class_ids : list | ||
| Class IDs of predicted boxes | ||
| indexes : list | ||
| Indexes of predicted boxes after NMS | ||
|
|
||
| Returns | ||
| ------- | ||
| boxes : list | ||
| List of predicted boxes in JSON format | ||
| """ | ||
|
|
||
| boxes = [] | ||
| for i in indexes: | ||
| x, y, w, h = box_dims[i] | ||
| boxes.append({ | ||
| "x": x, | ||
| "y": y, | ||
| "w": w, | ||
| "h": h, | ||
| "confidence": float(box_confidences[i]), | ||
| "class": str(self.classes[class_ids[i]]) | ||
| }) | ||
|
|
||
| # Sort boxes in descending sizes | ||
| boxes = sorted(boxes, key=lambda box: box["w"] * box["h"], reverse=True) | ||
|
|
||
| return boxes | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file modified
BIN
+0 Bytes
(100%)
lambda_backend/predict_microservice/weights/yolov4-tiny-obj.weights
Binary file not shown.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.