Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ RUN apt-get update && apt-get -y install python3-dev python3-pip chafa imagemagi
RUN mkdir /opt/imgrot
COPY . /opt/imgrot
RUN pip3 install -r /opt/imgrot/requirements.txt --break-system-packages
ENTRYPOINT [ "python3", "/opt/imgrot/demo.py" ]
ENTRYPOINT [ "python3", "/opt/imgrot/imgrot.py" ]
22 changes: 11 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@ clean: docker.clean py-clean
docs: docs.vhs docs.jinja #docs.rotations
docs.jinja:
${pynchon.run} jinja render README.md.j2
python demo.py img/icon.png --stream > img/demo.gif
python imgrot.py img/icon.png --stream > img/demo.gif
docs.vhs:; PS1="$$ " sh -c "${pynchon.run} vhs apply"
docs.rotations:
python demo.py img/graph.png --bg lightblue --rotation x --stream > img/rx.gif
python demo.py img/graph.png --bg lightblue --rotation y --stream > img/ry.gif
python demo.py img/graph.png --bg lightblue --rotation s --stream > img/rs.gif
python demo.py img/graph.png --bg lightblue --rotation j --stream > img/rj.gif
python demo.py img/graph.png --bg lightblue --rotation w --stream > img/rw.gif
python demo.py img/graph.png --bg lightblue --rotation f --stream > img/rf.gif
python demo.py img/graph.png --bg lightblue --rotation exit-ul --stream > img/rul.gif
python demo.py img/graph.png --bg lightblue --rotation exit-ur --stream > img/rur.gif
python demo.py img/graph.png --bg lightblue --rotation exit-lr --stream > img/rlr.gif
python demo.py img/graph.png --bg lightblue --rotation exit-ll --stream > img/rll.gif
python imgrot.py img/graph.png --bg lightblue --rotation x --stream > img/rx.gif
python imgrot.py img/graph.png --bg lightblue --rotation y --stream > img/ry.gif
python imgrot.py img/graph.png --bg lightblue --rotation s --stream > img/rs.gif
python imgrot.py img/graph.png --bg lightblue --rotation j --stream > img/rj.gif
python imgrot.py img/graph.png --bg lightblue --rotation w --stream > img/rw.gif
python imgrot.py img/graph.png --bg lightblue --rotation f --stream > img/rf.gif
python imgrot.py img/graph.png --bg lightblue --rotation exit-ul --stream > img/rul.gif
python imgrot.py img/graph.png --bg lightblue --rotation exit-ur --stream > img/rur.gif
python imgrot.py img/graph.png --bg lightblue --rotation exit-lr --stream > img/rlr.gif
python imgrot.py img/graph.png --bg lightblue --rotation exit-ll --stream > img/rll.gif


docker.clean:
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
<tr>
<td colspan=2><strong>
imgrot
</strong>&nbsp;&nbsp;&nbsp;&nbsp;
</strong><br/>
<a href="https://hub.docker.com/r/robotwranglers/imgrot"><img src="https://img.shields.io/badge/dockerhub-imgrot-blue"><img src="https://img.shields.io/docker/v/robotwranglers/imgrot"></a>
</td>
</tr>
<tr>
Expand All @@ -17,7 +18,6 @@
</tr>
</table>
</P>
<a href="https://hub.docker.com/r/robotwranglers/imgrot"><img src="https://img.shields.io/badge/dockerhub--blue.svg?logo=Docker"></a>

-------------------------------------

Expand All @@ -27,7 +27,7 @@ A fork / update for the excellent original work at [eborboihuc/rotate_3d](https:

The original uses `opencv` to rotate 2d -> 3d. This version adds better CLI parsing, support for python3, newer opencv, ability to animate and render animations with `ffmpeg`, and works via docker.

Besides creating gifs, it can display them inside a terminal, using [chafa](https://github.com/hpjansson/chafa).
Different kinds of rotation are supported as well (see the end of this page for [a gallery](#changing-axis-of-rotation)). Besides creating gifs, it can display them inside a terminal, using [chafa](https://github.com/hpjansson/chafa).

See also [the original docs](docs/README.original.md)

Expand All @@ -48,7 +48,7 @@ pip install -r requirements.txt
**Basic usage info follows:**

```bash
Usage: demo.py [OPTIONS] IMG_PATH
Usage: imgrot.py [OPTIONS] IMG_PATH

Options:
--bg TEXT Background color to pass to chafa
Expand Down Expand Up @@ -78,7 +78,7 @@ You can also set `LOGLEVEL=debug` for more info.

A few examples of usage from docker:

**Saving an animated gif to a file:**
#### Saving an Animation

```bash
$ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot img/icon.png --range 360 --img-shape 200x200 --stream > demo.gif
Expand All @@ -88,7 +88,7 @@ $ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot im
<img width=25% align=center src=img/demo.gif>
</p>

**Rendering a gif, then displaying it in a terminal-friendly way with chafa:**
#### Terminal-Friendly Display

```bash
$ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot img/icon.png --display --stretch --bg lightblue
Expand All @@ -98,11 +98,11 @@ $ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot im
<img width=50% align=center src=img/demo.chafa.gif>
</p>

Note that this tries to respect transparency in the original image, but for more contrast you can effectively add highlights by passing '--bg' arguments that go through to chafa.
Note that this tries to respect transparency in the original image, but for more contrast with black images on black terminals, you can effectively add highlights by passing '--bg' arguments that go through to chafa.

------------------------------

**Changing axis of rotation**
#### Changing Axis of Rotation

The rotation can be controlled to create a bunch of different effects:

Expand Down
16 changes: 8 additions & 8 deletions README.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
<tr>
<td colspan=2><strong>
imgrot
</strong>&nbsp;&nbsp;&nbsp;&nbsp;
</strong><br/>
<a href="{{dockerhub.repo_url}}"><img src="https://img.shields.io/badge/dockerhub-imgrot-blue"><img src="https://img.shields.io/docker/v/robotwranglers/imgrot"></a>
</td>
</tr>
<tr>
Expand All @@ -17,7 +18,6 @@
</tr>
</table>
</P>
<a href="{{dockerhub.repo_url}}"><img src="https://img.shields.io/badge/dockerhub--blue.svg?logo=Docker"></a>

-------------------------------------

Expand All @@ -27,7 +27,7 @@ A fork / update for the excellent original work at [eborboihuc/rotate_3d](https:

The original uses `opencv` to rotate 2d -> 3d. This version adds better CLI parsing, support for python3, newer opencv, ability to animate and render animations with `ffmpeg`, and works via docker.

Besides creating gifs, it can display them inside a terminal, using [chafa](https://github.com/hpjansson/chafa).
Different kinds of rotation are supported as well (see the end of this page for [a gallery](#changing-axis-of-rotation)). Besides creating gifs, it can display them inside a terminal, using [chafa](https://github.com/hpjansson/chafa).

See also [the original docs](docs/README.original.md)

Expand All @@ -48,7 +48,7 @@ pip install -r requirements.txt
**Basic usage info follows:**

```bash
{{bash('python demo.py --help')}}
{{bash('python imgrot.py --help')}}
```

You can also set `LOGLEVEL=debug` for more info.
Expand All @@ -59,7 +59,7 @@ You can also set `LOGLEVEL=debug` for more info.

A few examples of usage from docker:

**Saving an animated gif to a file:**
#### Saving an Animation

```bash
$ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot img/icon.png --range 360 --img-shape 200x200 --stream > demo.gif
Expand All @@ -69,7 +69,7 @@ $ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot im
<img width=25% align=center src=img/demo.gif>
</p>

**Rendering a gif, then displaying it in a terminal-friendly way with chafa:**
#### Terminal-Friendly Display

```bash
$ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot img/icon.png --display --stretch --bg lightblue
Expand All @@ -79,11 +79,11 @@ $ docker run -it --rm -v `pwd`:/workspace -w /workspace robotwranglers/imgrot im
<img width=50% align=center src=img/demo.chafa.gif>
</p>

Note that this tries to respect transparency in the original image, but for more contrast you can effectively add highlights by passing '--bg' arguments that go through to chafa.
Note that this tries to respect transparency in the original image, but for more contrast with black images on black terminals, you can effectively add highlights by passing '--bg' arguments that go through to chafa.

------------------------------

**Changing axis of rotation**
#### Changing Axis of Rotation

The rotation can be controlled to create a bunch of different effects:

Expand Down
4 changes: 2 additions & 2 deletions docs/README.original.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Rotate along XZ axis
Change main function with ideal [arguments](#parameters)

```bash
python demo.py [path of the image] [degree to rotate] ([ideal width] [ideal height])
python imgrot.py [path of the image] [degree to rotate] ([ideal width] [ideal height])
```
e.g.,
Example of rotating an image along yz-axis from 0 to 360 degree with a 5 pixel shift in +X direction
Expand All @@ -32,7 +32,7 @@ Example of rotating an image along yz-axis from 0 to 360 degree with a 5 pixel s
```
Then
```bash
python demo.py img/000001.jpg 360
python imgrot.py img/000001.jpg 360
```

## Parameters:
Expand Down
2 changes: 1 addition & 1 deletion docs/tape/demo.tape
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Set Height 800
Set TypingSpeed .05
Set PlaybackSpeed 1
Set CursorBlink false
Type "python demo.py img/icon.png --display --stretch --bg lightblue"
Type "python imgrot.py img/icon.png --display --stretch --bg lightblue"
Sleep 1.1
Enter
Sleep 30
Expand Down
96 changes: 84 additions & 12 deletions image_transformer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
from math import pi

import cv2
import numpy as np

# Usage:
# Change main function with ideal arguments
# Then
Expand All @@ -25,6 +20,13 @@
# 1. : http://stackoverflow.com/questions/17087446/how-to-calculate-perspective-transform-for-opencv-from-rotation-angles
# 2. : http://jepsonsblog.blogspot.tw/2012/11/rotation-in-3d-using-opencvs.html

import math
import random
from math import pi

import cv2
import numpy as np


def get_rad(theta, phi, gamma):
return (deg_to_rad(theta), deg_to_rad(phi), deg_to_rad(gamma))
Expand All @@ -43,29 +45,102 @@ def rad_to_deg(rad):


class ImageTransformer:
"""Perspective transformation class for image
with shape (height, width, #channels)"""
"""
Perspective transformation class for image
with shape (height, width, #channels)
"""

def load_image(self, img_path, shape=None):
""" """
img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
if shape is not None:
img = cv2.resize(img, shape)
return img

def __init__(self, image_path, shape):
""" """
self.image_path = image_path
self.image = self.load_image(image_path, shape)

self.height = self.image.shape[0]
self.width = self.image.shape[1]
self.num_channels = self.image.shape[2]

def get_rotation_args(self, rotation: str, ang: int):
"""
Generates the arguments used for 'rotate_along_axis'
This takes a rotation-mode 'rotation' and an angle
named 'ang' in (0 - rot_range), and is called from a loop.
"""
if rotation in ["y"]:
# y-axis from 0-360 degree, 5 pixel shift in +X
rotargs = dict(phi=ang, dx=5)
elif rotation in ["x"]:
rotargs = dict(gamma=ang)
elif rotation in ["s", "swivel"]:
# yz-axis from 0 to 360 degree
rotargs = dict(phi=ang, gamma=ang)
elif rotation in ["jitter", "j"]:
rotargs = dict(
dx=random.choice([5, 0, 10]),
phi=random.choice([ang, -ang]),
gamma=random.choice([0, ang, -ang]),
)
elif rotation in ["wobble", "w"]:
rotargs = dict(
dx=random.choice([0, 10, 30]),
dy=random.choice([25, 0, 10]),
phi=random.choice([ang, -ang, math.sin(ang)]),
gamma=random.choice([ang, -ang]),
)
elif rotation in ["f", "flip"]:
rotargs = dict(dx=ang, dy=-ang, phi=math.tan(ang), gamma=ang)
elif rotation.startswith("q"):
rotargs = dict(
dx=random.choice([0, 5, 10]),
dy=random.choice([25, 0, 10]),
phi=random.choice([ang, -ang, math.sin(ang)]),
gamma=random.choice([ang, -ang]),
)
elif rotation.startswith("exit"):
direction = rotation.split("-")[1]
if direction == "ul":
rotargs = dict(
dx=-ang,
dy=-ang,
)
elif direction == "ur":
rotargs = dict(
dx=ang,
dy=-ang,
)
elif direction == "lr":
rotargs = dict(
dx=ang,
dy=ang,
)
elif direction == "ll":
rotargs = dict(
dx=-ang,
dy=ang,
)
else:
raise ValueError(f"unknown rotation: {rotation}")
rotargs.update(phi=math.tan(ang), gamma=math.tan(ang))
else:
raise ValueError(f"Not sure how to perform rotation {rotation}")
return rotargs

@staticmethod
def save_image(img_path, img):
"""
Saves an output image
This is usually one that's resulted from a rotation, i.e a single frame in a larger animation
"""
cv2.imwrite(img_path, img)

def rotate_along_axis(self, theta=0, phi=0, gamma=0, dx=0, dy=0, dz=0):
"""Wrapper for rotating a image"""
"""Returns the new image that results from rotating self.image"""

# Get radius of rotation along 3 axes
rtheta, rphi, rgamma = get_rad(theta, phi, gamma)
Expand All @@ -78,13 +153,10 @@ def rotate_along_axis(self, theta=0, phi=0, gamma=0, dx=0, dy=0, dz=0):

# Get projection matrix
mat = self.get_M(rtheta, rphi, rgamma, dx, dy, dz)

return cv2.warpPerspective(self.image.copy(), mat, (self.width, self.height))

""" Get Perspective Projection Matrix """

def get_M(self, theta, phi, gamma, dx, dy, dz):

"""Get Perspective Projection Matrix"""
w = self.width
h = self.height
f = self.focal
Expand Down
Binary file modified img/demo.chafa.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading