Sourcery refactored master branch#1
Conversation
| count = 0 | ||
| for img in extracted_objects: | ||
| count += 1 | ||
|
|
||
| cv2.imshow("Window" + str(count), img) | ||
| for count, img in enumerate(extracted_objects, start=1): | ||
| cv2.imshow(f"Window{str(count)}", img) |
There was a problem hiding this comment.
Lines 19-23 refactored with the following changes:
- Replace manual loop counter with call to enumerate (
convert-to-enumerate) - Use f-string instead of string concatenation (
use-fstring-for-concatenation)
| count = 0 | ||
| for img in extracted_objects: | ||
| count += 1 | ||
|
|
||
| cv2.imshow("Window" + str(count), img) | ||
| for count, img in enumerate(extracted_objects, start=1): | ||
| cv2.imshow(f"Window{str(count)}", img) |
There was a problem hiding this comment.
Lines 17-21 refactored with the following changes:
- Replace manual loop counter with call to enumerate (
convert-to-enumerate) - Use f-string instead of string concatenation (
use-fstring-for-concatenation)
| counter = 0 | ||
|
|
||
| for eachItem in output_count: | ||
| counter += 1 | ||
| labels.append(eachItem + " = " + str(output_count[eachItem])) | ||
| labels.append(f"{eachItem} = {str(output_count[eachItem])}") |
There was a problem hiding this comment.
Function forFrame refactored with the following changes:
- Replace manual loop counter with call to enumerate (
convert-to-enumerate) - Remove unnecessary calls to
enumeratewhen the index is not used (remove-unused-enumerate) - Use f-string instead of string concatenation [×4] (
use-fstring-for-concatenation)
| counter = 0 | ||
|
|
||
| for eachItem in average_count: | ||
| counter += 1 | ||
| labels.append(eachItem + " = " + str(average_count[eachItem])) | ||
| labels.append(f"{eachItem} = {str(average_count[eachItem])}") |
There was a problem hiding this comment.
Function forSecond refactored with the following changes:
- Replace manual loop counter with call to enumerate (
convert-to-enumerate) - Remove unnecessary calls to
enumeratewhen the index is not used (remove-unused-enumerate) - Use f-string instead of string concatenation [×4] (
use-fstring-for-concatenation)
| if os.path.isfile(image_input): | ||
| img = Image.open(image_input).convert("RGB") | ||
| images.append(preprocess(img)) | ||
| else: | ||
| if not os.path.isfile(image_input): | ||
| raise ValueError(f"image path '{image_input}' is not found or a valid file") | ||
| img = Image.open(image_input).convert("RGB") | ||
| images.append(preprocess(img)) |
There was a problem hiding this comment.
Function ImageClassification.__load_image refactored with the following changes:
- Swap if/else branches (
swap-if-else-branches) - Remove unnecessary else after guard condition (
remove-unnecessary-else) - Replace f-string with no interpolated values with string (
remove-redundant-fstring)
| if not self.__model_loaded: | ||
| self.__load_classes() | ||
| try: | ||
| # change the last layer of the networks to conform to the number | ||
| # of unique classes in the custom dataset used to train the custom | ||
| # model | ||
|
|
||
| if self.__model_type == "resnet50": | ||
| self.__model = resnet50(pretrained=False) | ||
| in_features = self.__model.fc.in_features | ||
| self.__model.fc = nn.Linear(in_features, len(self.__class_names)) | ||
| elif self.__model_type == "mobilenet_v2": | ||
| self.__model = mobilenet_v2(pretrained=False) | ||
| in_features = self.__model.classifier[1].in_features | ||
| self.__model.classifier[1] = nn.Linear(in_features, len(self.__class_names)) | ||
| elif self.__model_type == "inception_v3": | ||
| self.__model = inception_v3(pretrained=False) | ||
| in_features = self.__model.fc.in_features | ||
| self.__model.fc = nn.Linear(in_features, len(self.__class_names)) | ||
| elif self.__model_type == "densenet121": | ||
| self.__model = densenet121(pretrained=False) | ||
| in_features = self.__model.classifier.in_features | ||
| self.__model.classifier = nn.Linear(in_features, len(self.__class_names)) | ||
| else: | ||
| raise RuntimeError("Unknown model type.\nEnsure the model type is properly set.") | ||
| if self.__model_loaded: | ||
| return | ||
| self.__load_classes() | ||
| try: | ||
| # change the last layer of the networks to conform to the number | ||
| # of unique classes in the custom dataset used to train the custom | ||
| # model | ||
|
|
||
| if self.__model_type == "resnet50": | ||
| self.__model = resnet50(pretrained=False) | ||
| in_features = self.__model.fc.in_features | ||
| self.__model.fc = nn.Linear(in_features, len(self.__class_names)) | ||
| elif self.__model_type == "mobilenet_v2": | ||
| self.__model = mobilenet_v2(pretrained=False) | ||
| in_features = self.__model.classifier[1].in_features | ||
| self.__model.classifier[1] = nn.Linear(in_features, len(self.__class_names)) | ||
| elif self.__model_type == "inception_v3": | ||
| self.__model = inception_v3(pretrained=False) | ||
| in_features = self.__model.fc.in_features | ||
| self.__model.fc = nn.Linear(in_features, len(self.__class_names)) | ||
| elif self.__model_type == "densenet121": | ||
| self.__model = densenet121(pretrained=False) | ||
| in_features = self.__model.classifier.in_features | ||
| self.__model.classifier = nn.Linear(in_features, len(self.__class_names)) | ||
| else: | ||
| raise RuntimeError("Unknown model type.\nEnsure the model type is properly set.") | ||
|
|
||
| state_dict = torch.load(self.__model_path, map_location=self.__device) | ||
| state_dict = torch.load(self.__model_path, map_location=self.__device) | ||
|
|
||
| if self.__model_type == "densenet121": | ||
| # '.'s are no longer allowed in module names, but previous densenet layers | ||
| # as provided by the pytorch organization has names that uses '.'s. | ||
| pattern = re.compile( | ||
| r"^(.*denselayer\d+\.(?:norm|relu|conv))\.((?:[12])\." | ||
| "(?:weight|bias|running_mean|running_var))$" | ||
| ) | ||
| for key in list(state_dict.keys()): | ||
| res = pattern.match(key) | ||
| if res: | ||
| new_key = res.group(1) + res.group(2) | ||
| state_dict[new_key] = state_dict[key] | ||
| del state_dict[key] | ||
| if self.__model_type == "densenet121": | ||
| # '.'s are no longer allowed in module names, but previous densenet layers | ||
| # as provided by the pytorch organization has names that uses '.'s. | ||
| pattern = re.compile( | ||
| r"^(.*denselayer\d+\.(?:norm|relu|conv))\.((?:[12])\." | ||
| "(?:weight|bias|running_mean|running_var))$" | ||
| ) | ||
| for key in list(state_dict.keys()): | ||
| if res := pattern.match(key): | ||
| new_key = res[1] + res[2] | ||
| state_dict[new_key] = state_dict[key] | ||
| del state_dict[key] | ||
|
|
||
| self.__model.load_state_dict(state_dict) | ||
| self.__model.to(self.__device).eval() | ||
| self.__model_loaded = True | ||
| self.__model.load_state_dict(state_dict) | ||
| self.__model.to(self.__device).eval() | ||
| self.__model_loaded = True | ||
|
|
||
| except Exception as e: | ||
| raise Exception("Weight loading failed.\nEnsure the model path is" | ||
| " set and the weight file is in the specified model path.") | ||
| except Exception as e: | ||
| raise Exception("Weight loading failed.\nEnsure the model path is" | ||
| " set and the weight file is in the specified model path.") |
There was a problem hiding this comment.
Function CustomImageClassification.loadModel refactored with the following changes:
- Add guard clause (
last-if-guard) - Use named expression to simplify assignment and conditional (
use-named-expression) - Replace m.group(x) with m[x] for re.Match objects [×2] (
use-getitem-for-re-match-groups)
| probabilities = torch.softmax(output, dim=1) | ||
| topN_prob, topN_catid = torch.topk(probabilities, result_count) | ||
|
|
There was a problem hiding this comment.
Function CustomImageClassification.classifyImage refactored with the following changes:
- Remove unnecessary calls to
enumeratewhen the index is not used (remove-unused-enumerate)
| allowed_exts = ["jpg", "jpeg", "png"] | ||
| fnames = [] | ||
| original_dims = [] | ||
| inputs = [] | ||
| original_imgs = [] | ||
| if type(input_image) == str: | ||
| if os.path.isfile(input_image): | ||
| if input_image.rsplit('.')[-1].lower() in allowed_exts: | ||
| img = cv2.imread(input_image) | ||
| else: | ||
| if not os.path.isfile(input_image): | ||
| raise ValueError(f"image path '{input_image}' is not found or a valid file") | ||
| allowed_exts = ["jpg", "jpeg", "png"] | ||
| if input_image.rsplit('.')[-1].lower() in allowed_exts: | ||
| img = cv2.imread(input_image) | ||
| elif type(input_image) == np.ndarray: | ||
| img = input_image | ||
| elif "PIL" in str(type(input_image)): | ||
| img = np.asarray(input_image) | ||
| else: | ||
| raise ValueError(f"Invalid image input format") | ||
| raise ValueError("Invalid image input format") | ||
|
|
||
| img_h, img_w, _ = img.shape | ||
|
|
||
| original_imgs.append(np.array(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)).astype(np.uint8)) | ||
| original_dims.append((img_w, img_h)) | ||
| original_imgs = [ | ||
| np.array(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)).astype(np.uint8) | ||
| ] | ||
| if type(input_image) == str: | ||
| fnames.append(os.path.basename(input_image)) | ||
| else: | ||
| fnames.append("") | ||
| inputs.append(prepare_image(img, (416, 416))) | ||
|
|
||
| if original_dims: | ||
| fnames.append("") | ||
| inputs = [prepare_image(img, (416, 416))] | ||
| if original_dims := [(img_w, img_h)]: |
There was a problem hiding this comment.
Function ObjectDetection.__load_image_yolo refactored with the following changes:
- Move assignments closer to their usage (
move-assign) - Move assignment closer to its usage within a block [×4] (
move-assign-in-block) - Swap if/else branches (
swap-if-else-branches) - Remove unnecessary else after guard condition (
remove-unnecessary-else) - Replace f-string with no interpolated values with string (
remove-redundant-fstring) - Merge append into list declaration [×3] (
merge-list-append) - Use named expression to simplify assignment and conditional (
use-named-expression)
| ) | ||
| ) | ||
| if type(input_image) == np.ndarray: | ||
| cv2.imwrite(temp_path, input_image) | ||
| elif "PIL" in str(type(input_image)): | ||
| input_image.save(temp_path) | ||
| else: | ||
| raise ValueError( | ||
| f"Invalid image input. Supported formats are OpenCV/Numpy array, PIL image or image file path" | ||
| "Invalid image input. Supported formats are OpenCV/Numpy array, PIL image or image file path" |
There was a problem hiding this comment.
Function ObjectDetection.__save_temp_img refactored with the following changes:
- Replace f-string with no interpolated values with string (
remove-redundant-fstring)
| allowed_file_extensions = ["jpg", "jpeg", "png"] | ||
| images = [] | ||
| scaled_images = [] | ||
| fnames = [] | ||
|
|
||
| delete_file = False | ||
| if type(input_image) is not str: | ||
| input_image = self.__save_temp_img(input_image=input_image) | ||
| delete_file = True | ||
|
|
||
|
|
||
| if os.path.isfile(input_image): | ||
| if input_image.rsplit('.')[-1].lower() in allowed_file_extensions: | ||
| img = read_image(input_image, ImageReadMode.RGB) | ||
| images.append(img) | ||
| scaled_images.append(img.div(255.0).to(self.__device)) | ||
| fnames.append(os.path.basename(input_image)) | ||
| else: | ||
| if not os.path.isfile(input_image): | ||
| raise ValueError(f"Input image with path {input_image} not a valid file") | ||
|
|
||
| allowed_file_extensions = ["jpg", "jpeg", "png"] | ||
| if input_image.rsplit('.')[-1].lower() in allowed_file_extensions: | ||
| img = read_image(input_image, ImageReadMode.RGB) | ||
| images.append(img) | ||
| scaled_images.append(img.div(255.0).to(self.__device)) | ||
| fnames.append(os.path.basename(input_image)) | ||
| if delete_file: | ||
| os.remove(input_image) | ||
|
|
There was a problem hiding this comment.
Function ObjectDetection.__load_image_retinanet refactored with the following changes:
- Move assignments closer to their usage (
move-assign) - Swap if/else branches (
swap-if-else-branches) - Remove unnecessary else after guard condition (
remove-unnecessary-else)
| if not self.__model_loaded: | ||
| if self.__model_type=="yolov3": | ||
| self.__model = YoloV3( | ||
| anchors=self.__anchors , | ||
| num_classes=len(self.__classes),\ | ||
| if self.__model_loaded: | ||
| return | ||
| if self.__model_type=="yolov3": | ||
| self.__model = YoloV3( | ||
| anchors=self.__anchors , | ||
| num_classes=len(self.__classes),\ | ||
| device=self.__device | ||
| ) | ||
| elif self.__model_type=="tiny-yolov3": | ||
| self.__model = YoloV3Tiny( | ||
| anchors=self.__anchors, | ||
| num_classes=len(self.__classes), | ||
| device=self.__device | ||
| ) | ||
| elif self.__model_type=="retinanet": | ||
| ) | ||
| elif self.__model_type=="tiny-yolov3": | ||
| self.__model = YoloV3Tiny( | ||
| anchors=self.__anchors, | ||
| num_classes=len(self.__classes), | ||
| device=self.__device | ||
| ) | ||
| elif self.__model_type=="retinanet": | ||
|
|
||
| self.__classes = self.__load_classes(os.path.join(os.path.dirname(os.path.abspath(__file__)), "coco91_classes.txt")) | ||
| self.__classes = self.__load_classes(os.path.join(os.path.dirname(os.path.abspath(__file__)), "coco91_classes.txt")) | ||
|
|
||
| self.__model = torchvision.models.detection.retinanet_resnet50_fpn( | ||
| pretrained=False, num_classes=91, | ||
| pretrained_backbone = False | ||
| ) | ||
| else: | ||
| raise ValueError(f"Invalid model type. Call setModelTypeAsYOLOv3(), setModelTypeAsTinyYOLOv3() or setModelTypeAsRetinaNet to set a model type before loading the model") | ||
| self.__model = torchvision.models.detection.retinanet_resnet50_fpn( | ||
| pretrained=False, num_classes=91, | ||
| pretrained_backbone = False | ||
| ) | ||
| else: | ||
| raise ValueError( | ||
| "Invalid model type. Call setModelTypeAsYOLOv3(), setModelTypeAsTinyYOLOv3() or setModelTypeAsRetinaNet to set a model type before loading the model" | ||
| ) | ||
|
|
||
| state_dict = torch.load(self.__model_path, map_location=self.__device) | ||
| try: | ||
| self.__model.load_state_dict(state_dict) | ||
| self.__model_loaded = True | ||
| self.__model.to(self.__device).eval() | ||
| except: | ||
| raise RuntimeError("Invalid weights!!!") from None | ||
| state_dict = torch.load(self.__model_path, map_location=self.__device) | ||
| try: | ||
| self.__model.load_state_dict(state_dict) | ||
| self.__model_loaded = True | ||
| self.__model.to(self.__device).eval() | ||
| except: | ||
| raise RuntimeError("Invalid weights!!!") from None |
There was a problem hiding this comment.
Function ObjectDetection.loadModel refactored with the following changes:
- Add guard clause (
last-if-guard) - Replace f-string with no interpolated values with string (
remove-redundant-fstring)
| all_objects_dict = {} | ||
| for object_str in all_objects_str: | ||
| all_objects_dict[object_str] = False | ||
|
|
||
| all_objects_dict = {object_str: False for object_str in all_objects_str} |
There was a problem hiding this comment.
Function ObjectDetection.CustomObjects refactored with the following changes:
- Convert for loop into dictionary comprehension (
dict-comprehension)
|
|
||
| print(f" recall: {mr:0.6f} precision: {mp:0.6f} mAP@0.5: {map50:0.6f}, mAP@0.5-0.95: {map50_95:0.6f}" "\n") | ||
|
|
||
| if map50 > best_fitness: | ||
| best_fitness = map50 | ||
| recent_save_name = self.__model_type+f"_{self.__dataset_name}_mAP-{best_fitness:0.5f}_epoch-{epoch}.pt" | ||
| recent_save_name = f"{self.__model_type}_{self.__dataset_name}_mAP-{best_fitness:0.5f}_epoch-{epoch}.pt" |
There was a problem hiding this comment.
Function DetectionModelTrainer.trainModel refactored with the following changes:
- Use f-string instead of string concatenation [×2] (
use-fstring-for-concatenation)
| def setModelPath(self, model_path: str): | ||
| if os.path.isfile(model_path): | ||
| extension_check(model_path) | ||
| self.__model_path = model_path | ||
| self.__model_loaded = False | ||
| else: | ||
| if not os.path.isfile(model_path): | ||
| raise ValueError( | ||
| "invalid path, path not pointing to the weightfile." | ||
| ) from None | ||
| extension_check(model_path) | ||
| self.__model_path = model_path | ||
| self.__model_loaded = False | ||
| self.__model_path = model_path |
There was a problem hiding this comment.
Function CustomObjectDetection.setModelPath refactored with the following changes:
- Swap if/else branches (
swap-if-else-branches) - Remove unnecessary else after guard condition (
remove-unnecessary-else)
| allowed_exts = ["jpg", "jpeg", "png"] | ||
| fnames = [] | ||
| original_dims = [] | ||
| inputs = [] | ||
| original_imgs = [] | ||
| if type(input_image) == str: | ||
| if os.path.isfile(input_image): | ||
| if input_image.rsplit('.')[-1].lower() in allowed_exts: | ||
| img = cv2.imread(input_image) | ||
| else: | ||
| if not os.path.isfile(input_image): | ||
| raise ValueError(f"image path '{input_image}' is not found or a valid file") | ||
| allowed_exts = ["jpg", "jpeg", "png"] | ||
| if input_image.rsplit('.')[-1].lower() in allowed_exts: | ||
| img = cv2.imread(input_image) | ||
| elif type(input_image) == np.ndarray: | ||
| img = input_image | ||
| elif "PIL" in str(type(input_image)): | ||
| img = np.asarray(input_image) | ||
| else: | ||
| raise ValueError(f"Invalid image input format") | ||
| raise ValueError("Invalid image input format") | ||
|
|
||
| img_h, img_w, _ = img.shape | ||
|
|
||
| original_imgs.append(np.array(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)).astype(np.uint8)) | ||
| original_dims.append((img_w, img_h)) | ||
| original_imgs = [ | ||
| np.array(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)).astype(np.uint8) | ||
| ] | ||
| if type(input_image) == str: | ||
| fnames.append(os.path.basename(input_image)) | ||
| else: | ||
| fnames.append("") | ||
| inputs.append(prepare_image(img, (416, 416))) | ||
|
|
||
| if original_dims: | ||
| fnames.append("") | ||
| inputs = [prepare_image(img, (416, 416))] | ||
| if original_dims := [(img_w, img_h)]: |
There was a problem hiding this comment.
Function CustomObjectDetection.__load_image_yolo refactored with the following changes:
- Move assignments closer to their usage (
move-assign) - Move assignment closer to its usage within a block [×4] (
move-assign-in-block) - Swap if/else branches (
swap-if-else-branches) - Remove unnecessary else after guard condition (
remove-unnecessary-else) - Replace f-string with no interpolated values with string (
remove-redundant-fstring) - Merge append into list declaration [×3] (
merge-list-append) - Use named expression to simplify assignment and conditional (
use-named-expression)
| if isinstance(y2, torch.Tensor): | ||
| return torch.cat([y1, y2], 1) | ||
| return y1 | ||
| return torch.cat([y1, y2], 1) if isinstance(y2, torch.Tensor) else y1 |
There was a problem hiding this comment.
Function YoloV3Tiny.__route_layer refactored with the following changes:
- Lift code into else after jump in control flow (
reintroduce-else) - Replace if statement with if expression (
assign-if-exp)
| in_f, out_f, stride=stride, kernel_size=kernel_size, | ||
| padding= kernel_size//2, | ||
| bias=False if use_batch_norm else True | ||
| ) | ||
| in_f, | ||
| out_f, | ||
| stride=stride, | ||
| kernel_size=kernel_size, | ||
| padding=kernel_size // 2, | ||
| bias=not use_batch_norm, | ||
| ) |
There was a problem hiding this comment.
Function ConvLayer.__init__ refactored with the following changes:
- Simplify boolean if expression (
boolean-if-exp-identity) - Remove unnecessary casts to int, str, float or bool (
remove-unnecessary-cast)
| if isinstance(y2, torch.Tensor): | ||
| return torch.cat([y1, y2], 1) | ||
| return y1 | ||
| return torch.cat([y1, y2], 1) if isinstance(y2, torch.Tensor) else y1 |
There was a problem hiding this comment.
Function YoloV3.__route_layer refactored with the following changes:
- Lift code into else after jump in control flow (
reintroduce-else) - Replace if statement with if expression (
assign-if-exp)
| if(self.__modelType == "" ): | ||
| if (self.__modelType == "" ): | ||
| raise ValueError("You must set a valid model type before loading the model.") | ||
|
|
||
| elif(self.__modelType == "mobilenetv2"): | ||
| elif (self.__modelType == "mobilenetv2"): |
There was a problem hiding this comment.
Function ImageClassification.loadModel refactored with the following changes:
- Replace call to format with f-string [×4] (
use-fstring-for-formatting)
| classification_results = [] | ||
| classification_probabilities = [] | ||
| if (self.__modelLoaded == False): | ||
| raise ValueError("You must call the loadModel() function before making classification.") | ||
|
|
||
| else: | ||
| if (input_type == "file"): | ||
| try: | ||
| image_to_predict = tf.keras.preprocessing.image.load_img(image_input, target_size=(self.__input_image_size, self.__input_image_size)) | ||
| image_to_predict = tf.keras.preprocessing.image.img_to_array(image_to_predict, data_format="channels_last") | ||
| image_to_predict = np.expand_dims(image_to_predict, axis=0) | ||
| except: | ||
| raise ValueError("You have set a path to an invalid image file.") | ||
| elif (input_type == "array"): | ||
| try: | ||
| image_input = Image.fromarray(np.uint8(image_input)) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
| except: | ||
| raise ValueError("You have parsed in a wrong numpy array for the image") | ||
| elif (input_type == "stream"): | ||
| try: | ||
| image_input = Image.open(image_input) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
|
|
||
| except: | ||
| raise ValueError("You have parsed in a wrong stream for the image") | ||
|
|
||
| if (input_type == "file"): | ||
| try: | ||
| image_to_predict = tf.keras.preprocessing.image.load_img(image_input, target_size=(self.__input_image_size, self.__input_image_size)) | ||
| image_to_predict = tf.keras.preprocessing.image.img_to_array(image_to_predict, data_format="channels_last") | ||
| image_to_predict = np.expand_dims(image_to_predict, axis=0) | ||
| except: | ||
| raise ValueError("You have set a path to an invalid image file.") | ||
| elif (input_type == "array"): | ||
| try: | ||
| image_input = Image.fromarray(np.uint8(image_input)) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
| except: | ||
| raise ValueError("You have parsed in a wrong numpy array for the image") | ||
| elif (input_type == "stream"): | ||
| try: | ||
| image_input = Image.open(image_input) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
|
|
||
| except: | ||
| raise ValueError("You have parsed in a wrong stream for the image") | ||
|
|
||
| if (self.__modelType == "mobilenetv2"): | ||
| image_to_predict = tf.keras.applications.mobilenet_v2.preprocess_input(image_to_predict) | ||
| elif (self.__modelType == "densenet121"): | ||
| image_to_predict = tf.keras.applications.densenet.preprocess_input(image_to_predict) | ||
| elif (self.__modelType == "inceptionv3"): | ||
| image_to_predict = tf.keras.applications.inception_v3.preprocess_input(image_to_predict) | ||
|
|
||
| classification_results = [] | ||
| classification_probabilities = [] | ||
| try: | ||
| model = self.__model_collection[0] | ||
| prediction = model.predict(image_to_predict, steps=1) | ||
|
|
||
| if (self.__modelType == "mobilenetv2"): | ||
| image_to_predict = tf.keras.applications.mobilenet_v2.preprocess_input(image_to_predict) | ||
| elif (self.__modelType == "densenet121"): | ||
| image_to_predict = tf.keras.applications.densenet.preprocess_input(image_to_predict) | ||
| predictiondata = tf.keras.applications.mobilenet_v2.decode_predictions(prediction, top=int(result_count)) | ||
| elif (self.__modelType == "resnet50"): | ||
| predictiondata = tf.keras.applications.resnet50.decode_predictions(prediction, top=int(result_count)) | ||
| elif (self.__modelType == "inceptionv3"): | ||
| image_to_predict = tf.keras.applications.inception_v3.preprocess_input(image_to_predict) | ||
| predictiondata = tf.keras.applications.inception_v3.decode_predictions(prediction, top=int(result_count)) | ||
| elif (self.__modelType == "densenet121"): | ||
| predictiondata = tf.keras.applications.densenet.decode_predictions(prediction, top=int(result_count)) | ||
|
|
||
| try: | ||
| model = self.__model_collection[0] | ||
| prediction = model.predict(image_to_predict, steps=1) | ||
|
|
||
| if (self.__modelType == "mobilenetv2"): | ||
| predictiondata = tf.keras.applications.mobilenet_v2.decode_predictions(prediction, top=int(result_count)) | ||
| elif (self.__modelType == "resnet50"): | ||
| predictiondata = tf.keras.applications.resnet50.decode_predictions(prediction, top=int(result_count)) | ||
| elif (self.__modelType == "inceptionv3"): | ||
| predictiondata = tf.keras.applications.inception_v3.decode_predictions(prediction, top=int(result_count)) | ||
| elif (self.__modelType == "densenet121"): | ||
| predictiondata = tf.keras.applications.densenet.decode_predictions(prediction, top=int(result_count)) | ||
|
|
||
|
|
||
|
|
||
| for results in predictiondata: | ||
| for result in results: | ||
| classification_results.append(str(result[1])) | ||
| classification_probabilities.append(result[2] * 100) | ||
| except: | ||
| raise ValueError("An error occured! Try again.") | ||
| for results in predictiondata: | ||
| for result in results: | ||
| classification_results.append(str(result[1])) | ||
| classification_probabilities.append(result[2] * 100) | ||
| except: | ||
| raise ValueError("An error occured! Try again.") | ||
|
|
||
| return classification_results, classification_probabilities | ||
| return classification_results, classification_probabilities |
There was a problem hiding this comment.
Function ImageClassification.classifyImage refactored with the following changes:
- Move assignments closer to their usage (
move-assign) - Remove unnecessary else after guard condition (
remove-unnecessary-else)
| if(training_image_size < 100): | ||
| warnings.warn("The specified training_image_size {} is less than 100. Hence the training_image_size will default to 100.".format(training_image_size)) | ||
| if (training_image_size < 100): | ||
| warnings.warn( | ||
| f"The specified training_image_size {training_image_size} is less than 100. Hence the training_image_size will default to 100." | ||
| ) |
There was a problem hiding this comment.
Function ClassificationModelTrainer.trainModel refactored with the following changes:
- Convert for loop into dictionary comprehension (
dict-comprehension) - Move setting of default value for variable into
elsebranch (introduce-default-else) - Replace call to format with f-string [×2] (
use-fstring-for-formatting) - Simplify boolean if expression (
boolean-if-exp-identity) - Replace if statement with if expression (
assign-if-exp) - Remove unnecessary casts to int, str, float or bool (
remove-unnecessary-cast)
| self.__model_classes = dict() | ||
| self.__model_classes = {} |
There was a problem hiding this comment.
Function CustomImageClassification.__init__ refactored with the following changes:
- Replace
dict()with{}(dict-literal)
| if(classification_speed=="normal"): | ||
| self.__input_image_size = 224 | ||
| elif(classification_speed=="fast"): | ||
| if classification_speed == "fast": | ||
| self.__input_image_size = 160 | ||
| elif(classification_speed=="faster"): | ||
| elif classification_speed == "faster": | ||
| self.__input_image_size = 120 | ||
| elif (classification_speed == "fastest"): | ||
| elif classification_speed == "fastest": | ||
| self.__input_image_size = 100 | ||
|
|
||
| elif classification_speed == "normal": | ||
| self.__input_image_size = 224 | ||
| if (self.__modelLoaded == False): | ||
|
|
||
| image_input = tf.keras.layers.Input(shape=(self.__input_image_size, self.__input_image_size, 3)) | ||
|
|
||
| if(self.__modelType == "" ): | ||
| if (self.__modelType == "" ): | ||
| raise ValueError("You must set a valid model type before loading the model.") | ||
|
|
||
| elif(self.__modelType == "mobilenetv2"): | ||
| elif (self.__modelType == "mobilenetv2"): | ||
| model = tf.keras.applications.MobileNetV2(input_shape=(self.__input_image_size, self.__input_image_size, 3), weights=self.modelPath, classes = num_objects ) | ||
| self.__model_collection.append(model) | ||
| self.__modelLoaded = True | ||
| try: | ||
| None | ||
| except: | ||
| raise ValueError("An error occured. Ensure your model file is a MobileNetV2 Model and is located in the path {}".format(self.modelPath)) | ||
| raise ValueError( | ||
| f"An error occured. Ensure your model file is a MobileNetV2 Model and is located in the path {self.modelPath}" | ||
| ) | ||
|
|
||
| elif(self.__modelType == "resnet50"): | ||
| elif (self.__modelType == "resnet50"): | ||
| try: | ||
| model = tf.keras.applications.ResNet50(input_shape=(self.__input_image_size, self.__input_image_size, 3), weights=None, classes = num_objects ) | ||
| model.load_weights(self.modelPath) | ||
| self.__model_collection.append(model) | ||
| self.__modelLoaded = True | ||
| except: | ||
| raise ValueError("An error occured. Ensure your model file is a ResNet50 Model and is located in the path {}".format(self.modelPath)) | ||
| raise ValueError( | ||
| f"An error occured. Ensure your model file is a ResNet50 Model and is located in the path {self.modelPath}" | ||
| ) |
There was a problem hiding this comment.
Function CustomImageClassification.loadModel refactored with the following changes:
- Simplify conditional into switch-like form [×5] (
switch) - Replace call to format with f-string [×4] (
use-fstring-for-formatting)
| classification_results = [] | ||
| classification_probabilities = [] | ||
| if (self.__modelLoaded == False): | ||
| raise ValueError("You must call the loadModel() function before making classification.") | ||
|
|
||
| else: | ||
| if (input_type == "file"): | ||
| try: | ||
| image_to_predict = tf.keras.preprocessing.image.load_img(image_input, target_size=(self.__input_image_size, self.__input_image_size)) | ||
| image_to_predict = tf.keras.preprocessing.image.img_to_array(image_to_predict, data_format="channels_last") | ||
| image_to_predict = np.expand_dims(image_to_predict, axis=0) | ||
| except: | ||
| raise ValueError("You have set a path to an invalid image file.") | ||
| elif (input_type == "array"): | ||
| try: | ||
| image_input = Image.fromarray(np.uint8(image_input)) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
| except: | ||
| raise ValueError("You have parsed in a wrong numpy array for the image") | ||
| elif (input_type == "stream"): | ||
| try: | ||
| image_input = Image.open(image_input) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
|
|
||
| except: | ||
| raise ValueError("You have parsed in a wrong stream for the image") | ||
|
|
||
| if (self.__modelType == "mobilenetv2"): | ||
| image_to_predict = tf.keras.applications.mobilenet_v2.preprocess_input(image_to_predict) | ||
| elif (self.__modelType == "full"): | ||
| image_to_predict = tf.keras.applications.mobilenet_v2.preprocess_input(image_to_predict) | ||
| elif (self.__modelType == "inceptionv3"): | ||
| image_to_predict = tf.keras.applications.inception_v3.preprocess_input(image_to_predict) | ||
| elif (self.__modelType == "densenet121"): | ||
| image_to_predict = tf.keras.applications.densenet.preprocess_input(image_to_predict) | ||
| if (input_type == "file"): | ||
| try: | ||
| image_to_predict = tf.keras.preprocessing.image.load_img(image_input, target_size=(self.__input_image_size, self.__input_image_size)) | ||
| image_to_predict = tf.keras.preprocessing.image.img_to_array(image_to_predict, data_format="channels_last") | ||
| image_to_predict = np.expand_dims(image_to_predict, axis=0) | ||
| except: | ||
| raise ValueError("You have set a path to an invalid image file.") | ||
| elif (input_type == "array"): | ||
| try: | ||
| image_input = Image.fromarray(np.uint8(image_input)) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
| except: | ||
| raise ValueError("You have parsed in a wrong numpy array for the image") | ||
| elif (input_type == "stream"): | ||
| try: | ||
| model = self.__model_collection[0] | ||
| prediction = model.predict(image_to_predict, steps=1) | ||
|
|
||
| predictiondata = [] | ||
| for pred in prediction: | ||
| top_indices = pred.argsort()[-result_count:][::-1] | ||
| for i in top_indices: | ||
| each_result = [] | ||
| each_result.append(self.__model_classes[str(i)]) | ||
| each_result.append(pred[i]) | ||
| predictiondata.append(each_result) | ||
|
|
||
| for result in predictiondata: | ||
| classification_results.append(str(result[0])) | ||
| classification_probabilities.append(result[1] * 100) | ||
|
|
||
| image_input = Image.open(image_input) | ||
| image_input = image_input.resize((self.__input_image_size, self.__input_image_size)) | ||
| image_input = np.expand_dims(image_input, axis=0) | ||
| image_to_predict = image_input.copy() | ||
| image_to_predict = np.asarray(image_to_predict, dtype=np.float64) | ||
|
|
||
| except: | ||
| raise ValueError("Error. Ensure your input image is valid") | ||
| raise ValueError("You have parsed in a wrong stream for the image") | ||
|
|
||
| if self.__modelType in ["mobilenetv2", "full"]: | ||
| image_to_predict = tf.keras.applications.mobilenet_v2.preprocess_input(image_to_predict) | ||
| elif self.__modelType == "inceptionv3": | ||
| image_to_predict = tf.keras.applications.inception_v3.preprocess_input(image_to_predict) | ||
| elif self.__modelType == "densenet121": | ||
| image_to_predict = tf.keras.applications.densenet.preprocess_input(image_to_predict) | ||
| classification_results = [] | ||
| classification_probabilities = [] | ||
| try: | ||
| model = self.__model_collection[0] | ||
| prediction = model.predict(image_to_predict, steps=1) | ||
|
|
||
| predictiondata = [] | ||
| for pred in prediction: | ||
| top_indices = pred.argsort()[-result_count:][::-1] | ||
| for i in top_indices: | ||
| each_result = [self.__model_classes[str(i)], pred[i]] | ||
| predictiondata.append(each_result) | ||
|
|
||
| for result in predictiondata: | ||
| classification_results.append(str(result[0])) | ||
| classification_probabilities.append(result[1] * 100) | ||
|
|
||
| except: | ||
| raise ValueError("Error. Ensure your input image is valid") | ||
|
|
||
| return classification_results, classification_probabilities | ||
| return classification_results, classification_probabilities |
There was a problem hiding this comment.
Function CustomImageClassification.classifyImage refactored with the following changes:
- Move assignments closer to their usage (
move-assign) - Remove unnecessary else after guard condition (
remove-unnecessary-else) - Merge duplicate blocks in conditional (
merge-duplicate-blocks) - Merge append into list declaration [×2] (
merge-list-append) - Remove redundant conditional [×3] (
remove-redundant-if) - Replace multiple comparisons of same variable with
inoperator (merge-comparisons)
| if (self.__modelType == "retinanet"): | ||
| if (detection_speed == "normal"): | ||
| self.__input_image_min = 800 | ||
| self.__input_image_max = 1333 | ||
| elif (detection_speed == "fast"): | ||
| if self.__modelType == "retinanet": | ||
| if detection_speed == "fast": | ||
| self.__input_image_min = 400 | ||
| self.__input_image_max = 700 | ||
| elif (detection_speed == "faster"): | ||
| elif detection_speed == "faster": | ||
| self.__input_image_min = 300 | ||
| self.__input_image_max = 500 | ||
| elif (detection_speed == "fastest"): | ||
| elif detection_speed == "fastest": | ||
| self.__input_image_min = 200 | ||
| self.__input_image_max = 350 | ||
| elif (detection_speed == "flash"): | ||
| elif detection_speed == "flash": | ||
| self.__input_image_min = 100 | ||
| self.__input_image_max = 250 | ||
| elif (self.__modelType == "yolov3"): | ||
| if (detection_speed == "normal"): | ||
| elif detection_speed == "normal": | ||
| self.__input_image_min = 800 | ||
| self.__input_image_max = 1333 | ||
| elif self.__modelType == "tinyyolov3": | ||
| if detection_speed == "fast": | ||
| self.__yolo_model_image_size = (576, 576) | ||
| elif detection_speed == "faster": | ||
| self.__yolo_model_image_size = (416, 416) | ||
| elif (detection_speed == "fast"): | ||
| elif detection_speed == "fastest": | ||
| self.__yolo_model_image_size = (320, 320) | ||
| elif detection_speed == "flash": | ||
| self.__yolo_model_image_size = (272, 272) | ||
|
|
||
| elif detection_speed == "normal": | ||
| self.__yolo_model_image_size = (832, 832) | ||
| elif self.__modelType == "yolov3": | ||
| if detection_speed == "fast": | ||
| self.__yolo_model_image_size = (320, 320) | ||
| elif (detection_speed == "faster"): | ||
| elif detection_speed == "faster": | ||
| self.__yolo_model_image_size = (208, 208) | ||
| elif (detection_speed == "fastest"): | ||
| elif detection_speed == "fastest": | ||
| self.__yolo_model_image_size = (128, 128) | ||
| elif (detection_speed == "flash"): | ||
| elif detection_speed == "flash": | ||
| self.__yolo_model_image_size = (96, 96) | ||
|
|
||
| elif (self.__modelType == "tinyyolov3"): | ||
| if (detection_speed == "normal"): | ||
| self.__yolo_model_image_size = (832, 832) | ||
| elif (detection_speed == "fast"): | ||
| self.__yolo_model_image_size = (576, 576) | ||
| elif (detection_speed == "faster"): | ||
| elif detection_speed == "normal": | ||
| self.__yolo_model_image_size = (416, 416) | ||
| elif (detection_speed == "fastest"): | ||
| self.__yolo_model_image_size = (320, 320) | ||
| elif (detection_speed == "flash"): | ||
| self.__yolo_model_image_size = (272, 272) | ||
|
|
||
| if (self.__modelLoaded == False): | ||
| if (self.__modelType == ""): | ||
| if (self.__modelType == ""): | ||
| if (self.__modelLoaded == False): | ||
| raise ValueError("You must set a valid model type before loading the model.") | ||
| elif (self.__modelType == "retinanet"): | ||
| elif (self.__modelType == "retinanet"): | ||
| if (self.__modelLoaded == False): | ||
| model = retinanet_models.load_model(self.modelPath, backbone_name='resnet50') | ||
| self.__model_collection.append(model) | ||
| self.__modelLoaded = True | ||
| elif (self.__modelType == "yolov3" or self.__modelType == "tinyyolov3"): | ||
| elif self.__modelType in ["yolov3", "tinyyolov3"]: | ||
| if (self.__modelLoaded == False): | ||
|
|
||
| input_image = Input(shape=(None, None, 3)) | ||
|
|
||
| if self.__modelType == "yolov3": | ||
| model = yolov3_main(input_image, len(self.__yolo_anchors), | ||
| len(self.numbers_to_names.keys())) | ||
| else: | ||
| model = tiny_yolov3_main(input_image, 3, | ||
| len(self.numbers_to_names.keys())) | ||
|
|
||
| model = ( | ||
| yolov3_main( | ||
| input_image, | ||
| len(self.__yolo_anchors), | ||
| len(self.numbers_to_names.keys()), | ||
| ) | ||
| if self.__modelType == "yolov3" | ||
| else tiny_yolov3_main( | ||
| input_image, 3, len(self.numbers_to_names.keys()) | ||
| ) | ||
| ) | ||
| model.load_weights(self.modelPath) | ||
There was a problem hiding this comment.
Function ObjectDetection.loadModel refactored with the following changes:
- Simplify conditional into switch-like form [×9] (
switch) - Swap positions of nested conditionals (
swap-nested-ifs) - Replace multiple comparisons of same variable with
inoperator (merge-comparisons) - Replace if statement with if expression (
assign-if-exp)
|
|
||
| for i in range(len(labels)): | ||
| if box.classes[i] > obj_thresh: | ||
| if label_str != '': label_str += ', ' | ||
| label_str += (labels[i] + ' ' + str(round(box.get_score()*100, 2)) + '%') | ||
| label_str += f'{labels[i]} {str(round(box.get_score() * 100, 2))}%' | ||
| label = i | ||
| if not quiet: print(label_str) | ||
|
|
There was a problem hiding this comment.
Function draw_boxes refactored with the following changes:
- Use f-string instead of string concatenation [×3] (
use-fstring-for-concatenation)
| else: | ||
| print('Label {} has no color, returning default.'.format(label)) | ||
| return (0, 255, 0) | ||
| print(f'Label {label} has no color, returning default.') | ||
| return (0, 255, 0) |
There was a problem hiding this comment.
Function get_color refactored with the following changes:
- Remove unnecessary else after guard condition (
remove-unnecessary-else) - Replace call to format with f-string (
use-fstring-for-formatting)
| return max_v | ||
|
|
||
| return value | ||
| return min_v if value < min_v else min(value, max_v) |
There was a problem hiding this comment.
Function _constrain refactored with the following changes:
- Lift code into else after jump in control flow [×2] (
reintroduce-else) - Replace if statement with if expression [×2] (
assign-if-exp) - Replace comparison with min/max call (
min-max-identity)
| if flip == 1: | ||
| return cv2.flip(image, 1) | ||
| return image | ||
| return cv2.flip(image, 1) if flip == 1 else image |
There was a problem hiding this comment.
Function random_flip refactored with the following changes:
- Lift code into else after jump in control flow (
reintroduce-else) - Replace if statement with if expression (
assign-if-exp)
| size = batch_size - step * i | ||
| else: | ||
| size = step | ||
| size = batch_size - step * i if i == num_gpus - 1 else step |
There was a problem hiding this comment.
Function multi_gpu_model refactored with the following changes:
- Replace if statement with if expression (
assign-if-exp)
Sourcery Code Quality Report✅ Merging this PR will increase code quality in the affected files by 0.36%.
Here are some functions in these files that still need a tune-up:
Legend and ExplanationThe emojis denote the absolute quality of the code:
The 👍 and 👎 indicate whether the quality has improved or gotten worse with this pull request. Please see our documentation here for details on how these metrics are calculated. We are actively working on this report - lots more documentation and extra metrics to come! Help us improve this quality report! |
Branch
masterrefactored by Sourcery.If you're happy with these changes, merge this Pull Request using the Squash and merge strategy.
See our documentation here.
Run Sourcery locally
Reduce the feedback loop during development by using the Sourcery editor plugin:
Review changes via command line
To manually merge these changes, make sure you're on the
masterbranch, then run:Help us improve this pull request!