Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
BachiLi committed Sep 4, 2020
0 parents commit 413a3e5
Show file tree
Hide file tree
Showing 148 changed files with 138,536 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
build
apps/results
apps/files
apps/__pycache__
compile_commands.json
.vimrc
diffvg.egg-info
dist
__pycache__
.DS_Store
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "pybind11"]
path = pybind11
url = https://github.com/pybind/pybind11
[submodule "thrust"]
path = thrust
url = https://github.com/thrust/thrust.git
140 changes: 140 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
cmake_minimum_required(VERSION 3.12)

project(diffvg VERSION 0.0.1 DESCRIPTION "Differentiable Vector Graphics")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(WIN32)
find_package(Python 3.6 COMPONENTS Development REQUIRED)
else()
find_package(Python 3.7 COMPONENTS Development REQUIRED)
endif()
add_subdirectory(pybind11)

option(DIFFVG_CUDA "Build diffvg with GPU code path?" ON)

if(DIFFVG_CUDA)
message(STATUS "Build with CUDA support")
find_package(CUDA 10 REQUIRED)
set(CMAKE_CUDA_STANDARD 11)
if(NOT WIN32)
# Hack: for some reason the line above doesn't work on some Linux systems.
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++11")
#set(CUDA_NVCC_FLAGS_DEBUG "-g -G")
endif()
else()
message(STATUS "Build without CUDA support")
find_package(Thrust REQUIRED)
endif()

# include_directories(${CMAKE_SOURCE_DIR}/pybind11/include)
include_directories(${PYTHON_INCLUDE_PATH})
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_PATH})
include_directories(${PYTHON_INCLUDE_DIRS})
include_directories(pybind11/include)
if(DIFFVG_CUDA)
link_directories(${CUDA_LIBRARIES})
else()
include_directories(${THRUST_INCLUDE_DIR})
endif()

if(NOT MSVC)
# These compile definitions are not meaningful for MSVC
add_compile_options(-Wall -g -O3 -fvisibility=hidden -Wno-unknown-pragmas)
else()
add_compile_options(/Wall /Zi)
add_link_options(/DEBUG)
endif()

if(NOT DIFFVG_CUDA)
add_compile_options("-DTHRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CPP")
endif()

set(SRCS atomic.h
color.h
cdf.h
cuda_utils.h
diffvg.h
edge_query.h
filter.h
matrix.h
parallel.h
pcg.h
ptr.h
sample_boundary.h
scene.h
shape.h
solve.h
vector.h
within_distance.h
winding_number.h
atomic.cpp
color.cpp
diffvg.cpp
parallel.cpp
scene.cpp
shape.cpp)

if(DIFFVG_CUDA)
add_compile_definitions(COMPILE_WITH_CUDA)
set_source_files_properties(
diffvg.cpp
scene.cpp
PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)

cuda_add_library(diffvg MODULE ${SRCS})
else()
add_library(diffvg MODULE ${SRCS})
endif()

if(APPLE)
# The "-undefined dynamic_lookup" is a hack for systems with
# multiple Python installed. If we link a particular Python version
# here, and we import it with a different Python version later.
# likely a segmentation fault.
# The solution for Linux Mac OS machines, as mentioned in
# https://github.com/pybind/pybind11/blob/master/tools/pybind11Tools.cmake
# is to not link against Python library at all and resolve the symbols
# at compile time.
set(DYNAMIC_LOOKUP "-undefined dynamic_lookup")
endif()

target_link_libraries(diffvg ${DYNAMIC_LOOKUP})

if(WIN32)
# See: https://pybind11.readthedocs.io/en/master/compiling.html#advanced-interface-library-target
target_link_libraries(diffvg pybind11::module)
set_target_properties(diffvg PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
SUFFIX "${PYTHON_MODULE_EXTENSION}")
endif()

set_target_properties(diffvg PROPERTIES SKIP_BUILD_RPATH FALSE)
set_target_properties(diffvg PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
if(UNIX AND NOT APPLE)
set_target_properties(diffvg PROPERTIES INSTALL_RPATH "$ORIGIN")
elseif(APPLE)
set_target_properties(diffvg PROPERTIES INSTALL_RPATH "@loader_path")
endif()

set_property(TARGET diffvg PROPERTY CXX_STANDARD 11)
set_target_properties(diffvg PROPERTIES PREFIX "")
# Still enable assertion in release mode
string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string( REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string( REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string( REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string( REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string( REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string( REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")

if(NOT WIN32)
find_package(TensorFlow)
if(TensorFlow_FOUND)
add_subdirectory(pydiffvg_tensorflow/custom_ops)
else()
message(INFO " Building without TensorFlow support (not found)")
endif()
endif()
115 changes: 115 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# diffvg
Differentiable Rasterizer for Vector Graphics
https://people.csail.mit.edu/tzumao/diffvg

diffvg is a differentiable rasterizer for 2D vector graphics. See the webpage for more info.

![teaser](https://user-images.githubusercontent.com/951021/92184822-2a0bc500-ee20-11ea-81a6-f26af2d120f4.jpg)

![circle](https://user-images.githubusercontent.com/951021/63556018-0b2ddf80-c4f8-11e9-849c-b4ecfcb9a865.gif)
![ellipse](https://user-images.githubusercontent.com/951021/63556021-0ec16680-c4f8-11e9-8fc6-8b34de45b8be.gif)
![rect](https://user-images.githubusercontent.com/951021/63556028-12ed8400-c4f8-11e9-8072-81702c9193e1.gif)
![polygon](https://user-images.githubusercontent.com/951021/63980999-1e99f700-ca72-11e9-9786-1cba14d2d862.gif)
![curve](https://user-images.githubusercontent.com/951021/64042667-3d9e9480-cb17-11e9-88d8-2f7b9da8b8ab.gif)
![path](https://user-images.githubusercontent.com/951021/64070625-7a52b480-cc19-11e9-9380-eac02f56f693.gif)
![gradient](https://user-images.githubusercontent.com/951021/64898668-da475300-d63c-11e9-917a-825b94be0710.gif)
![circle_outline](https://user-images.githubusercontent.com/951021/65125594-84f7a280-d9aa-11e9-8bc4-669fd2eff2f4.gif)
![ellipse_transform](https://user-images.githubusercontent.com/951021/67149013-06b54700-f25b-11e9-91eb-a61171c6d4a4.gif)

# Install
```
git submodule update --init --recursive
conda install pytorch torchvision -c pytorch
conda install numpy
conda install scikit-image
pip install svgwrite
pip install svgpathtools
pip install cssutils
pip install numba
pip install torch-tools
pip install visdom
python setup.py install
```

# Building in debug mode

```
python setup.py build --debug install
```

# Run
```
cd apps
```

Optimizing a single circle to a target.
```
python single_circle.py
```

Finite difference comparison.
```
finite_difference_comp.py [-h] [--size_scale SIZE_SCALE]
[--clamping_factor CLAMPING_FACTOR]
[--use_prefiltering USE_PREFILTERING]
svg_file
```
e.g.,
```
python finite_difference_comp.py imgs/tiger.svg
```

Interactive editor
```
python svg_brush.py
```

Painterly rendering
```
painterly_rendering.py [-h] [--num_paths NUM_PATHS]
[--max_width MAX_WIDTH] [--use_lpips_loss]
[--num_iter NUM_ITER] [--use_blob]
target
```
e.g.,
```
python painterly_rendering.py imgs/fallingwater.jpg --num_paths 2048 --max_width 4.0 --use_lpips_loss
```

Image vectorization
```
python refine_svg.py [-h] [--use_lpips_loss] [--num_iter NUM_ITER] svg target
```
e.g.,
```
python refine_svg.py imgs/flower.svg imgs/flower.jpg
```

Seam carving
```
python seam_carving.py [-h] [--svg SVG] [--optim_steps OPTIM_STEPS]
```
e.g.,
```
python seam_carving.py imgs/hokusai.svg
```

Vector variational autoencoder & vector GAN:

For the GAN models, see `apps/generative_models/train_gan.py`. Generate samples from a pretrained using `apps/generative_models/eval_gan.py`.

For the VAE models, see `apps/generative_models/mnist_vae.py`.

If you use diffvg in your academic work, please cite

```
@article{Li:2020:DVG,
title = {Differentiable Vector Graphics Rasterization for Editing and Learning},
author = {Li, Tzu-Mao and Luk\'{a}\v{c}, Michal and Gharbi Micha\"{e}l and Jonathan Ragan-Kelley},
journal = {ACM Trans. Graph. (Proc. SIGGRAPH Asia)},
volume = {39},
number = {6},
pages = {193:1--193:15},
year = {2020}
}
```
67 changes: 67 additions & 0 deletions aabb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

#include "diffvg.h"
#include "cuda_utils.h"
#include "vector.h"
#include "matrix.h"

struct AABB {
DEVICE
inline AABB(const Vector2f &p_min = Vector2f{infinity<float>(), infinity<float>()},
const Vector2f &p_max = Vector2f{-infinity<float>(), -infinity<float>()})
: p_min(p_min), p_max(p_max) {}
Vector2f p_min, p_max;
};

DEVICE
inline
AABB merge(const AABB &box, const Vector2f &p) {
return AABB{Vector2f{min(p.x, box.p_min.x), min(p.y, box.p_min.y)},
Vector2f{max(p.x, box.p_max.x), max(p.y, box.p_max.y)}};
}

DEVICE
inline
AABB merge(const AABB &box0, const AABB &box1) {
return AABB{Vector2f{min(box0.p_min.x, box1.p_min.x), min(box0.p_min.y, box1.p_min.y)},
Vector2f{max(box0.p_max.x, box1.p_max.x), max(box0.p_max.y, box1.p_max.y)}};
}

DEVICE
inline
bool inside(const AABB &box, const Vector2f &p) {
return p.x >= box.p_min.x && p.x <= box.p_max.x &&
p.y >= box.p_min.y && p.y <= box.p_max.y;
}

DEVICE
inline
bool inside(const AABB &box, const Vector2f &p, float radius) {
return p.x >= box.p_min.x - radius && p.x <= box.p_max.x + radius &&
p.y >= box.p_min.y - radius && p.y <= box.p_max.y + radius;
}

DEVICE
inline
AABB enlarge(const AABB &box, float width) {
return AABB{Vector2f{box.p_min.x - width, box.p_min.y - width},
Vector2f{box.p_max.x + width, box.p_max.y + width}};
}

DEVICE
inline
AABB transform(const Matrix3x3f &xform, const AABB &box) {
auto ret = AABB();
ret = merge(ret, xform_pt(xform, Vector2f{box.p_min.x, box.p_min.y}));
ret = merge(ret, xform_pt(xform, Vector2f{box.p_min.x, box.p_max.y}));
ret = merge(ret, xform_pt(xform, Vector2f{box.p_max.x, box.p_min.y}));
ret = merge(ret, xform_pt(xform, Vector2f{box.p_max.x, box.p_max.y}));
return ret;
}

DEVICE
inline
bool within_distance(const AABB &box, const Vector2f &pt, float r) {
return pt.x >= box.p_min.x - r && pt.x <= box.p_max.x + r &&
pt.y >= box.p_min.y - r && pt.y <= box.p_max.y + r;
}
3 changes: 3 additions & 0 deletions apps/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mnist
data/sketchrnn_cat.npz
data
10 changes: 10 additions & 0 deletions apps/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SEAM_IMAGES=seaside2 sunset2 hokusai cat ice_cream
SEAM_OUT=results/seam_carving
SEAM_RESULTS=$(addsuffix /out.mp4,$(addprefix $(SEAM_OUT)/,$(SEAM_IMAGES)))

all: $(SEAM_RESULTS)
echo $(SEAM_RESULTS)

$(SEAM_OUT)/%/out.mp4: imgs/seamcarving/%.svg
python seam_carving.py --svg $^

Loading

0 comments on commit 413a3e5

Please sign in to comment.