Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/unifyai/vision
Browse files Browse the repository at this point in the history
  • Loading branch information
juliagsy committed May 11, 2023
2 parents 86e6403 + 44c6077 commit 46dfa8e
Show file tree
Hide file tree
Showing 39 changed files with 4,005 additions and 1,620 deletions.
35 changes: 11 additions & 24 deletions .github/workflows/docs.yml
@@ -1,26 +1,13 @@
name: docs
on: [push]
name: Update docs
on:
push:
branches:
- master
tags:
- v*

jobs:
update-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️Ivy Vision
uses: actions/checkout@v2
with:
path: ivy_vision
persist-credentials: false

- name: Build Docs
run: |
cd ivy_vision
docker run --rm -v "$(pwd)":/project unifyai/doc-builder:latest
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: ivy_vision/docs/build
CLEAN: false
GIT_CONFIG_NAME: ivy-seed
GIT_CONFIG_EMAIL: ivydl.team@gmail.com
name: Update docs
uses: unifyai/workflows/.github/workflows/docs.yml@master
secrets: inherit
15 changes: 15 additions & 0 deletions .github/workflows/lint-bot.yml
@@ -0,0 +1,15 @@
name: lint-bot

on:
schedule:
- cron: '0 8 * * *'
workflow_dispatch:

permissions:
contents: write

jobs:
fix-linting:
name: Fix Linting
uses: unifyai/workflows/.github/workflows/lint-bot.yml@master
secrets: inherit
8 changes: 8 additions & 0 deletions .github/workflows/lint.yml
@@ -0,0 +1,8 @@
name: lint

on: [push, pull_request]

jobs:
check-formatting:
name: Check formatting
uses: unifyai/workflows/.github/workflows/lint.yml@master
18 changes: 18 additions & 0 deletions .pre-commit-config.yaml
@@ -0,0 +1,18 @@
repos:
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
language_version: python3
- repo: https://github.com/PyCQA/autoflake
rev: v2.1.1
hooks:
- id: autoflake
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/pydocstyle
rev: 6.3.0
hooks:
- id: pydocstyle
48 changes: 27 additions & 21 deletions conftest.py
Expand Up @@ -4,11 +4,10 @@

# local
import ivy
import ivy.compiler.compiler as ic
from ivy_tests.test_ivy import helpers


FW_STRS = ['numpy', 'jax', 'tensorflow', 'torch']
FW_STRS = ["numpy", "jax", "tensorflow", "torch"]


TEST_BACKENDS: Dict[str, callable] = {
Expand All @@ -18,9 +17,10 @@
"torch": lambda: helpers.globals._get_ivy_torch(),
}


@pytest.fixture(autouse=True)
def run_around_tests(dev_str, f, compile_graph, implicit, fw):
if 'gpu' in dev_str and fw == 'numpy':
if "gpu" in dev_str and fw == "numpy":
# Numpy does not support GPU
pytest.skip()
ivy.unset_backend()
Expand All @@ -30,32 +30,31 @@ def run_around_tests(dev_str, f, compile_graph, implicit, fw):


def pytest_generate_tests(metafunc):

# device
raw_value = metafunc.config.getoption('--device')
if raw_value == 'all':
devices = ['cpu', 'gpu:0', 'tpu:0']
raw_value = metafunc.config.getoption("--device")
if raw_value == "all":
devices = ["cpu", "gpu:0", "tpu:0"]
else:
devices = raw_value.split(',')
devices = raw_value.split(",")

# framework
raw_value = metafunc.config.getoption('--backend')
if raw_value == 'all':
raw_value = metafunc.config.getoption("--backend")
if raw_value == "all":
backend_strs = TEST_BACKENDS.keys()
else:
backend_strs = raw_value.split(',')
backend_strs = raw_value.split(",")

# compile_graph
raw_value = metafunc.config.getoption('--compile_graph')
if raw_value == 'both':
raw_value = metafunc.config.getoption("--compile_graph")
if raw_value == "both":
compile_modes = [True, False]
elif raw_value == 'true':
elif raw_value == "true":
compile_modes = [True]
else:
compile_modes = [False]

# with_implicit
raw_value = metafunc.config.getoption('--with_implicit')
raw_value = metafunc.config.getoption("--with_implicit")
if raw_value == "true":
implicit_modes = [True, False]
else:
Expand All @@ -68,12 +67,19 @@ def pytest_generate_tests(metafunc):
for compile_graph in compile_modes:
for implicit in implicit_modes:
configs.append(
(device, TEST_BACKENDS[backend_str](), compile_graph, implicit, backend_str))
metafunc.parametrize('dev_str,f,compile_graph,implicit,fw', configs)
(
device,
TEST_BACKENDS[backend_str](),
compile_graph,
implicit,
backend_str,
)
)
metafunc.parametrize("dev_str,f,compile_graph,implicit,fw", configs)


