Skip to content

Commit

Permalink
Merge branch 'develop' into CTX-4070
Browse files Browse the repository at this point in the history
* develop:
  CTX-4079: Redesigned terminate condition for experiment worker process - Added log file output for experiment worker process for debugging purposes
  CTX-4251: Update "model-queue/custom" to "run" endpoint
  Version bump
  CTX-4219: Make root not private to make it available outside the class - Name starts with an underscore to mark it as internally used don't touch
  CTX-4083: Moved heartbeat to the metrics worker process - Renamed metrics worker process to experiment worker
  Version bump
  CTX-4102: Fix terminating metrics process on experiment process kill
  CTX-4166: Implemented Sequence sample import
  CTX-3890: Changed division to //
  CTX-3890: Converted wider code to be compatible with int based bounding boxes
  CTX-3890: Changed width and height variables from float to int
  Update README.md
  • Loading branch information
Vuk Manojlovic committed Jul 11, 2023
2 parents 620fac0 + 9415689 commit 5c31d92
Show file tree
Hide file tree
Showing 31 changed files with 604 additions and 224 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ if __name__ == "__main__":
initializeProject(main)
```

(Read the documentation and learn how you can migrate your project to the Coretex platform -> [Migrate your project to Coretex](https://app.gitbook.com/o/6QxmEiF5ygi67vFH3kV1/s/YoN0XCeop3vrJ0hyRKxx/getting-started/demo-experiments/migrate-your-project-to-coretex))
Read the documentation and learn how you can migrate your project to the Coretex platform -> [Migrate your project to Coretex](https://app.gitbook.com/o/6QxmEiF5ygi67vFH3kV1/s/YoN0XCeop3vrJ0hyRKxx/getting-started/demo-experiments/migrate-your-project-to-coretex)

## Key Features

Expand Down
40 changes: 20 additions & 20 deletions coretex/coretex/annotation/image/bbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,49 +28,49 @@ class BBox(Codable):
Properties
----------
minX : float
minX : int
top left x coordinate
minY : float
minY : int
top left y coordinate
width : float
width : int
width of the bounding box
height : float
height : int
height of the bounding box
"""

def __init__(self, minX: float = 0, minY: float = 0, width: float = 0, height: float = 0) -> None:
def __init__(self, minX: int = 0, minY: int = 0, width: int = 0, height: int = 0) -> None:
self.minX: Final = minX
self.minY: Final = minY

self.width: Final = width
self.height: Final = height

@property
def maxX(self) -> float:
def maxX(self) -> int:
"""
Returns
-------
float -> bottom right x coordinate
int -> bottom right x coordinate
"""

return self.minX + self.width

@property
def maxY(self) -> float:
def maxY(self) -> int:
"""
Returns
-------
float -> bottom right y coordinate
int -> bottom right y coordinate
"""

return self.minY + self.height

@property
def polygon(self) -> List[float]:
def polygon(self) -> List[int]:
"""
Returns
-------
List[float] -> Bounding box represented as a polygon (x, y) values
List[int] -> Bounding box represented as a polygon (x, y) values
"""

return [
Expand All @@ -91,20 +91,20 @@ def _keyDescriptors(cls) -> Dict[str, KeyDescriptor]:
return descriptors

@classmethod
def create(cls, minX: float, minY: float, maxX: float, maxY: float) -> Self:
def create(cls, minX: int, minY: int, maxX: int, maxY: int) -> Self:
"""
Utility constructor which has maxX and maxY as parameters instead
of width and height
Parameters
----------
minX : float
minX : int
top left x coordinate
minY : float
minY : int
top left y coordinate
maxX : float
maxX : int
bottom right x coordinate
maxY : float
maxY : int
bottom right y coordinate
Returns
Expand All @@ -115,15 +115,15 @@ def create(cls, minX: float, minY: float, maxX: float, maxY: float) -> Self:
return cls(minX, minY, maxX - minX, maxY - minY)

@classmethod
def fromPoly(cls, polygon: List[float]) -> Self:
def fromPoly(cls, polygon: List[int]) -> Self:
"""
Creates bounding box from a polygon, by finding
the minimum x and y coordinates and calculating
width and height of the polygon
Parameters
----------
polygon : List[float]
polygon : List[int]
list of x, y points - length must be even
Returns
Expand All @@ -140,8 +140,8 @@ def fromPoly(cls, polygon: List[float]) -> Self:
"minX: 0, minY: 0, width: 4, height: 3"
"""

x: List[float] = []
y: List[float] = []
x: List[int] = []
y: List[int] = []

for index, value in enumerate(polygon):
if index % 2 == 0:
Expand Down
46 changes: 23 additions & 23 deletions coretex/coretex/annotation/image/coretex_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
from ....codable import Codable, KeyDescriptor


SegmentationType = List[float]
SegmentationType = List[int]


def toPoly(segmentation: List[float]) -> List[Tuple[float, float]]:
points: List[Tuple[float, float]] = []
def toPoly(segmentation: List[int]) -> List[Tuple[int, int]]:
points: List[Tuple[int, int]] = []

for index in range(0, len(segmentation) - 1, 2):
points.append((segmentation[index], segmentation[index + 1]))
Expand Down Expand Up @@ -145,42 +145,42 @@ def extractBinaryMask(self, width: int, height: int) -> np.ndarray:

return binaryMask

def centroid(self) -> Tuple[float, float]:
def centroid(self) -> Tuple[int, int]:
"""
Calculates centroid of segmentations
Returns
-------
Tuple[float, float] -> x, y coordinates of centroid
Tuple[int, int] -> x, y coordinates of centroid
"""

flattenedSegmentations = [element for sublist in self.segmentations for element in sublist]

listCX = [value for index, value in enumerate(flattenedSegmentations) if index % 2 == 0]
centerX = fsum(listCX) / len(listCX)
centerX = sum(listCX) // len(listCX)

listCY = [value for index, value in enumerate(flattenedSegmentations) if index % 2 != 0]
centerY = fsum(listCY) / len(listCY)
centerY = sum(listCY) // len(listCY)

return centerX, centerY

def centerSegmentations(self, newCentroid: Tuple[float, float]) -> None:
def centerSegmentations(self, newCentroid: Tuple[int, int]) -> None:
"""
Centers segmentations to the specified center point
Parameters
----------
newCentroid : Tuple[float, float]
newCentroid : Tuple[int, int]
x, y coordinates of centroid
"""

newCenterX, newCenterY = newCentroid
oldCenterX, oldCenterY = self.centroid()

modifiedSegmentations: List[List[float]] = []
modifiedSegmentations: List[List[int]] = []

for segmentation in self.segmentations:
modifiedSegmentation: List[float] = []
modifiedSegmentation: List[int] = []

for i in range(0, len(segmentation), 2):
x = segmentation[i] + (newCenterX - oldCenterX)
Expand All @@ -203,7 +203,7 @@ def rotateSegmentations(self, degrees: int) -> None:
degree of rotation
"""

rotatedSegmentations: List[List[float]] = []
rotatedSegmentations: List[List[int]] = []
centerX, centerY = self.centroid()

# because rotations with image and segmentations doesn't go in same direction
Expand All @@ -212,14 +212,14 @@ def rotateSegmentations(self, degrees: int) -> None:
cosang, sinang = cos(theta), sin(theta)

for segmentation in self.segmentations:
rotatedSegmentation: List[float] = []
rotatedSegmentation: List[int] = []

for i in range(0, len(segmentation), 2):
x = segmentation[i] - centerX
y = segmentation[i + 1] - centerY

newX = (x * cosang - y * sinang) + centerX
newY = (x * sinang + y * cosang) + centerY
newX = int(x * cosang - y * sinang) + centerX
newY = int(x * sinang + y * cosang) + centerY

rotatedSegmentation.append(newX)
rotatedSegmentation.append(newY)
Expand All @@ -238,17 +238,17 @@ class CoretexImageAnnotation(Codable):
----------
name : str
name of annotation class
width : float
width : int
width of annotation
height : float
height : int
height of annotation
instances : List[CoretexSegmentationInstance]
list of SegmentationInstance objects
"""

name: str
width: float
height: float
width: int
height: int
instances: List[CoretexSegmentationInstance]

@classmethod
Expand All @@ -262,8 +262,8 @@ def _keyDescriptors(cls) -> Dict[str, KeyDescriptor]:
def create(
cls,
name: str,
width: float,
height: float,
width: int,
height: int,
instances: List[CoretexSegmentationInstance]
) -> Self:
"""
Expand All @@ -273,9 +273,9 @@ def create(
----------
name : str
name of annotation class
width : float
width : int
width of annotation
height : float
height : int
height of annotation
instances : List[CoretexSegmentationInstance]
list of SegmentationInstance objects
Expand Down
6 changes: 3 additions & 3 deletions coretex/coretex/conversion/converters/create_ml_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ def _extractLabels(self) -> Set[str]:

return labels

def __extractBBox(self, bbox: Dict[str, float]) -> BBox:
def __extractBBox(self, bbox: Dict[str, int]) -> BBox:
return BBox(
bbox["x"] - bbox["width"] / 2,
bbox["y"] - bbox["height"] / 2,
bbox["x"] - bbox["width"] // 2,
bbox["y"] - bbox["height"] // 2,
bbox["width"],
bbox["height"]
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def _dataSource(self) -> List[str]:
def _extractLabels(self) -> Set[str]:
return set(["background", "human"])

def __extractPolygons(self, annotationPath: str, imageWidth: int, imageHeight: int) -> List[List[float]]:
def __extractPolygons(self, annotationPath: str, imageWidth: int, imageHeight: int) -> List[List[int]]:
maskImage = Image.open(annotationPath)
if maskImage is None:
return []
Expand All @@ -81,7 +81,7 @@ def __extractPolygons(self, annotationPath: str, imageWidth: int, imageHeight: i

contours = skimage.measure.find_contours(subMaskArray, 0.5)

segmentations: List[List[float]] = []
segmentations: List[List[int]] = []
for contour in contours:
for i in range(len(contour)):
row, col = contour[i]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __extractInstance(self, shape: Dict[str, Any]) -> Optional[CoretexSegmentati
logging.getLogger("coretexpylib").info(f">> [Coretex] Class: ({label}) is not a part of dataset")
return None

points: List[float] = np.array(shape["points"]).flatten().tolist()
points: List[int] = np.array(shape["points"]).flatten().tolist()
bbox = BBox.fromPoly(points)

return CoretexSegmentationInstance.create(coretexClass.classIds[0], bbox, [points])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from ....dataset import ImageDataset


ContourPoints = List[List[float]]
ContourPoints = List[List[int]]
SegmentationPolygon = List[ContourPoints]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import glob
import xml.etree.ElementTree as ET

from .shared import getTag, toFloat
from .shared import getTag, toInt
from .instance_extractor import InstanceExtractor
from ...base_converter import BaseConverter
from .....coretex import CoretexImageAnnotation
Expand Down Expand Up @@ -84,7 +84,7 @@ def __extractImageAnnotation(self, root: ET.Element) -> None:
if size is None:
return

width, height = toFloat(size, "width", "height")
width, height = toInt(size, "width", "height")
if width is None or height is None:
return

Expand Down
10 changes: 10 additions & 0 deletions coretex/coretex/conversion/converters/pascal/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ def toFloat(rootEl: ET.Element, firstEl: str, secondEl: str) -> Tuple[Optional[f
return (float(firstVal), float(secondVal))


def toInt(rootEl: ET.Element, firstEl: str, secondEl: str) -> Tuple[Optional[int], Optional[int]]:
firstVal = getTag(rootEl, firstEl)
secondVal = getTag(rootEl, secondEl)

if firstVal is None or secondVal is None:
return (None, None)

return (int(firstVal), int(secondVal))


def getBoxes(bndbox: ET.Element) -> Optional[Dict[str, float]]:
xmin, ymin = toFloat(bndbox, "xmin", "ymin")
xmax, ymax = toFloat(bndbox, "xmax", "ymax")
Expand Down
4 changes: 2 additions & 2 deletions coretex/coretex/conversion/converters/voc_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import glob
import xml.etree.ElementTree as ET

from .pascal.shared import getTag, getBoxes, toFloat
from .pascal.shared import getTag, getBoxes, toInt
from ..base_converter import BaseConverter
from ...annotation import CoretexImageAnnotation, CoretexSegmentationInstance, BBox

Expand Down Expand Up @@ -91,7 +91,7 @@ def _extractImageAnnotation(self, root: ET.Element) -> None:
if size is None:
return

width, height = toFloat(size, "width", "height")
width, height = toInt(size, "width", "height")
if width is None or height is None:
return

Expand Down
8 changes: 4 additions & 4 deletions coretex/coretex/conversion/converters/yolo_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ def __extractBBox(self, rawInstance: List[str], width: int, height: int) -> BBox
wYolo = float(rawInstance[3])
hYolo = float(rawInstance[4])

boxWidth = wYolo * width
boxHeight = hYolo * height
xMin = float(xYolo * width - (boxWidth / 2))
yMin = float(yYolo * height - (boxHeight / 2))
boxWidth = int(wYolo * width)
boxHeight = int(hYolo * height)
xMin = int(xYolo * width - (boxWidth / 2))
yMin = int(yYolo * height - (boxHeight / 2))

return BBox(xMin, yMin, boxWidth, boxHeight)

Expand Down
1 change: 1 addition & 0 deletions coretex/coretex/dataset/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@
from .local_dataset import LocalDataset
from .network_dataset import NetworkDataset
from .utils import downloadDataset
from .sequence_dataset import SequenceDataset, LocalSequenceDataset
Loading

0 comments on commit 5c31d92

Please sign in to comment.