Skip to content

Sourcery refactored master branch#1

Open
sourcery-ai[bot] wants to merge 1 commit into
masterfrom
sourcery/master
Open

Sourcery refactored master branch#1
sourcery-ai[bot] wants to merge 1 commit into
masterfrom
sourcery/master

Conversation

@sourcery-ai

@sourcery-ai sourcery-ai Bot commented Mar 1, 2023

Copy link
Copy Markdown

Branch master refactored 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 master branch, then run:

git fetch origin sourcery/master
git merge --ff-only FETCH_HEAD
git reset HEAD^

Help us improve this pull request!

@sourcery-ai sourcery-ai Bot requested a review from thanx228 March 1, 2023 02:48

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to GitHub API limits, only the first 60 comments can be shown.

Comment on lines -19 to +20
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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 19-23 refactored with the following changes:

Comment on lines -17 to +18
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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 17-21 refactored with the following changes:

Comment on lines -21 to +22
counter = 0

for eachItem in output_count:
counter += 1
labels.append(eachItem + " = " + str(output_count[eachItem]))
labels.append(f"{eachItem} = {str(output_count[eachItem])}")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function forFrame refactored with the following changes:

Comment on lines -21 to +22
counter = 0

for eachItem in average_count:
counter += 1
labels.append(eachItem + " = " + str(average_count[eachItem]))
labels.append(f"{eachItem} = {str(average_count[eachItem])}")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function forSecond refactored with the following changes:

Comment on lines -85 to +88
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))

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ImageClassification.__load_image refactored with the following changes:

Comment on lines -466 to +509
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.")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CustomImageClassification.loadModel refactored with the following changes:

probabilities = torch.softmax(output, dim=1)
topN_prob, topN_catid = torch.topk(probabilities, result_count)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CustomImageClassification.classifyImage refactored with the following changes:

Comment on lines -81 to +105
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)]:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ObjectDetection.__load_image_yolo refactored with the following changes:

Comment on lines -127 to +130
)
)
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"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ObjectDetection.__save_temp_img refactored with the following changes:

Comment on lines -143 to +160
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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ObjectDetection.__load_image_retinanet refactored with the following changes:

Comment on lines -231 to +259
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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ObjectDetection.loadModel refactored with the following changes:

Comment on lines -280 to +278
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}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ObjectDetection.CustomObjects refactored with the following changes:

Comment on lines -296 to +301

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"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function DetectionModelTrainer.trainModel refactored with the following changes:

Comment on lines 354 to 364
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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CustomObjectDetection.setModelPath refactored with the following changes:

Comment on lines -380 to +406
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)]:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CustomObjectDetection.__load_image_yolo refactored with the following changes:

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function YoloV3Tiny.__route_layer refactored with the following changes:

Comment thread imageai/yolov3/yolov3.py
Comment on lines -82 to +88
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,
)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ConvLayer.__init__ refactored with the following changes:

Comment thread imageai/yolov3/yolov3.py
Comment on lines -247 to +250
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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function YoloV3.__route_layer refactored with the following changes:

Comment on lines -105 to +108
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"):

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ImageClassification.loadModel refactored with the following changes:

Comment on lines -165 to +234
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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ImageClassification.classifyImage refactored with the following changes:

Comment on lines -183 to +186
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."
)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ClassificationModelTrainer.trainModel refactored with the following changes:

Comment on lines -422 to +418
self.__model_classes = dict()
self.__model_classes = {}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CustomImageClassification.__init__ refactored with the following changes:

Comment on lines -492 to +524
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}"
)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CustomImageClassification.loadModel refactored with the following changes:

Comment on lines -599 to +659
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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function CustomImageClassification.classifyImage refactored with the following changes:

Comment on lines -137 to -196
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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ObjectDetection.loadModel refactored with the following changes:

Comment on lines -66 to +69

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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function draw_boxes refactored with the following changes:

Comment on lines -11 to +12
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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function get_color refactored with the following changes:

return max_v

return value
return min_v if value < min_v else min(value, max_v)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function _constrain refactored with the following changes:

Comment on lines -23 to +17
if flip == 1:
return cv2.flip(image, 1)
return image
return cv2.flip(image, 1) if flip == 1 else image

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function random_flip refactored with the following changes:

size = batch_size - step * i
else:
size = step
size = batch_size - step * i if i == num_gpus - 1 else step

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function multi_gpu_model refactored with the following changes:

@sourcery-ai

sourcery-ai Bot commented Mar 1, 2023

Copy link
Copy Markdown
Author

Sourcery Code Quality Report

✅  Merging this PR will increase code quality in the affected files by 0.36%.

Quality metrics Before After Change
Complexity 28.33 😞 28.06 😞 -0.27 👍
Method Length 101.59 🙂 101.24 🙂 -0.35 👍
Working memory 13.14 😞 13.14 😞 0.00
Quality 49.17% 😞 49.53% 😞 0.36% 👍
Other metrics Before After Change
Lines 14661 14700 39
Changed files Quality Before Quality After Quality Change
examples/custom_detection_from_array_extract_objects_array.py 70.63% 🙂 70.38% 🙂 -0.25% 👎
examples/custom_detection_from_file_extract_objects_array.py 74.36% 🙂 74.10% 🙂 -0.26% 👎
examples/video_analysis_per_frame.py 65.96% 🙂 66.62% 🙂 0.66% 👍
examples/video_analysis_per_second.py 65.75% 🙂 66.40% 🙂 0.65% 👍
imageai/Classification/__init__.py 66.99% 🙂 67.65% 🙂 0.66% 👍
imageai/Classification/Custom/__init__.py 50.71% 🙂 51.63% 🙂 0.92% 👍
imageai/Detection/__init__.py 26.05% 😞 26.74% 😞 0.69% 👍
imageai/Detection/Custom/__init__.py 27.95% 😞 28.38% 😞 0.43% 👍
imageai/Detection/Custom/yolo/compute_loss.py 30.66% 😞 31.69% 😞 1.03% 👍
imageai/Detection/Custom/yolo/dataset.py 68.75% 🙂 68.74% 🙂 -0.01% 👎
imageai/Detection/Custom/yolo/metric.py 46.26% 😞 50.35% 🙂 4.09% 👍
imageai/densenet121/__init__.py 59.60% 🙂 59.76% 🙂 0.16% 👍
imageai/retinanet/utils.py 30.39% 😞 28.67% 😞 -1.72% 👎
imageai/yolov3/tiny_yolov3.py 68.15% 🙂 67.12% 🙂 -1.03% 👎
imageai/yolov3/yolov3.py 60.68% 🙂 60.41% 🙂 -0.27% 👎
imageai_tf_deprecated/Classification/__init__.py 40.21% 😞 43.83% 😞 3.62% 👍
imageai_tf_deprecated/Classification/Custom/__init__.py 34.83% 😞 37.84% 😞 3.01% 👍
imageai_tf_deprecated/Detection/__init__.py 21.81% ⛔ 21.68% ⛔ -0.13% 👎
imageai_tf_deprecated/Detection/Custom/__init__.py 41.67% 😞 41.76% 😞 0.09% 👍
imageai_tf_deprecated/Detection/Custom/callbacks.py 44.15% 😞 47.77% 😞 3.62% 👍
imageai_tf_deprecated/Detection/Custom/gen_anchors.py 55.16% 🙂 55.76% 🙂 0.60% 👍
imageai_tf_deprecated/Detection/Custom/generator.py 44.29% 😞 44.68% 😞 0.39% 👍
imageai_tf_deprecated/Detection/Custom/voc.py 6.16% ⛔ 6.19% ⛔ 0.03% 👍
imageai_tf_deprecated/Detection/Custom/utils/bbox.py 63.93% 🙂 63.13% 🙂 -0.80% 👎
imageai_tf_deprecated/Detection/Custom/utils/colors.py 88.12% ⭐ 91.17% ⭐ 3.05% 👍
imageai_tf_deprecated/Detection/Custom/utils/image.py 63.87% 🙂 60.19% 🙂 -3.68% 👎
imageai_tf_deprecated/Detection/Custom/utils/multi_gpu_model.py 36.33% 😞 37.73% 😞 1.40% 👍
imageai_tf_deprecated/Detection/Custom/utils/utils.py 46.34% 😞 46.18% 😞 -0.16% 👎
imageai_tf_deprecated/Detection/YOLO/utils.py 56.82% 🙂 57.76% 🙂 0.94% 👍
imageai_tf_deprecated/Detection/YOLO/yolov3.py 50.71% 🙂 50.82% 🙂 0.11% 👍
imageai_tf_deprecated/Detection/keras_retinanet/initializers.py 91.99% ⭐ 94.57% ⭐ 2.58% 👍
imageai_tf_deprecated/Detection/keras_retinanet/backend/backend.py 63.21% 🙂 63.44% 🙂 0.23% 👍
imageai_tf_deprecated/Detection/keras_retinanet/bin/debug.py 47.21% 😞 47.36% 😞 0.15% 👍
imageai_tf_deprecated/Detection/keras_retinanet/bin/evaluate.py 51.11% 🙂 51.13% 🙂 0.02% 👍
imageai_tf_deprecated/Detection/keras_retinanet/bin/train.py 46.80% 😞 46.64% 😞 -0.16% 👎
imageai_tf_deprecated/Detection/keras_retinanet/callbacks/coco.py 64.22% 🙂 62.97% 🙂 -1.25% 👎
imageai_tf_deprecated/Detection/keras_retinanet/callbacks/eval.py 43.55% 😞 43.51% 😞 -0.04% 👎
imageai_tf_deprecated/Detection/keras_retinanet/layers/_misc.py 69.39% 🙂 70.07% 🙂 0.68% 👍
imageai_tf_deprecated/Detection/keras_retinanet/models/__init__.py 86.64% ⭐ 86.64% ⭐ 0.00%
imageai_tf_deprecated/Detection/keras_retinanet/models/densenet.py 74.67% 🙂 73.12% 🙂 -1.55% 👎
imageai_tf_deprecated/Detection/keras_retinanet/models/effnet.py 66.77% 🙂 66.50% 🙂 -0.27% 👎
imageai_tf_deprecated/Detection/keras_retinanet/models/mobilenet.py 72.12% 🙂 71.83% 🙂 -0.29% 👎
imageai_tf_deprecated/Detection/keras_retinanet/models/resnet.py 73.67% 🙂 73.67% 🙂 0.00%
imageai_tf_deprecated/Detection/keras_retinanet/models/retinanet.py 50.69% 🙂 50.81% 🙂 0.12% 👍
imageai_tf_deprecated/Detection/keras_retinanet/models/senet.py 66.45% 🙂 67.16% 🙂 0.71% 👍
imageai_tf_deprecated/Detection/keras_retinanet/models/vgg.py 72.25% 🙂 71.90% 🙂 -0.35% 👎
imageai_tf_deprecated/Detection/keras_retinanet/preprocessing/coco.py 83.03% ⭐ 83.65% ⭐ 0.62% 👍
imageai_tf_deprecated/Detection/keras_retinanet/preprocessing/csv_generator.py 69.49% 🙂 67.99% 🙂 -1.50% 👎
imageai_tf_deprecated/Detection/keras_retinanet/preprocessing/generator.py 78.78% ⭐ 78.56% ⭐ -0.22% 👎
imageai_tf_deprecated/Detection/keras_retinanet/preprocessing/kitti.py 72.31% 🙂 72.45% 🙂 0.14% 👍
imageai_tf_deprecated/Detection/keras_retinanet/preprocessing/open_images.py 38.54% 😞 39.00% 😞 0.46% 👍
imageai_tf_deprecated/Detection/keras_retinanet/preprocessing/pascal_voc.py 74.55% 🙂 74.04% 🙂 -0.51% 👎
imageai_tf_deprecated/Detection/keras_retinanet/utils/anchors.py 61.80% 🙂 61.81% 🙂 0.01% 👍
imageai_tf_deprecated/Detection/keras_retinanet/utils/coco_eval.py 43.31% 😞 43.43% 😞 0.12% 👍
imageai_tf_deprecated/Detection/keras_retinanet/utils/colors.py 87.84% ⭐ 90.89% ⭐ 3.05% 👍
imageai_tf_deprecated/Detection/keras_retinanet/utils/config.py 82.12% ⭐ 81.62% ⭐ -0.50% 👎
imageai_tf_deprecated/Detection/keras_retinanet/utils/eval.py 37.29% 😞 36.90% 😞 -0.39% 👎
imageai_tf_deprecated/Detection/keras_retinanet/utils/gpu.py 68.94% 🙂 62.05% 🙂 -6.89% 👎
imageai_tf_deprecated/Detection/keras_retinanet/utils/image.py 83.80% ⭐ 83.85% ⭐ 0.05% 👍
imageai_tf_deprecated/Detection/keras_retinanet/utils/tf_version.py 92.43% ⭐ 91.04% ⭐ -1.39% 👎
imageai_tf_deprecated/Detection/keras_retinanet/utils/visualization.py 68.35% 🙂 69.30% 🙂 0.95% 👍
imageai_tf_deprecated/Prediction/Custom/custom_utils.py 80.46% ⭐ 82.34% ⭐ 1.88% 👍
test/test_custom_detection_training.py 74.79% 🙂 77.03% ⭐ 2.24% 👍
test/test_custom_object_detection.py 38.09% 😞 39.91% 😞 1.82% 👍
test/test_custom_video_detection.py 79.82% ⭐ 79.86% ⭐ 0.04% 👍
test/test_object_detection.py 44.61% 😞 46.34% 😞 1.73% 👍
test/test_video_object_detection.py 81.71% ⭐ 81.65% ⭐ -0.06% 👎