def pytest_addoption(parser):
parser.addoption('--device', action="store", default="cpu")
parser.addoption('--backend', action="store", default="numpy,jax,tensorflow,torch")
parser.addoption('--compile_graph', action="store", default="true")
parser.addoption('--with_implicit', action="store", default="false")
parser.addoption("--device", action="store", default="cpu")
parser.addoption("--backend", action="store", default="numpy,jax,tensorflow,torch")
parser.addoption("--compile_graph", action="store", default="true")
parser.addoption("--with_implicit", action="store", default="false")
3 changes: 2 additions & 1 deletion docs/index.rst
Expand Up @@ -4,6 +4,7 @@
:toctree: vision
:template: top_level_toc.rst
:recursive:
:include:
:caption: API Reference
:hide-table:

ivy_vision
9 changes: 6 additions & 3 deletions docs/partial_conf.py
@@ -1,3 +1,6 @@
ivy_toctree_caption_map = {
"ivy_vision": "Vision",
}
# Retrieve html_theme_options from docs/conf.py
from docs.conf import html_theme_options

html_theme_options["switcher"][
"json_url"
] = "https://lets-unify.ai/docs/versions/vision.json"
68 changes: 33 additions & 35 deletions ivy_vision/containers.py
@@ -1,18 +1,19 @@
# global
import ivy
import ivy

# local
import ivy_vision.sdf as ivy_sdf


# noinspection PyMissingConstructor
class PrimitiveScene(ivy.Container):

def __init__(self,
sphere_positions=None,
sphere_radii=None,
cuboid_ext_mats=None,
cuboid_dims=None):
def __init__(
self,
sphere_positions=None,
sphere_radii=None,
cuboid_ext_mats=None,
cuboid_dims=None,
):
"""Initialize scene description as a composition of primitive shapes. # ToDo:
extend this to include cylinders and cones once supported in ivy_vision.sdf
module
Expand All @@ -35,7 +36,8 @@ def __init__(self,
sphere_positions=sphere_positions,
sphere_radii=sphere_radii,
cuboid_ext_mats=cuboid_ext_mats,
cuboid_dims=cuboid_dims)
cuboid_dims=cuboid_dims,
)

# Class Methods #
# --------------#
Expand Down Expand Up @@ -87,25 +89,27 @@ def sdf(self, query_positions):
all_sdfs_list = list()
if self.sphere_positions is not None:
sphere_sdfs = ivy_sdf.sphere_signed_distances(
self.sphere_positions[..., 0:3, -1], self.sphere_radii, query_positions)
self.sphere_positions[..., 0:3, -1], self.sphere_radii, query_positions
)
all_sdfs_list.append(sphere_sdfs)
if self.cuboid_ext_mats is not None:
cuboid_sdfs = ivy_sdf.cuboid_signed_distances(
self.cuboid_ext_mats, self.cuboid_dims, query_positions)
self.cuboid_ext_mats, self.cuboid_dims, query_positions
)
all_sdfs_list.append(cuboid_sdfs)
sdfs_concatted = ivy.concat(all_sdfs_list, axis=-1) if len(all_sdfs_list) > 1 else all_sdfs_list[0]
sdfs_concatted = (
ivy.concat(all_sdfs_list, axis=-1)
if len(all_sdfs_list) > 1
else all_sdfs_list[0]
)
return ivy.min(sdfs_concatted, axis=-1, keepdims=True)


# noinspection PyMissingConstructor
class Intrinsics(ivy.Container):

def __init__(self,
focal_lengths,
persp_angles,
pp_offsets,
calib_mats,
inv_calib_mats):
def __init__(
self, focal_lengths, persp_angles, pp_offsets, calib_mats, inv_calib_mats
):
"""Initialize camera intrinsics container.
Parameters
Expand All @@ -127,7 +131,8 @@ def __init__(self,
persp_angles=persp_angles,
pp_offsets=pp_offsets,
calib_mats=calib_mats,
inv_calib_mats=inv_calib_mats)
inv_calib_mats=inv_calib_mats,
)

# Class Methods #
# --------------#
Expand Down Expand Up @@ -155,18 +160,14 @@ def as_identity(batch_shape):
pp_offsets = ivy.zeros(batch_shape + [2])
calib_mats = ivy.eye(3, batch_shape=batch_shape)
inv_calib_mats = ivy.eye(3, batch_shape=batch_shape)
return __class__(focal_lengths, persp_angles, pp_offsets, calib_mats, inv_calib_mats)
return __class__(
focal_lengths, persp_angles, pp_offsets, calib_mats, inv_calib_mats
)


# noinspection PyMissingConstructor
class Extrinsics(ivy.Container):

def __init__(self,
cam_centers,
Rs,
inv_Rs,
ext_mats_homo,
inv_ext_mats_homo):
def __init__(self, cam_centers, Rs, inv_Rs, ext_mats_homo, inv_ext_mats_homo):
"""Initialize camera extrinsics container.
Parameters
Expand All @@ -188,7 +189,8 @@ def __init__(self,
Rs=Rs,
inv_Rs=inv_Rs,
ext_mats_homo=ext_mats_homo,
inv_ext_mats_homo=inv_ext_mats_homo)
inv_ext_mats_homo=inv_ext_mats_homo,
)

# Class Methods #
# --------------#
Expand Down Expand Up @@ -221,12 +223,7 @@ def as_identity(batch_shape):

# noinspection PyMissingConstructor
class CameraGeometry(ivy.Container):

def __init__(self,
intrinsics,
extrinsics,
full_mats_homo,
inv_full_mats_homo):
def __init__(self, intrinsics, extrinsics, full_mats_homo, inv_full_mats_homo):
"""Initialize camera geometry container.
Parameters
Expand All @@ -245,7 +242,8 @@ def __init__(self,
intrinsics=intrinsics,
extrinsics=extrinsics,
full_mats_homo=full_mats_homo,
inv_full_mats_homo=inv_full_mats_homo)
inv_full_mats_homo=inv_full_mats_homo,
)

# Class Methods #
# --------------#
Expand Down
15 changes: 9 additions & 6 deletions ivy_vision/image.py
Expand Up @@ -47,7 +47,6 @@ def stack_images(images, desired_aspect_ratio):


def gradient_image(x):

"""Computes image gradients (dy, dx) for each channel.
Parameters
----------
Expand All @@ -74,10 +73,12 @@ def gradient_image(x):
dx = x[..., :, 1:, :] - x[..., :, :-1, :]
# BS x H x W x D
dy = ivy.concat(
(dy, ivy.zeros(batch_shape + [1, image_dims[1], num_dims], device=device)), axis=-3
(dy, ivy.zeros(batch_shape + [1, image_dims[1], num_dims], device=device)),
axis=-3,
)
dx = ivy.concat(
(dx, ivy.zeros(batch_shape + [image_dims[0], 1, num_dims], device=device)), axis=-2
(dx, ivy.zeros(batch_shape + [image_dims[0], 1, num_dims], device=device)),
axis=-2,
)
# BS x H x W x D, BS x H x W x D
return dx, dy
Expand Down Expand Up @@ -167,7 +168,9 @@ def random_crop(x, crop_size, batch_shape=None, image_dims=None, seed: int = Non
# list of 1 x NH x NW x F
cropped_list = [
img[..., xo : xo + crop_size[0], yo : yo + crop_size[1], :]
for img, xo, yo in zip(ivy.unstack(x_flat, axis=0, keepdims=True), x_offsets, y_offsets)
for img, xo, yo in zip(
ivy.unstack(x_flat, axis=0, keepdims=True), x_offsets, y_offsets
)
]

# FBS x NH x NW x F
Expand Down Expand Up @@ -203,7 +206,7 @@ def bilinear_resample(x, warp):
height, width = input_image_dims
max_x = width - 1
max_y = height - 1
idx_size = warp.shape[-2]
warp.shape[-2]
batch_shape_flat = int(ivy.prod(ivy.asarray(batch_shape)))
# B
batch_offsets = ivy.arange(batch_shape_flat) * height * width
Expand All @@ -215,7 +218,7 @@ def bilinear_resample(x, warp):
data_flat = ivy.reshape(x, [batch_shape_flat * height * width, -1])
# (BxHxW) x 2
warp_flat = ivy.reshape(warp, [-1, 2])
warp_floored = (ivy.floor(warp_flat)).astype('int32')
warp_floored = (ivy.floor(warp_flat)).astype("int32")
bilinear_weights = warp_flat - ivy.floor(warp_flat)
# (BxHxW)
x0 = warp_floored[:, 0]
Expand Down

0 comments on commit 46dfa8e

Please sign in to comment.