Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/lapix-ufsc/lapixdl into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrevmatias committed Dec 6, 2021
2 parents 60d71a8 + b63fbae commit 6e54802
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 40 deletions.
43 changes: 25 additions & 18 deletions examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
Module examples
Requires:
opencv-python, numpy
numpy
"""
import cv2
from typing import Tuple

import numpy as np
from matplotlib.colors import ListedColormap

Expand Down Expand Up @@ -35,29 +36,29 @@ def evaluate_segmentation_example():
# Creating fake data
# Creates a rectangle of 1s in a 0s array
gt_bbox_1 = BBox(10, 10, 10, 10, 1)
mask_bin_GT_1 = cv2.rectangle(np.zeros(mask_shape, np.int),
gt_bbox_1.upper_left_point,
gt_bbox_1.bottom_right_point,
1, -1)
mask_bin_GT_1 = draw_rectangle(np.zeros(mask_shape, np.int),
gt_bbox_1.upper_left_point,
gt_bbox_1.bottom_right_point,
1)

pred_bbox_1 = BBox(10, 10, 10, 10, 1)
mask_bin_pred_1 = cv2.rectangle(np.zeros(mask_shape, np.int),
pred_bbox_1.upper_left_point,
pred_bbox_1.bottom_right_point,
1, -1)
mask_bin_pred_1 = draw_rectangle(np.zeros(mask_shape, np.int),
pred_bbox_1.upper_left_point,
pred_bbox_1.bottom_right_point,
1)

# Creates a rectangle of 2s in a 0s array
gt_bbox_2 = BBox(110, 110, 320, 280, 2)
mask_bin_GT_2 = cv2.rectangle(np.zeros(mask_shape, np.int),
gt_bbox_2.upper_left_point,
gt_bbox_2.bottom_right_point,
2, -1)
mask_bin_GT_2 = draw_rectangle(np.zeros(mask_shape, np.int),
gt_bbox_2.upper_left_point,
gt_bbox_2.bottom_right_point,
2)

pred_bbox_2 = BBox(70, 50, 240, 220, 2)
mask_bin_pred_2 = cv2.rectangle(np.zeros(mask_shape, np.int),
pred_bbox_2.upper_left_point,
pred_bbox_2.bottom_right_point,
2, -1)
mask_bin_pred_2 = draw_rectangle(np.zeros(mask_shape, np.int),
pred_bbox_2.upper_left_point,
pred_bbox_2.bottom_right_point,
2)

# Merging masks
mask_GT = np.maximum(mask_bin_GT_1, mask_bin_GT_2)
Expand Down Expand Up @@ -242,4 +243,10 @@ def draw_bboxes(mask_shape, bboxes):
return mask


def draw_rectangle(img: np.ndarray, pt1: Tuple[int, int], pt2: Tuple[int, int], fill: int):
cp = img.copy()
cp[slice(pt1[0], pt2[0] + 1), slice(pt1[1], pt2[1] + 1)] = fill
return cp


main()
42 changes: 26 additions & 16 deletions lapixdl/evaluation/evaluate.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from typing import List, Iterable
import warnings
import itertools

import numpy as np

from typing import List, Iterable
from tqdm import tqdm
import warnings

from .model import *

Expand All @@ -28,17 +30,25 @@ def evaluate_segmentation(gt_masks: Iterable[Mask],
SegmentationMetrics: Pixel-based classification and segmentation metrics.
"""

confusion_matrix = np.zeros((len(classes), len(classes)), np.int)
classes_count = len(classes)
zeros_matrix = np.zeros((classes_count, classes_count), int)
confusion_matrix = zeros_matrix.copy()
classes_count_range = range(classes_count)

for (curr_gt_mask, curr_pred_mask) in tqdm(zip(gt_masks, pred_masks), unit=' masks'):
flat_gt = __flat_mask(curr_gt_mask)
flat_pred = __flat_mask(curr_pred_mask)
if len(flat_gt) != len(flat_pred):
warnings.warn(
f"The GT mask and Pred mask should have the same shape. GT length: {len(flat_gt)}. Pred length: {len(flat_pred)}.")

for (curr_pred, curr_gt) in zip(flat_pred, flat_gt):
confusion_matrix[curr_pred, curr_gt] += 1
curr_gt_mask = np.array(curr_gt_mask)
curr_pred_mask = np.array(curr_pred_mask)
if curr_gt_mask.shape != curr_pred_mask.shape:
warnings.warn(f"The GT mask and Pred mask should have the same shape. GT shape: {curr_gt_mask.shape}.Pred shape: {curr_pred_mask.shape}.")

curr_confusion_matrix = zeros_matrix.copy()
for i, j in itertools.product(classes_count_range, classes_count_range):
curr_confusion_matrix[j, i] = np.sum((curr_pred_mask==j)*(curr_gt_mask==i))

# ~1% slower alternative:
# curr_confusion_matrix = np.array([[np.sum((msk==i)*(pred == j)) for i in range(classes_count)] for j in range(classes_count)])

confusion_matrix += curr_confusion_matrix

metrics = SegmentationMetrics(classes, confusion_matrix)

Expand All @@ -65,7 +75,7 @@ def evaluate_classification(gt_classifications: Iterable[Classification],
ClassificationMetrics: Classification metrics.
"""

confusion_matrix = np.zeros((len(classes), len(classes)), np.int)
confusion_matrix = np.zeros((len(classes), len(classes)), int)

for (curr_gt_classification, curr_pred_classification) in tqdm(zip(gt_classifications, pred_classifications), unit=' samples'):
confusion_matrix[curr_pred_classification.cls,
Expand Down Expand Up @@ -103,7 +113,7 @@ def evaluate_detection(gt_bboxes: Iterable[List[BBox]],
classes_count = len(classes)

cls_ious_sum = np.zeros(classes_count)
confusion_matrix = np.zeros((classes_count + 1, classes_count + 1), np.int)
confusion_matrix = np.zeros((classes_count + 1, classes_count + 1), int)
undetected_idx = classes_count
# Tracks detection scores to calculate the Precision x Recall curve and the Average Precision metric
predictions_by_class: List[List[PredictionResult]] = [
Expand Down Expand Up @@ -181,7 +191,7 @@ def calculate_pairwise_bbox_ious(gt_bboxes: List[BBox],
List[List[float]]: [gt x pred] matrix of pairwise IoUs of GT and predicted bboxes
"""

ious = np.zeros((len(gt_bboxes), len(pred_bboxes)), np.float)
ious = np.zeros((len(gt_bboxes), len(pred_bboxes)), float)

for i, gt_bbox in enumerate(gt_bboxes):
for j, pred_bbox in enumerate(pred_bboxes):
Expand Down Expand Up @@ -222,7 +232,7 @@ def calculate_iou_by_class(gt_bboxes: List[BBox],
List[float]: IoUs of an image indexed by class
"""

ious = np.zeros(classes_count, np.float)
ious = np.zeros(classes_count, float)

for i in range(classes_count):
ious[i] = __calculate_binary_iou([gt_bbox for gt_bbox in gt_bboxes if gt_bbox.cls == i],
Expand Down Expand Up @@ -257,7 +267,7 @@ def __calculate_binary_iou(gt_bboxes: List[BBox],


def __draw_bboxes(mask_shape: Tuple[int, int], bboxes: List[BBox]) -> List[List[int]]:
mask = np.zeros(mask_shape, np.int)
mask = np.zeros(mask_shape, int)

for bbox in bboxes:
mask[
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

install_requires=['numpy', 'tqdm', 'seaborn', 'pandas', 'matplotlib'],
setup_requires=['pytest-runner'],
tests_require=['pytest', 'cv2'],
tests_require=['pytest'],
test_suite='tests',

classifiers=[
Expand Down
15 changes: 10 additions & 5 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from typing import Tuple

import cv2
import numpy as np

from lapixdl.evaluation.model import BBox
Expand All @@ -10,7 +9,13 @@ def bin_mask_from_bb(mask_shape: Tuple[int, int], bbox: BBox):
'''
Draws a mask from a bounding box
'''
return cv2.rectangle(np.zeros(mask_shape, np.int),
bbox.upper_left_point,
bbox.bottom_right_point,
1, -1)
return draw_rectangle(np.zeros(mask_shape, int),
bbox.upper_left_point,
bbox.bottom_right_point,
1)


def draw_rectangle(img: np.ndarray, pt1: Tuple[int, int], pt2: Tuple[int, int], fill: int):
cp = img.copy()
cp[slice(pt1[0], pt2[0] + 1), slice(pt1[1], pt2[1] + 1)] = fill
return cp

0 comments on commit 6e54802

Please sign in to comment.