Skip to content

Commit aada297

Browse files
authored
Merge pull request #37 from fernaper/development
v2.0.2
2 parents 6ef796f + bbeac23 commit aada297

File tree

15 files changed

+331
-198
lines changed

15 files changed

+331
-198
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Images and videos
2+
*.jpg
3+
*.jpeg
4+
*.png
5+
*.mp4
6+
17
# Byte-compiled / optimized / DLL files
28
__pycache__/
39
*.py[cod]

README.md

Lines changed: 58 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# opencv-draw-tools
1+
# cv2_tools
22
Library to help the drawing process with OpenCV. Thought to add labels to the images. Classification of images, etc.
33

44
![image](https://user-images.githubusercontent.com/18369529/53686731-3dba0500-3d2b-11e9-95e5-e4517c013d14.png)
@@ -24,21 +24,70 @@ Finally you can install the library with:
2424

2525
When you install `opencv-draw-tools`, it will automatically download `numpy` but not opencv becouse in some cases you will need another version.
2626

27-
## Usage
28-
29-
### Test
27+
## Test
3028

3129
```
32-
import opencv_draw_tools as cv2_tools
30+
import cv2_tools
3331
3432
print('Name: {}\nVersion:{}\nHelp:{}'.format(cv2_tools.name,cv2_tools.__version__,cv2_tools.help))
35-
cv2_tools.webcam_test()
33+
webcam_test()
34+
```
35+
36+
## Ussage and Important classes
37+
38+
### ManagerCV2
39+
40+
```
41+
from cv2_tools.Management import ManagerCV2
42+
```
43+
44+
If you want to work with video or stream, this class will help you mantain your code cleaner while you get more features.
45+
46+
For example:
47+
- Open a a stream (your webcam).
48+
- Reproduce it on real time with max FPS equals to 24.
49+
- Press `esc` to finish the program.
50+
- At the end print average FPS.
51+
52+
```
53+
from cv2_tools.Managment import ManagerCV2
54+
import cv2
55+
56+
# keystroke=27 is the button `esc`
57+
manager_cv2 = ManagerCV2(cv2.VideoCapture(0), is_stream=True, keystroke=27, wait_key=1, fps_limit=60)
58+
59+
# This for will manage file descriptor for you
60+
for frame in manager_cv2:
61+
cv2.imshow('Example easy manager', frame)
62+
cv2.destroyAllWindows()
63+
print(manager_cv2.get_fps())
64+
```
65+
66+
If you want to use another button and you don't know the ID, you can check easily using the following code:
67+
68+
```
69+
from cv2_tools.Managment import ManagerCV2
70+
import cv2
71+
72+
# keystroke=27 is the button `esc`
73+
manager_cv2 = ManagerCV2(cv2.VideoCapture(0), is_stream=True, keystroke=27, wait_key=1, fps_limit=60)
74+
75+
# This for will manage file descriptor for you
76+
for frame in manager_cv2:
77+
# Each time you press a button, you will get its id in your terminal
78+
last_keystroke = manager_cv2.get_last_keystroke()
79+
if last_keystroke != -1:
80+
print(last_keystroke)
81+
cv2.imshow('Easy button checker', frame)
82+
cv2.destroyAllWindows()
3683
```
37-
### Oriented Object Programming method
84+
85+
### SelectorCV2
3886

3987
Firstly create a SelectorCV2 object. You can pass it optional parameters to configure the output.
4088
```
41-
selector = cv2_tools.SelectorCV2(color=(200,90,0), filled=True)
89+
from cv2_tools.Selection import SelectorCV2
90+
selector = SelectorCV2(color=(200,90,0), filled=True)
4291
```
4392

4493
Also you can configure it later using the method (all optional parameters):
@@ -80,70 +129,4 @@ selector.set_range_valid_rectangles( origin, destination)
80129
set_valid_rectangles(indexes)
81130
```
82131

83-
If you want, you can see the example [detect_faces.py](opencv_draw_tools/detect_faces.py), it also use an open source library called `face_recognition`.
84-
85-
86-
### Manual method
87-
88-
```
89-
import opencv_draw_tools as cv2_tools
90-
91-
92-
"""
93-
Draw better rectangles to select zones.
94-
Keyword arguments:
95-
frame -- opencv frame object where you want to draw
96-
position -- touple with 4 elements (x1, y1, x2, y2)
97-
This elements must be between 0 and 1 in case it is normalized
98-
or between 0 and frame height/width.
99-
tags -- list of strings/tags you want to associate to the selected zone (default [])
100-
tag_position -- position where you want to add the tags, relatively to the selected zone (default None)
101-
If None provided it will auto select the zone where it fits better:
102-
- First try to put the text on the Bottom Rigth corner
103-
- If it doesn't fit, try to put the text on the Bottom Left corner
104-
- If it doesn't fit, try to put the text Inside the rectangle
105-
- Finally if it doesn't fit, try to put the text On top of the rectangle
106-
alpha -- transparency of the selected zone on the image (default 0.9)
107-
1 means totally visible and 0 totally invisible
108-
color -- color of the selected zone, touple with 3 elements BGR (default (110,70,45) -> dark blue)
109-
BGR = Blue - Green - Red
110-
normalized -- boolean parameter, if True, position provided normalized (between 0 and 1) else you should provide concrete values (default False)
111-
thickness -- thickness of the drawing in pixels (default 2)
112-
filled -- boolean parameter, if True, will draw a filled rectangle with one-third opacity compared to the rectangle (default False)
113-
peephole -- boolean parameter, if True, also draw additional effect, so it looks like a peephole
114-
"""
115-
frame = cv2_tools.select_zone(frame, position, tags=[])
116-
```
117-
118-
### Example with Webcam
119-
120-
```
121-
import opencv_draw_tools as cv2_tools
122-
cv2_tools.webcam_test()
123-
```
124-
125-
See `webcam_test()` code:
126-
127-
```
128-
def webcam_test():
129-
"""Reproduce Webcam in real time with a selected zone."""
130-
print('Launching webcam test')
131-
cap = cv2.VideoCapture(0)
132-
f_width = cap.get(3)
133-
f_height = cap.get(4)
134-
window_name = 'opencv_draw_tools'
135-
while True:
136-
ret, frame = cap.read()
137-
frame = cv2.flip(frame, 1)
138-
if ret:
139-
keystroke = cv2.waitKey(1)
140-
position = (0.33,0.2,0.66,0.8)
141-
tags = ['MIT License', '(C) Copyright\n Fernando\n Perez\n Gutierrez']
142-
frame = select_zone(frame, position, tags=tags, color=(130,58,14), thickness=2, filled=True, normalized=True)
143-
cv2.imshow(window_name, frame)
144-
# True if escape 'esc' is pressed
145-
if keystroke == 27:
146-
break
147-
cv2.destroyAllWindows()
148-
cv2.VideoCapture(0).release()
149-
```
132+
If you want, you can see the example [detect_faces.py](examples/detect_faces.py), it also use an open source library called `face_recognition`.

cv2_tools/LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../LICENSE

cv2_tools/Management.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# MIT License
2+
# Copyright (c) 2019 Fernando Perez
3+
import time
4+
import cv2
5+
6+
# TODO: Document ManagerCV2
7+
class ManagerCV2():
8+
9+
_tries_reconnect_stream = 10
10+
11+
def __init__(self, video, is_stream=False, keystroke=-1, wait_key=-1, fps_limit=0):
12+
self.video = video
13+
self.is_stream = is_stream
14+
self.stream = video
15+
self.fps_limit = fps_limit
16+
17+
self.keystroke = keystroke
18+
self.wait_key = wait_key
19+
20+
self.last_keystroke = -1
21+
self.initial_time = None
22+
self.final_time = None
23+
self.count_frames = 0
24+
25+
26+
def __iter__(self):
27+
self.initial_time = time.time()
28+
self.last_frame_time = self.initial_time
29+
self.count_frames = 0
30+
self.last_keystroke = -1
31+
return self
32+
33+
34+
def __next__(self):
35+
ret, frame = self.video.read()
36+
self.final_time = time.time()
37+
38+
if self.is_stream:
39+
for i in range(ManagerCV2._tries_reconnect_stream):
40+
ret, frame = self.video.read()
41+
if ret:
42+
break
43+
if i+1 == ManagerCV2._tries_reconnect_stream:
44+
self.end_iteration()
45+
elif not ret:
46+
self.end_iteration()
47+
48+
if self.wait_key != -1:
49+
self.last_keystroke = cv2.waitKey(self.wait_key)
50+
if self.last_keystroke == self.keystroke:
51+
self.end_iteration()
52+
53+
self.count_frames += 1
54+
55+
# Here we limit the speed (if we want constant frames)
56+
if self.fps_limit:
57+
time_to_sleep = (1 / self.fps_limit) - (time.time() - self.last_frame_time)
58+
if time_to_sleep > 0:
59+
time.sleep(time_to_sleep)
60+
61+
self.last_frame_time = time.time()
62+
return frame
63+
64+
65+
def get_last_keystroke(self):
66+
return self.last_keystroke
67+
68+
69+
def end_iteration(self):
70+
self.video.release()
71+
raise StopIteration
72+
73+
74+
def get_fps(self):
75+
return round(self.count_frames / (self.final_time - self.initial_time),3)

cv2_tools/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../README.md

cv2_tools/Selection.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# MIT License
2+
# Copyright (c) 2019 Fernando Perez
3+
import cv2
4+
5+
from cv2_tools.utils import *
6+
7+
8+
# TODO: Document SelectorCV2
9+
class SelectorCV2():
10+
11+
12+
def __init__(self, alpha=0.9, color=(110,70,45), normalized=False, thickness=2,
13+
filled=False, peephole=True, margin=5, closed_polygon=False):
14+
self.zones = []
15+
self.polygon_zones = []
16+
self.all_tags = []
17+
# Visual parameters
18+
self.alpha = alpha
19+
self.color = color
20+
self.normalized = normalized
21+
self.thickness = thickness
22+
self.filled = filled
23+
self.peephole = peephole
24+
self.margin = margin
25+
# Polygon
26+
self.closed_polygon = closed_polygon
27+
28+
29+
def set_properties(self, alpha=None, color=None, normalized=None,
30+
thickness=None, filled=None, peephole=None,
31+
margin=None):
32+
if alpha is not None:
33+
self.alpha = alpha
34+
if color is not None:
35+
self.color = color
36+
if normalized is not None:
37+
self.normalized = normalized
38+
if thickness is not None:
39+
self.thickness = thickness
40+
if filled is not None:
41+
self.filled = filled
42+
if peephole is not None:
43+
self.peephole = peephole
44+
if margin is not None:
45+
self.margin = margin
46+
47+
48+
def add_zone(self, zone, tags=None):
49+
self.zones.append(zone)
50+
if tags and type(tags) is not list:
51+
tags = [tags]
52+
elif not tags:
53+
tags = []
54+
self.all_tags.append(tags)
55+
56+
57+
def add_polygon(self, polygon, surrounding_box=False, tags=None):
58+
if not polygon:
59+
return
60+
61+
self.polygon_zones.append(polygon)
62+
63+
if surrounding_box:
64+
min_x, min_y, max_x, max_y = polygon[0][0], polygon[0][1], 0, 0
65+
for position in polygon:
66+
if position[0] < min_x:
67+
min_x = position[0]
68+
if position[0] > max_x:
69+
max_x = position[0]
70+
if position[1] < min_y:
71+
min_y = position[1]
72+
if position[1] > max_y:
73+
max_y = position[1]
74+
75+
self.zones.append((min_x, min_y, max_x, max_y))
76+
77+
if tags and type(tags) is not list:
78+
tags = [tags]
79+
elif not tags:
80+
tags = []
81+
self.all_tags.append(tags)
82+
83+
84+
def set_range_valid_rectangles(self, origin, destination):
85+
self.zones = self.zones[origin:destination]
86+
self.all_tags = self.all_tags[origin:destination]
87+
88+
89+
def set_valid_rectangles(self, indexes):
90+
# This if is just for efficiency
91+
if not indexes:
92+
self.zones = []
93+
self.all_tags = []
94+
return
95+
96+
for i in range(len(self.zones)):
97+
if i not in indexes:
98+
self.zones.pop(i)
99+
self.all_tags.pop(i)
100+
101+
102+
def draw(self, frame, fx=1, fy=1, interpolation=cv2.INTER_LINEAR):
103+
next_frame = select_multiple_zones(
104+
frame.copy(),
105+
self.zones,
106+
all_tags=self.all_tags,
107+
alpha=self.alpha,
108+
color=self.color,
109+
normalized=self.normalized,
110+
thickness=self.thickness,
111+
filled=self.filled,
112+
peephole=self.peephole,
113+
margin=self.margin)
114+
115+
next_frame = select_polygon(
116+
next_frame,
117+
all_vertexes=self.polygon_zones,
118+
color=self.color,
119+
thickness=self.thickness,
120+
closed=self.closed_polygon
121+
)
122+
123+
return cv2.resize(next_frame, (0,0), fx=fx, fy=fy, interpolation=interpolation)

opencv_draw_tools/__init__.py renamed to cv2_tools/__init__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
from opencv_draw_tools.SelectZone import *
2-
import opencv_draw_tools.tags_constraint
1+
from cv2_tools.utils import webcam_test, get_complete_help
32

4-
name = 'opencv_draw_tools'
3+
name = 'cv2_tools'
54
help = '''
65
MIT License
76
Copyright (c) 2019 Fernando Perez
87
For more information visit: https://github.com/fernaper/opencv-draw-tools
98
Also you can write complete_help to view full information'''
10-
__version__ = '1.2.0'
9+
__version__ = '2.0.2'
1110

1211
complete_help = '''
1312
{} - v{}
File renamed without changes.

0 commit comments

Comments
 (0)