Here are some functions in these files that still need a tune-up:

File Function Complexity Length Working Memory Quality Recommendation
imageai_tf_deprecated/Detection/__init__.py VideoObjectDetection.detectObjectsFromVideo 209 ⛔ 719 ⛔ 35 ⛔ 0.45% ⛔ Refactor to reduce nesting. Try splitting into smaller methods. Extract out complex expressions
imageai/Detection/__init__.py VideoObjectDetection.detectObjectsFromVideo 209 ⛔ 711 ⛔ 35 ⛔ 0.46% ⛔ Refactor to reduce nesting. Try splitting into smaller methods. Extract out complex expressions
imageai/Detection/Custom/__init__.py CustomVideoObjectDetection.detectObjectsFromVideo 235 ⛔ 712 ⛔ 34 ⛔ 0.52% ⛔ Refactor to reduce nesting. Try splitting into smaller methods. Extract out complex expressions
imageai_tf_deprecated/Detection/Custom/__init__.py CustomVideoObjectDetection.detectObjectsFromVideo 202 ⛔ 687 ⛔ 32 ⛔ 0.71% ⛔ Refactor to reduce nesting. Try splitting into smaller methods. Extract out complex expressions
imageai/Detection/__init__.py ObjectDetection.detectObjectsFromImage 160 ⛔ 1139 ⛔ 28 ⛔ 1.20% ⛔ Refactor to reduce nesting. Try splitting into smaller methods. Extract out complex expressions

Legend and Explanation

The emojis denote the absolute quality of the code:

  • ⭐ excellent
  • 🙂 good
  • 😞 poor
  • ⛔ very poor

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants