homa 0.21__tar.gz → 0.23__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of homa might be problematic. Click here for more details.
- homa-0.23/PKG-INFO +110 -0
- homa-0.23/README.md +102 -0
- homa-0.23/homa/__init__.py +9 -0
- homa-0.23/homa/camera.py +19 -0
- {homa-0.21 → homa-0.23}/homa/classes/Repository.py +2 -7
- homa-0.23/homa/events.py +70 -0
- homa-0.23/homa/filters.py +41 -0
- homa-0.23/homa/helpers/__init__.py +0 -0
- homa-0.23/homa/helpers/alias.py +14 -0
- homa-0.23/homa/helpers/environment.py +5 -0
- homa-0.23/homa/helpers/kernel.py +15 -0
- homa-0.23/homa/helpers.py +0 -0
- homa-0.23/homa/main.py +75 -0
- homa-0.23/homa/orientation.py +38 -0
- homa-0.23/homa/shapes.py +9 -0
- homa-0.23/homa/spaces.py +20 -0
- homa-0.23/homa.egg-info/PKG-INFO +110 -0
- {homa-0.21 → homa-0.23}/homa.egg-info/SOURCES.txt +13 -1
- homa-0.23/homa.egg-info/top_level.txt +2 -0
- homa-0.23/tests/__init__.py +0 -0
- homa-0.23/tests/test_images.py +27 -0
- homa-0.21/PKG-INFO +0 -16
- homa-0.21/README.md +0 -8
- homa-0.21/homa/__init__.py +0 -1
- homa-0.21/homa/helpers.py +0 -16
- homa-0.21/homa/main.py +0 -109
- homa-0.21/homa.egg-info/PKG-INFO +0 -16
- homa-0.21/homa.egg-info/top_level.txt +0 -1
- {homa-0.21 → homa-0.23}/LICENSE +0 -0
- {homa-0.21 → homa-0.23}/homa/classes/Collection.py +0 -0
- {homa-0.21 → homa-0.23}/homa/classes/Logger.py +0 -0
- {homa-0.21 → homa-0.23}/homa/classes/__init__.py +0 -0
- {homa-0.21 → homa-0.23}/homa/constants.py +0 -0
- {homa-0.21 → homa-0.23}/homa.egg-info/dependency_links.txt +0 -0
- {homa-0.21 → homa-0.23}/homa.egg-info/requires.txt +0 -0
- {homa-0.21 → homa-0.23}/setup.cfg +0 -0
- {homa-0.21 → homa-0.23}/setup.py +0 -0
homa-0.23/PKG-INFO
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: homa
|
|
3
|
+
Version: 0.23
|
|
4
|
+
Maintainer: Taha Shieenavaz
|
|
5
|
+
Maintainer-email: tahashieenavaz@gmail.com
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<img
|
|
11
|
+
src="https://raw.githubusercontent.com/tahashieenavaz/homa/main/art/homa.svg"
|
|
12
|
+
width=500
|
|
13
|
+
/>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<hr />
|
|
17
|
+
|
|
18
|
+
Homa is an easy way to start learning Computer Vision with OpenCV.
|
|
19
|
+
|
|
20
|
+
## Loading Images
|
|
21
|
+
|
|
22
|
+
Images could be loaded with the `image` helper, that accepts the file name and a key for the repository.
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from homa import *
|
|
26
|
+
|
|
27
|
+
image("horse.jpg", "horse")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Alternatively, following code will load the file into the repository with a key of everything before the last in the filename.
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from homa import *
|
|
34
|
+
|
|
35
|
+
image("horse.jpg") # stored as "horse"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Smoothing
|
|
39
|
+
|
|
40
|
+
### Blur
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from homa import *
|
|
44
|
+
|
|
45
|
+
image("horse.jpg")
|
|
46
|
+
|
|
47
|
+
blur("horse", 7) # rewrites "horse" key
|
|
48
|
+
blur("horse", (7, 19)) # rewrites "horse" key
|
|
49
|
+
blur("horse", 9, "blurred horse") # as a new key in the repository
|
|
50
|
+
|
|
51
|
+
showWait("blurred horse")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Gaussian Blur
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from homa import *
|
|
58
|
+
|
|
59
|
+
image("horse.jpg")
|
|
60
|
+
|
|
61
|
+
gaussian("horse", 7) # rewrites "horse" key
|
|
62
|
+
gaussian("horse", (7, 19)) # rewrites "horse" key
|
|
63
|
+
gaussian("horse", 9, "gaussian blurred horse") # as a new key in the repository
|
|
64
|
+
|
|
65
|
+
showWait("gaussian blurred horse")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Stacking
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from homa import *
|
|
72
|
+
|
|
73
|
+
image("horse.jpg")
|
|
74
|
+
blur("horse", 9, "blurred horse")
|
|
75
|
+
|
|
76
|
+
show(
|
|
77
|
+
vstack("horse", "blurred horse"),
|
|
78
|
+
window="Vstacked"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
showWait(
|
|
82
|
+
hstack("horse", "blurred horse"),
|
|
83
|
+
window="Hstacked"
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Camera
|
|
88
|
+
|
|
89
|
+
Camera frames could be access from the repository with a key of `camera`.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from homa import *
|
|
93
|
+
|
|
94
|
+
for _ in camera():
|
|
95
|
+
show("camera")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You can simply combine camera frames with the supported effects.
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from homa import *
|
|
102
|
+
|
|
103
|
+
for _ in camera():
|
|
104
|
+
blur("camera", 13, "blurred camera")
|
|
105
|
+
|
|
106
|
+
show(
|
|
107
|
+
vstack("camera", "blurred camera"),
|
|
108
|
+
window="Camera Effect"
|
|
109
|
+
)
|
|
110
|
+
```
|
homa-0.23/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img
|
|
3
|
+
src="https://raw.githubusercontent.com/tahashieenavaz/homa/main/art/homa.svg"
|
|
4
|
+
width=500
|
|
5
|
+
/>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<hr />
|
|
9
|
+
|
|
10
|
+
Homa is an easy way to start learning Computer Vision with OpenCV.
|
|
11
|
+
|
|
12
|
+
## Loading Images
|
|
13
|
+
|
|
14
|
+
Images could be loaded with the `image` helper, that accepts the file name and a key for the repository.
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from homa import *
|
|
18
|
+
|
|
19
|
+
image("horse.jpg", "horse")
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Alternatively, following code will load the file into the repository with a key of everything before the last in the filename.
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from homa import *
|
|
26
|
+
|
|
27
|
+
image("horse.jpg") # stored as "horse"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Smoothing
|
|
31
|
+
|
|
32
|
+
### Blur
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from homa import *
|
|
36
|
+
|
|
37
|
+
image("horse.jpg")
|
|
38
|
+
|
|
39
|
+
blur("horse", 7) # rewrites "horse" key
|
|
40
|
+
blur("horse", (7, 19)) # rewrites "horse" key
|
|
41
|
+
blur("horse", 9, "blurred horse") # as a new key in the repository
|
|
42
|
+
|
|
43
|
+
showWait("blurred horse")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Gaussian Blur
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from homa import *
|
|
50
|
+
|
|
51
|
+
image("horse.jpg")
|
|
52
|
+
|
|
53
|
+
gaussian("horse", 7) # rewrites "horse" key
|
|
54
|
+
gaussian("horse", (7, 19)) # rewrites "horse" key
|
|
55
|
+
gaussian("horse", 9, "gaussian blurred horse") # as a new key in the repository
|
|
56
|
+
|
|
57
|
+
showWait("gaussian blurred horse")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Stacking
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from homa import *
|
|
64
|
+
|
|
65
|
+
image("horse.jpg")
|
|
66
|
+
blur("horse", 9, "blurred horse")
|
|
67
|
+
|
|
68
|
+
show(
|
|
69
|
+
vstack("horse", "blurred horse"),
|
|
70
|
+
window="Vstacked"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
showWait(
|
|
74
|
+
hstack("horse", "blurred horse"),
|
|
75
|
+
window="Hstacked"
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Camera
|
|
80
|
+
|
|
81
|
+
Camera frames could be access from the repository with a key of `camera`.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from homa import *
|
|
85
|
+
|
|
86
|
+
for _ in camera():
|
|
87
|
+
show("camera")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
You can simply combine camera frames with the supported effects.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from homa import *
|
|
94
|
+
|
|
95
|
+
for _ in camera():
|
|
96
|
+
blur("camera", 13, "blurred camera")
|
|
97
|
+
|
|
98
|
+
show(
|
|
99
|
+
vstack("camera", "blurred camera"),
|
|
100
|
+
window="Camera Effect"
|
|
101
|
+
)
|
|
102
|
+
```
|
homa-0.23/homa/camera.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
from .classes.Repository import Repository
|
|
3
|
+
from typing import Iterator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def camera(delay: int = 10, exit_on: str = "q") -> Iterator[int]:
|
|
7
|
+
pressed_key = None
|
|
8
|
+
capture = cv2.VideoCapture(0)
|
|
9
|
+
frame_number = 0
|
|
10
|
+
while pressed_key != ord(exit_on):
|
|
11
|
+
_, frame = capture.read()
|
|
12
|
+
Repository.images["camera"] = frame
|
|
13
|
+
|
|
14
|
+
frame_number += 1
|
|
15
|
+
yield frame_number
|
|
16
|
+
|
|
17
|
+
pressed_key = cv2.waitKey(delay)
|
|
18
|
+
|
|
19
|
+
capture.release()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from ..helpers import is_colab
|
|
1
|
+
from ..helpers.environment import is_colab
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class RepositoryWrapper:
|
|
@@ -8,8 +8,7 @@ class RepositoryWrapper:
|
|
|
8
8
|
|
|
9
9
|
self.directory = "./"
|
|
10
10
|
self.images = {}
|
|
11
|
-
self.
|
|
12
|
-
self.window_counter = 0
|
|
11
|
+
self.windows = {}
|
|
13
12
|
|
|
14
13
|
if is_colab():
|
|
15
14
|
from google.colab.patches import cv2_imshow as imshow
|
|
@@ -24,9 +23,5 @@ class RepositoryWrapper:
|
|
|
24
23
|
|
|
25
24
|
self.imshow = final_imshow
|
|
26
25
|
|
|
27
|
-
def get_counter(self):
|
|
28
|
-
self.window_counter += 1
|
|
29
|
-
return self.window_counter
|
|
30
|
-
|
|
31
26
|
|
|
32
27
|
Repository = RepositoryWrapper()
|
homa-0.23/homa/events.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# enum MouseEventTypes
|
|
2
|
+
# {
|
|
3
|
+
# EVENT_MOUSEMOVE = 0,
|
|
4
|
+
# EVENT_LBUTTONDOWN = 1,
|
|
5
|
+
# EVENT_RBUTTONDOWN = 2,
|
|
6
|
+
# EVENT_MBUTTONDOWN = 3,
|
|
7
|
+
# EVENT_LBUTTONUP = 4,
|
|
8
|
+
# EVENT_RBUTTONUP = 5,
|
|
9
|
+
# EVENT_MBUTTONUP = 6,
|
|
10
|
+
# EVENT_LBUTTONDBLCLK = 7,
|
|
11
|
+
# EVENT_RBUTTONDBLCLK = 8,
|
|
12
|
+
# EVENT_MBUTTONDBLCLK = 9,
|
|
13
|
+
# EVENT_MOUSEWHEEL = 10,
|
|
14
|
+
# EVENT_MOUSEHWHEEL = 11,
|
|
15
|
+
# };
|
|
16
|
+
import cv2
|
|
17
|
+
from .main import win
|
|
18
|
+
from inspect import signature
|
|
19
|
+
|
|
20
|
+
event_map = {
|
|
21
|
+
"click": cv2.EVENT_LBUTTONDOWN,
|
|
22
|
+
"rclick": cv2.EVENT_RBUTTONDOWN,
|
|
23
|
+
"mclick": cv2.EVENT_MBUTTONDOWN,
|
|
24
|
+
"mouseup": cv2.EVENT_LBUTTONUP,
|
|
25
|
+
"rmouseup": cv2.EVENT_RBUTTONUP,
|
|
26
|
+
"dblclick": cv2.EVENT_LBUTTONDBLCLK,
|
|
27
|
+
"rdblclick": cv2.EVENT_RBUTTONDBLCLK,
|
|
28
|
+
"move": cv2.EVENT_MOUSEMOVE
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def create_wrapper_function(event_name: str, handler: callable):
|
|
33
|
+
def wrapper_function(event, x, y, flags, param):
|
|
34
|
+
if event != event_map[event_name]:
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
argument_count = len(signature(handler).parameters)
|
|
38
|
+
if argument_count == 2:
|
|
39
|
+
handler(x, y)
|
|
40
|
+
elif argument_count == 3:
|
|
41
|
+
handler(x, y, flags)
|
|
42
|
+
elif argument_count == 4:
|
|
43
|
+
handler(x, y, flags, param)
|
|
44
|
+
|
|
45
|
+
return wrapper_function
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def onClick(key: str, handler: callable):
|
|
49
|
+
win(key)
|
|
50
|
+
cv2.setMouseCallback(key, create_wrapper_function("click", handler))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def onRightClick(key: str, handler: callable):
|
|
54
|
+
win(key)
|
|
55
|
+
cv2.setMouseCallback(key, create_wrapper_function("rclick", handler))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def onMouseUp(key: str, handler: callable):
|
|
59
|
+
win(key)
|
|
60
|
+
cv2.setMouseCallback(key, create_wrapper_function("mouseup", handler))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def onMove(key: str, handler: callable):
|
|
64
|
+
win(key)
|
|
65
|
+
cv2.setMouseCallback(key, create_wrapper_function("mousemove", handler))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def onDoubleClick(key: str, handler: callable):
|
|
69
|
+
win(key)
|
|
70
|
+
cv2.setMouseCallback(key, create_wrapper_function("dblclick", handler))
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
from .classes.Repository import Repository
|
|
3
|
+
from .helpers.kernel import create_kernel
|
|
4
|
+
import cv2
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def blur(key: str, kernel: int | List[int] = (7, 7), new_key: str | None = None) -> None:
|
|
8
|
+
if new_key is None:
|
|
9
|
+
new_key = key
|
|
10
|
+
|
|
11
|
+
Repository.images[new_key] = cv2.blur(
|
|
12
|
+
Repository.images[key],
|
|
13
|
+
create_kernel(kernel)
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def median(key: str, kernel: int | List[int] = (7, 7), new_key: str | None = None) -> None:
|
|
18
|
+
if new_key is None:
|
|
19
|
+
new_key = key
|
|
20
|
+
|
|
21
|
+
Repository.images[new_key] = cv2.medianBlur(
|
|
22
|
+
Repository.images[key],
|
|
23
|
+
create_kernel(kernel)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def sigma(x: float = 0, y: float = 0) -> None:
|
|
28
|
+
Repository.sigmaX = x
|
|
29
|
+
Repository.sigmaY = y
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def gaussian(key: str, kernel: None | List[int] = None, new_key: str | None = None) -> None:
|
|
33
|
+
if new_key is None:
|
|
34
|
+
new_key = key
|
|
35
|
+
|
|
36
|
+
Repository.images[new_key] = cv2.GaussianBlur(
|
|
37
|
+
Repository.images[key],
|
|
38
|
+
create_kernel(kernel),
|
|
39
|
+
sigmaX=Repository.sigmaX,
|
|
40
|
+
sigmaY=Repository.sigmaY
|
|
41
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from ..classes.Repository import Repository
|
|
2
|
+
from ..classes import Collection
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def repo(key: str|None = None):
|
|
7
|
+
if key is None:
|
|
8
|
+
return Repository.images
|
|
9
|
+
|
|
10
|
+
return Repository.images[key]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def collection(items: List[any]):
|
|
14
|
+
return Collection(items)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from typing import Tuple
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def create_kernel(value: int | Tuple[int, int]) -> Tuple[int, int]:
|
|
5
|
+
if isinstance(value, tuple):
|
|
6
|
+
x, y = value
|
|
7
|
+
|
|
8
|
+
x = x - 1 if x % 2 == 0 else x
|
|
9
|
+
y = y - 1 if y % 2 == 0 else y
|
|
10
|
+
|
|
11
|
+
return (x, y)
|
|
12
|
+
|
|
13
|
+
value = value - 1 if value % 2 == 0 else value
|
|
14
|
+
|
|
15
|
+
return (value, value)
|
|
File without changes
|
homa-0.23/homa/main.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
from .classes.Logger import Logger
|
|
3
|
+
from .classes.Repository import Repository
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def destroy(key: str | None = None) -> None:
|
|
7
|
+
if key is not None:
|
|
8
|
+
cv2.destroyWindow(key)
|
|
9
|
+
return
|
|
10
|
+
|
|
11
|
+
cv2.destroyAllWindows()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def win(key: str):
|
|
15
|
+
cv2.namedWindow(key)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def path(directory: str) -> None:
|
|
19
|
+
Repository.directory = directory
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def write(key: str, filename: str) -> None:
|
|
23
|
+
cv2.imwrite(
|
|
24
|
+
filename=filename,
|
|
25
|
+
img=Repository.images[key]
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def save(*args, **kwargs) -> None:
|
|
30
|
+
write(args, kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def image(filename: str, key: str | None = None, color: bool = True) -> None:
|
|
34
|
+
# TODO: add no extension in the file
|
|
35
|
+
if key is None:
|
|
36
|
+
key = filename.split(".")[0]
|
|
37
|
+
|
|
38
|
+
Repository.images[key] = cv2.imread(filename, int(color))
|
|
39
|
+
return Repository.images[key]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def wait(delay=0):
|
|
43
|
+
cv2.waitKey(delay)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def showWait(*args, **kwargs):
|
|
47
|
+
kwargs["wait"] = True
|
|
48
|
+
show(*args, **kwargs)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def show(key: any = None, wait: bool = False, window: str = "Homa Window") -> None:
|
|
52
|
+
# TODO: add functionality to distinguish between camera and images
|
|
53
|
+
|
|
54
|
+
if key is not None and not isinstance(key, str):
|
|
55
|
+
Repository.imshow(window, key)
|
|
56
|
+
Repository.windows[key] = window
|
|
57
|
+
|
|
58
|
+
elif key is None:
|
|
59
|
+
for key, image in Repository.images.items():
|
|
60
|
+
Repository.imshow(key, image)
|
|
61
|
+
Repository.windows[key] = key
|
|
62
|
+
|
|
63
|
+
elif key is not None:
|
|
64
|
+
if key in Repository.images:
|
|
65
|
+
Repository.imshow(key, Repository.images[key])
|
|
66
|
+
Repository.windows[key] = key
|
|
67
|
+
else:
|
|
68
|
+
Logger.danger(f"No image found with key {key}")
|
|
69
|
+
|
|
70
|
+
if wait:
|
|
71
|
+
cv2.waitKey(0)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def refresh(key: str) -> None:
|
|
75
|
+
cv2.imshow(Repository.windows[key], Repository.images[key])
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from .classes.Repository import Repository
|
|
2
|
+
from .helpers.alias import collection
|
|
3
|
+
import numpy
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def stack(*keys, **settings):
|
|
7
|
+
default_settings = {
|
|
8
|
+
"axis": 1,
|
|
9
|
+
"new_key": None
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
settings = {
|
|
13
|
+
**default_settings,
|
|
14
|
+
**settings
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if all(isinstance(item, str) for item in keys):
|
|
18
|
+
keys = collection(keys).map(lambda key: Repository.images[key])
|
|
19
|
+
|
|
20
|
+
stacked_image = numpy.concatenate(
|
|
21
|
+
keys,
|
|
22
|
+
axis=settings["axis"]
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if settings["new_key"] is not None:
|
|
26
|
+
Repository.images[settings["new_key"]] = stacked_image
|
|
27
|
+
|
|
28
|
+
return stacked_image
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def vstack(*keys, **settings):
|
|
32
|
+
settings["axis"] = 1
|
|
33
|
+
return stack(*keys, **settings)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def hstack(*keys, **settings):
|
|
37
|
+
settings["axis"] = 0
|
|
38
|
+
return stack(*keys, **settings)
|
homa-0.23/homa/shapes.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
from .main import refresh
|
|
3
|
+
from .helpers.alias import repo
|
|
4
|
+
from .classes.Repository import Repository
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def circle(key: str, x: int = 0, y: int = 0, r: int = 1, color=(0, 0, 255), thickness: int = 1):
|
|
8
|
+
cv2.circle(repo(key), (x, y), r, color, thickness)
|
|
9
|
+
refresh(key)
|
homa-0.23/homa/spaces.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from typing import Tuple
|
|
2
|
+
from .helpers.alias import repo
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def rgb(key: str) -> Tuple[int, int, int]:
|
|
6
|
+
image = repo(key)
|
|
7
|
+
|
|
8
|
+
if image.shape[2] == 3:
|
|
9
|
+
# found three channels in stored image
|
|
10
|
+
# meaning that it has been loaded as a color image
|
|
11
|
+
|
|
12
|
+
b = image[:, :, 0]
|
|
13
|
+
g = image[:, :, 0]
|
|
14
|
+
r = image[:, :, 0]
|
|
15
|
+
|
|
16
|
+
return (r, g, b)
|
|
17
|
+
|
|
18
|
+
if image.shape[2] == 1:
|
|
19
|
+
gray = image[:, :, 0]
|
|
20
|
+
return (gray, gray, gray)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: homa
|
|
3
|
+
Version: 0.23
|
|
4
|
+
Maintainer: Taha Shieenavaz
|
|
5
|
+
Maintainer-email: tahashieenavaz@gmail.com
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<img
|
|
11
|
+
src="https://raw.githubusercontent.com/tahashieenavaz/homa/main/art/homa.svg"
|
|
12
|
+
width=500
|
|
13
|
+
/>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<hr />
|
|
17
|
+
|
|
18
|
+
Homa is an easy way to start learning Computer Vision with OpenCV.
|
|
19
|
+
|
|
20
|
+
## Loading Images
|
|
21
|
+
|
|
22
|
+
Images could be loaded with the `image` helper, that accepts the file name and a key for the repository.
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from homa import *
|
|
26
|
+
|
|
27
|
+
image("horse.jpg", "horse")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Alternatively, following code will load the file into the repository with a key of everything before the last in the filename.
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from homa import *
|
|
34
|
+
|
|
35
|
+
image("horse.jpg") # stored as "horse"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Smoothing
|
|
39
|
+
|
|
40
|
+
### Blur
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from homa import *
|
|
44
|
+
|
|
45
|
+
image("horse.jpg")
|
|
46
|
+
|
|
47
|
+
blur("horse", 7) # rewrites "horse" key
|
|
48
|
+
blur("horse", (7, 19)) # rewrites "horse" key
|
|
49
|
+
blur("horse", 9, "blurred horse") # as a new key in the repository
|
|
50
|
+
|
|
51
|
+
showWait("blurred horse")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Gaussian Blur
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from homa import *
|
|
58
|
+
|
|
59
|
+
image("horse.jpg")
|
|
60
|
+
|
|
61
|
+
gaussian("horse", 7) # rewrites "horse" key
|
|
62
|
+
gaussian("horse", (7, 19)) # rewrites "horse" key
|
|
63
|
+
gaussian("horse", 9, "gaussian blurred horse") # as a new key in the repository
|
|
64
|
+
|
|
65
|
+
showWait("gaussian blurred horse")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Stacking
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from homa import *
|
|
72
|
+
|
|
73
|
+
image("horse.jpg")
|
|
74
|
+
blur("horse", 9, "blurred horse")
|
|
75
|
+
|
|
76
|
+
show(
|
|
77
|
+
vstack("horse", "blurred horse"),
|
|
78
|
+
window="Vstacked"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
showWait(
|
|
82
|
+
hstack("horse", "blurred horse"),
|
|
83
|
+
window="Hstacked"
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Camera
|
|
88
|
+
|
|
89
|
+
Camera frames could be access from the repository with a key of `camera`.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from homa import *
|
|
93
|
+
|
|
94
|
+
for _ in camera():
|
|
95
|
+
show("camera")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You can simply combine camera frames with the supported effects.
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from homa import *
|
|
102
|
+
|
|
103
|
+
for _ in camera():
|
|
104
|
+
blur("camera", 13, "blurred camera")
|
|
105
|
+
|
|
106
|
+
show(
|
|
107
|
+
vstack("camera", "blurred camera"),
|
|
108
|
+
window="Camera Effect"
|
|
109
|
+
)
|
|
110
|
+
```
|
|
@@ -2,9 +2,15 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
setup.py
|
|
4
4
|
homa/__init__.py
|
|
5
|
+
homa/camera.py
|
|
5
6
|
homa/constants.py
|
|
7
|
+
homa/events.py
|
|
8
|
+
homa/filters.py
|
|
6
9
|
homa/helpers.py
|
|
7
10
|
homa/main.py
|
|
11
|
+
homa/orientation.py
|
|
12
|
+
homa/shapes.py
|
|
13
|
+
homa/spaces.py
|
|
8
14
|
homa.egg-info/PKG-INFO
|
|
9
15
|
homa.egg-info/SOURCES.txt
|
|
10
16
|
homa.egg-info/dependency_links.txt
|
|
@@ -13,4 +19,10 @@ homa.egg-info/top_level.txt
|
|
|
13
19
|
homa/classes/Collection.py
|
|
14
20
|
homa/classes/Logger.py
|
|
15
21
|
homa/classes/Repository.py
|
|
16
|
-
homa/classes/__init__.py
|
|
22
|
+
homa/classes/__init__.py
|
|
23
|
+
homa/helpers/__init__.py
|
|
24
|
+
homa/helpers/alias.py
|
|
25
|
+
homa/helpers/environment.py
|
|
26
|
+
homa/helpers/kernel.py
|
|
27
|
+
tests/__init__.py
|
|
28
|
+
tests/test_images.py
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from homa import *
|
|
2
|
+
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LoadingImagesTest(unittest.TestCase):
|
|
7
|
+
def setUp(self):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
def test_can_load_images_into_repository(self):
|
|
11
|
+
image("italy.jpg", "italy")
|
|
12
|
+
self.assertIn("italy", repo())
|
|
13
|
+
|
|
14
|
+
def test_it_does_not_load_extra_images(self):
|
|
15
|
+
image("italy.jpg", "italy")
|
|
16
|
+
self.assertEqual(len(repo()), 1)
|
|
17
|
+
|
|
18
|
+
image("italy.jpg", "italy again")
|
|
19
|
+
self.assertEqual(len(repo()), 2)
|
|
20
|
+
|
|
21
|
+
def test_it_can_load_images_as_black_and_white(self):
|
|
22
|
+
image("italy.jpg", "italy", color=False)
|
|
23
|
+
self.assertEqual(len(repo("italy").shape), 2)
|
|
24
|
+
|
|
25
|
+
def test_it_can_load_images_as_colorful(self):
|
|
26
|
+
image("italy.jpg", "italy", color=True)
|
|
27
|
+
self.assertEqual(len(repo("italy").shape), 3)
|
homa-0.21/PKG-INFO
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: homa
|
|
3
|
-
Version: 0.21
|
|
4
|
-
Maintainer: Taha Shieenavaz
|
|
5
|
-
Maintainer-email: tahashieenavaz@gmail.com
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
License-File: LICENSE
|
|
8
|
-
|
|
9
|
-
<p align="center">
|
|
10
|
-
<img
|
|
11
|
-
src="https://raw.githubusercontent.com/tahashieenavaz/homa/main/art/homa.svg"
|
|
12
|
-
width=400
|
|
13
|
-
/>
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<hr />
|
homa-0.21/README.md
DELETED
homa-0.21/homa/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .main import *
|
homa-0.21/homa/helpers.py
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from typing import List
|
|
3
|
-
from .classes.Collection import Collection
|
|
4
|
-
from .classes.Logger import Logger
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def is_colab() -> bool:
|
|
8
|
-
return 'google.colab' in sys.modules
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def collection(items: List[any]):
|
|
12
|
-
return Collection(items)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def danger(message: str) -> None:
|
|
16
|
-
Logger.danger(message)
|
homa-0.21/homa/main.py
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import cv2
|
|
2
|
-
import numpy
|
|
3
|
-
from typing import List
|
|
4
|
-
from .helpers import collection
|
|
5
|
-
from .helpers import danger
|
|
6
|
-
from .helpers import is_colab
|
|
7
|
-
|
|
8
|
-
from .classes.Repository import Repository
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def path(directory: str) -> None:
|
|
12
|
-
Repository.directory = directory
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def write(key: str, filename: str) -> None:
|
|
16
|
-
cv2.imwrite(
|
|
17
|
-
filename=filename,
|
|
18
|
-
img=Repository.images[key]
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def save(key: str, filename: str) -> None:
|
|
23
|
-
write(key, filename)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def image(filename: str, key: str | None = None, color: bool = True) -> None:
|
|
27
|
-
# TODO: add no extension in the file
|
|
28
|
-
if key is None:
|
|
29
|
-
key = filename
|
|
30
|
-
|
|
31
|
-
Repository.images[key] = cv2.imread(filename, int(color))
|
|
32
|
-
return Repository.images[key]
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def show(key: any = None) -> None:
|
|
36
|
-
# TODO: add functionality to distinguish between camera and images
|
|
37
|
-
|
|
38
|
-
if key is not None and not isinstance(key, str):
|
|
39
|
-
Repository.imshow(f"Window #{Repository.get_counter()}", key)
|
|
40
|
-
|
|
41
|
-
elif key is None:
|
|
42
|
-
for key, image in Repository.images.items():
|
|
43
|
-
Repository.imshow(key, image)
|
|
44
|
-
|
|
45
|
-
elif key is not None:
|
|
46
|
-
if key in Repository.images:
|
|
47
|
-
Repository.imshow(key, Repository.images[key])
|
|
48
|
-
else:
|
|
49
|
-
danger(f"No image found with key {key}")
|
|
50
|
-
|
|
51
|
-
cv2.waitKey(0)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def camera():
|
|
55
|
-
capture = cv2.VideoCapture()
|
|
56
|
-
_, frame = capture.read()
|
|
57
|
-
Repository.camera_frame = frame
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def stack(keys: List[str], new_key: str, axis: int):
|
|
61
|
-
Repository.images[new_key] = numpy.concatenate(
|
|
62
|
-
collection(keys).map(lambda key: Repository.images[key]),
|
|
63
|
-
axis=axis
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def vstack(keys: List[str], new_key: str) -> None:
|
|
68
|
-
stack(keys, new_key, 1)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def hstack(keys: List[str] | str, new_key: str | None = None):
|
|
72
|
-
if isinstance(keys, str) and new_key is None:
|
|
73
|
-
hstack([keys], keys)
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
stack(keys, new_key, 0)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def blur(key: str, kernel: int | List[int] = (7, 7), new_key: str | None = None):
|
|
80
|
-
if new_key is None:
|
|
81
|
-
new_key = key
|
|
82
|
-
|
|
83
|
-
if isinstance(kernel, int):
|
|
84
|
-
kernel = (kernel, kernel)
|
|
85
|
-
|
|
86
|
-
Repository.images[new_key] = cv2.blur(
|
|
87
|
-
Repository.images[key],
|
|
88
|
-
kernel
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def sigma(x: float = 0, y: float = 0):
|
|
93
|
-
Repository.sigmaX = x
|
|
94
|
-
Repository.sigmaY = y
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def gaussian(key: str, kernel: None | List[int] = None, new_key: str | None = None):
|
|
98
|
-
if new_key is None:
|
|
99
|
-
new_key = key
|
|
100
|
-
|
|
101
|
-
if isinstance(kernel, int):
|
|
102
|
-
kernel = (kernel, kernel)
|
|
103
|
-
|
|
104
|
-
Repository.images[new_key] = cv2.GaussianBlur(
|
|
105
|
-
Repository.images[key],
|
|
106
|
-
kernel,
|
|
107
|
-
sigmaX=Repository.sigmaX,
|
|
108
|
-
sigmaY=Repository.sigmaY
|
|
109
|
-
)
|
homa-0.21/homa.egg-info/PKG-INFO
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: homa
|
|
3
|
-
Version: 0.21
|
|
4
|
-
Maintainer: Taha Shieenavaz
|
|
5
|
-
Maintainer-email: tahashieenavaz@gmail.com
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
License-File: LICENSE
|
|
8
|
-
|
|
9
|
-
<p align="center">
|
|
10
|
-
<img
|
|
11
|
-
src="https://raw.githubusercontent.com/tahashieenavaz/homa/main/art/homa.svg"
|
|
12
|
-
width=400
|
|
13
|
-
/>
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<hr />
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
homa
|
{homa-0.21 → homa-0.23}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{homa-0.21 → homa-0.23}/setup.py
RENAMED
|
File without changes
|