Skip to content

Commit

Permalink
cli improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
ptg committed Oct 9, 2024
1 parent 3ab1ad3 commit 3bb2d94
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 12 deletions.
5 changes: 4 additions & 1 deletion ptgctl/tools/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import asyncio
import datetime
import numpy as np
from PIL import Image
from .. import util

log = util.getLogger(__name__, 'debug')
Expand All @@ -21,6 +20,7 @@
async def imshow(api, stream_id, delay=1, api_output='jpg', stream_format=None, **kw):
'''Show a video stream from the API.'''
import cv2
from PIL import Image
from .. import holoframe
async with api.data_pull_connect(stream_id, output=api_output, input=stream_format, time_sync_id=0, ack=True, **kw) as ws:
t0 = time.time()
Expand Down Expand Up @@ -55,6 +55,7 @@ async def imshow(api, stream_id, delay=1, api_output='jpg', stream_format=None,
def imshow1(api, stream_id, **kw):#, raw_holo=False
'''Show a single frame of a stream.'''
import cv2
from PIL import Image
# if raw_holo:
# from .. import holoframe
for sid, ts, data in api.data(stream_id, output='jpg', **kw):
Expand Down Expand Up @@ -370,6 +371,7 @@ def ascii_image(img, width=60, height=None, invert=False, preserve_aspect=True):
if img is None:
return ''
if isinstance(img, np.ndarray):
from PIL import Image
img = Image.fromarray(img)
# resize the image
w, h = img.size
Expand All @@ -393,4 +395,5 @@ def _aspect(w, h, w_im, h_im, preserve=True):
return int(w), int(h)

def ascii_test(api, path, width=60, invert=False):
from PIL import Image
print(ascii_image(Image.open(path), width, invert))
32 changes: 25 additions & 7 deletions ptgctl/tools/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import time
import asyncio
import cv2
from PIL import Image as pil

from .. import util
from ptgctl.holoframe import dump_v3, load

Expand All @@ -33,12 +31,12 @@ async def video_loop(api, src=0, pos=0, **kw):

DIVS = 4
@util.async2sync
async def video(api, src=0, pos=0, width=0.3, shape=(300, 400, 3), fps=30, stepbystep=False, prefix=None):
async def video(api, src=0, pos=0, width=0.3, shape=None, fps=15, stepbystep=False, prefix=None):
'''Send video (by default your webcam) to the API.'''
sid = CAM_POS_SIDS[pos]
sid = f'{prefix or ""}{sid}'
async with api.data_push_connect(sid, batch=True) as ws:
for im in _video_feed(src, shape):
async for im in _video_feed(src, fps, shape):
if pos:
im = _fake_side_cam(im, pos, width)
# else:
Expand All @@ -48,11 +46,11 @@ async def video(api, src=0, pos=0, width=0.3, shape=(300, 400, 3), fps=30, stepb
if stepbystep:
input()
await ws.send_data([dump_v3(im)], [sid], [util.format_epoch_time(time.time())])
await asyncio.sleep(1/fps)

def _img_dump(im, format='jpeg'):
from PIL import Image
output = io.BytesIO()
pil.fromarray(im).save(output, format=format)
Image.fromarray(im).save(output, format=format)
return output.getvalue()


Expand All @@ -66,24 +64,44 @@ def _fake_side_cam(im, pos=0, width=0.3):
return im


def _video_feed(src, shape=(300, 400, 3)):
async def _video_feed(src, fps=None, shape=None):
import tqdm
with tqdm.tqdm() as pbar:
if src is False:
import numpy as np
if isinstance(shape, int):
shape = (shape, shape, 3)
if shape is None:
shape = (300, 400, 3)
while True:
yield np.random.uniform(0, 255, shape).astype('uint8')
pbar.update()
if fps:
await asyncio.sleep(1/fps)
return
cap = cv2.VideoCapture(src)
vid_fps = cap.get(cv2.CAP_PROP_FPS)
skip = max(1, int(vid_fps / fps)) if fps else 1
if not cap.isOpened():
raise ValueError(f"{cap}")
i = 0
while True:
ret, im = cap.read()
if not ret:
break
i += 1
if i % skip:
continue
if isinstance(shape, int):
ratio = max(shape/im.shape[0], shape/im.shape[1])
im = cv2.resize(im, (0, 0), fx=ratio, fy=ratio)
elif shape:
im = cv2.resize(im, (shape[1], shape[0]))
yield im
pbar.update()
if fps:
await asyncio.sleep(1/fps)


@util.async2sync
async def audio(api, sid='mic0', device=None, weird_offset=1.6):
Expand Down
8 changes: 6 additions & 2 deletions ptgctl/util/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ def _load_module(self, reload=False):
if not reload and self._loaded:
return # be idempotent

self._wrapped = wrapped = self._get_module(self._self)
try:
self._wrapped = wrapped = self._get_module(self._self)
except ImportError as e:
log.warning(f"{e}")
self._wrapped = None
keys = (
getattr(wrapped, '__bind__', None) or
getattr(wrapped, '__all__', None) or
Expand All @@ -87,7 +91,7 @@ def _load_module(self, reload=False):
# mimic - idk
for k in self._COPY_OVER:
setattr(self, k, getattr(self._wrapped, k))
self._loaded = True
self._loaded = self._wrapped is not None

def _is_public(self, func):
return is_public_func(func) and belongs_to_module(self._wrapped, func)
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
NAME = 'ptgctl'

deps = {
'image': ['Pillow', 'opencv-python', 'numpy'],
'image': ['Pillow', 'opencv-python', 'numpy', 'supervision'],
'audio': ['sounddevice', 'soundfile'],
}

Expand All @@ -24,7 +24,7 @@
install_requires=[
'requests', 'websockets', 'fire>=0.5.0',
# 'fire @ git+ssh://[email protected]/google/python-fire@master#egg=fire',
'tabulate', 'tqdm',
'tabulate', 'tqdm', 'IPython',
'redis_record>=0.0.4',
],
extras_require={
Expand Down

0 comments on commit 3bb2d94

Please sign in to comment.