Added escapi back and added code to attempt using each different library for camera reading.

This commit is contained in:
Emiliana 2020-08-08 00:07:01 +02:00
parent ca850f1218
commit b29ecbc059
5 changed files with 242 additions and 22 deletions

125
escapi.py Normal file
View file

@ -0,0 +1,125 @@
"""
A simple python wrapper around escapi
Usage:
from camera import Device
device = Deveice.connect(0, 500, 500)
image = device.get_image()
"""
import os
import platform
import sys
from ctypes import *
from PIL import Image
import numpy as np
import cv2
def resolve(name):
f = os.path.join(os.path.dirname(__file__), name)
return f
class CAPTURE_PROPETIES:
CAPTURE_BRIGHTNESS = 1,
CAPTURE_CONTRAST = 2,
CAPTURE_HUE = 3,
CAPTURE_SATURATION = 4,
CAPTURE_SHARPNESS = 5,
CAPTURE_GAMMA = 6,
CAPTURE_COLORENABLE = 7,
CAPTURE_WHITEBALANCE = 8,
CAPTURE_BACKLIGHTCOMPENSATION = 9,
CAPTURE_GAIN = 10,
CAPTURE_PAN = 11,
CAPTURE_TILT = 12,
CAPTURE_ROLL = 13,
CAPTURE_ZOOM = 14,
CAPTURE_EXPOSURE = 15,
CAPTURE_IRIS = 16,
CAPTURE_FOCUS = 17,
CAPTURE_PROP_MAX = 18,
class SimpleCapParms(Structure):
_fields_ = [
("buffer", POINTER(c_int)),
("width", c_int),
("height", c_int),
("fps", c_int),
]
lib = None
def init():
global lib
if platform.architecture()[0] == '32bit':
dll_path = resolve(os.path.join("escapi", "escapi_x86.dll"))
lib = cdll.LoadLibrary(dll_path)
else:
dll_path = resolve(os.path.join("escapi", "escapi_x64.dll"))
lib = cdll.LoadLibrary(dll_path)
if lib is None or lib.ESCAPIVersion() != 0xfff001:
print("Invalid ESCAPI DLL found.")
sys.exit(1)
lib.initCapture.argtypes = [c_int, POINTER(SimpleCapParms)]
lib.initCapture.restype = c_int
lib.initCOM()
def count_capture_devices():
return lib.countCaptureDevices()
def device_name(device):
"""
Get the device name for the given device
:param device: The number of the device
:return: The name of the device
"""
namearry = (c_char * 256)()
lib.getCaptureDeviceName(device, namearry, 256)
camearaname = namearry.value
return camearaname
def init_camera(device, width, height, fps):
global devices
array = (width * height * c_int)()
options = SimpleCapParms()
options.width = width
options.height = height
options.fps = fps
options.buffer = array
lib.initCapture(device, byref(options))
return array
def do_capture(device):
lib.doCapture(device)
def is_capture_done(device):
return lib.isCaptureDone(device)
def read(device, width, height, array):
if is_capture_done(device):
img = Image.frombuffer('RGBA', (width, height), array, 'raw', 'BGRA', 0, 1)
img = np.array(img)
img = cv2.cvtColor(img, cv2.COLOR_RGBA2BGR);
return img
else:
return None
def get_image(device, width, height, array):
lib.doCapture(device)
while lib.isCaptureDone(device) == 0:
pass
img = Image.frombuffer('RGBA', (width, height), array, 'raw', 'BGRA', 0, 0)
img = np.array(img)
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR);
return img
def deinit_camera(device):
lib.deinitCapture(device)

BIN
escapi/escapi_x64.dll Normal file

Binary file not shown.

BIN
escapi/escapi_x86.dll Normal file

Binary file not shown.

View file

@ -3,11 +3,14 @@ import sys
import os
import cv2
import numpy as np
import escapi
import dshowcapture
import time
import traceback
class VideoReader():
def __init__(self, capture):
if os.name == 'nt':
def __init__(self, capture, camera=False):
if os.name == 'nt' and camera:
self.cap = cv2.VideoCapture(capture, cv2.CAP_DSHOW)
else:
self.cap = cv2.VideoCapture(capture)
@ -23,40 +26,70 @@ class VideoReader():
def close(self):
self.cap.release()
class CameraReader(VideoReader):
class EscapiReader(VideoReader):
def __init__(self, capture, width, height, fps):
self.device = None
self.width = width
self.height = height
self.fps = fps
self.device = capture
self.buffer = escapi.init_camera(self.device, self.width, self.height, self.fps)
escapi.do_capture(self.device)
def is_open(self):
return True
def is_ready(self):
return escapi.is_capture_done(self.device)
def read(self):
if escapi.is_capture_done(self.device):
image = escapi.read(self.device, self.width, self.height, self.buffer)
escapi.do_capture(self.device)
return True, image
else:
return False, None
def close(self):
escapi.deinit_camera(self.device)
class DShowCaptureReader(VideoReader):
def __init__(self, capture, width, height, fps, use_dshowcapture=True):
self.device = None
self.width = width
self.height = height
self.fps = fps
if os.name == 'nt' and use_dshowcapture:
self.device = dshowcapture.DShowCapture()
self.device.capture_device(capture, self.width, self.height, self.fps)
else:
super(CameraReader, self).__init__(capture)
self.cap.set(3, width)
self.cap.set(4, height)
self.device = dshowcapture.DShowCapture()
self.device.get_devices()
self.device_name = self.device.get_device(capture)
self.device.capture_device(capture, self.width, self.height, self.fps)
self.timeout = 1000
def is_open(self):
if self.device is None:
return super(CameraReader, self).is_open()
return self.device.capturing()
def is_ready(self):
if self.device is None:
return super(CameraReader, self).is_ready()
return self.device.capturing()
def read(self):
if self.device is None:
return super(CameraReader, self).read()
img = self.device.get_frame(1000)
img = self.device.get_frame(self.timeout)
if img is None:
return False, None
else:
return True, img
def close(self):
if self.device is None:
super(CameraReader, self).close()
else:
self.device.destroy_capture()
self.device.destroy_capture()
class OpenCVReader(VideoReader):
def __init__(self, capture, width, height, fps):
self.device = None
self.width = width
self.height = height
self.fps = fps
super(OpenCVReader, self).__init__(capture, camera=True)
self.cap.set(3, width)
self.cap.set(4, height)
def is_open(self):
return super(OpenCVReader, self).is_open()
def is_ready(self):
return super(OpenCVReader, self).is_ready()
def read(self):
return super(OpenCVReader, self).read()
def close(self):
super(OpenCVReader, self).close()
class RawReader:
def __init__(self, width, height):
@ -90,6 +123,24 @@ def try_int(s):
except:
return None
def test_reader(reader):
try:
for i in range(30):
if not reader.is_ready():
time.sleep(0.02)
ret, frame = reader.read()
if not ret:
print("Not ret")
return False
if reader.is_open():
return True
print("Fail")
return False
except:
traceback.print_exc()
print("Except")
return False
class InputReader():
def __init__(self, capture, raw_rgb, width, height, fps, use_dshowcapture=False):
self.reader = None
@ -99,7 +150,47 @@ class InputReader():
elif os.path.exists(capture):
self.reader = VideoReader(capture)
elif capture == str(try_int(capture)):
self.reader = CameraReader(int(capture), width, height, fps, use_dshowcapture=use_dshowcapture)
if os.name == 'nt':
# Try with DShowCapture
good = True
name = ""
try:
if use_dshowcapture:
self.reader = DShowCaptureReader(int(capture), width, height, fps)
name = self.reader.device_name
good = test_reader(self.reader)
else:
good = False
except:
good = False
if good:
return
# Try with Escapi
good = True
try:
print(f"DShowCapture failed. Falling back to escapi for device {name}.", file=sys.stderr)
escapi.init()
devices = escapi.count_capture_devices()
found = None
for i in range(devices):
escapi_name = str(escapi.device_name(i).decode('utf8'))
if name == escapi_name:
found = i
if found is None:
good = False
else:
print(f"Found device {name} as {i}.", file=sys.stderr)
self.reader = EscapiReader(found, width, height, fps)
good = test_reader(self.reader)
except:
good = False
if good:
return
# Try with OpenCV
print(f"Escapi failed. Falling back to OpenCV. If this fails, please change your camera settings.", file=sys.stderr)
self.reader = OpenCVReader(int(capture), width, height, fps)
else:
self.reader = OpenCVReader(int(capture), width, height, fps)
except Exception as e:
print("Error: " + str(e))

View file

@ -1,9 +1,13 @@
REM pyinstaller --onefile ^
REM --add-binary dshowcapture/dshowcapture_x86.dll;. ^
REM --add-binary dshowcapture/dshowcapture_x64.dll;. ^
REM --add-binary escapi/escapi_x86.dll;. ^
REM --add-binary escapi/escapi_x64.dll;. ^
REM facetracker.py
pyinstaller --onedir ^
--add-binary dshowcapture/dshowcapture_x86.dll;. ^
--add-binary dshowcapture/dshowcapture_x64.dll;. ^
--add-binary escapi/escapi_x86.dll;. ^
--add-binary escapi/escapi_x64.dll;. ^
facetracker.py