Added escapi back and added code to attempt using each different library for camera reading.
This commit is contained in:
parent
ca850f1218
commit
b29ecbc059
5 changed files with 242 additions and 22 deletions
125
escapi.py
Normal file
125
escapi.py
Normal 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
BIN
escapi/escapi_x64.dll
Normal file
Binary file not shown.
BIN
escapi/escapi_x86.dll
Normal file
BIN
escapi/escapi_x86.dll
Normal file
Binary file not shown.
129
input_reader.py
129
input_reader.py
|
|
@ -3,11 +3,14 @@ import sys
|
||||||
import os
|
import os
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import escapi
|
||||||
import dshowcapture
|
import dshowcapture
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
class VideoReader():
|
class VideoReader():
|
||||||
def __init__(self, capture):
|
def __init__(self, capture, camera=False):
|
||||||
if os.name == 'nt':
|
if os.name == 'nt' and camera:
|
||||||
self.cap = cv2.VideoCapture(capture, cv2.CAP_DSHOW)
|
self.cap = cv2.VideoCapture(capture, cv2.CAP_DSHOW)
|
||||||
else:
|
else:
|
||||||
self.cap = cv2.VideoCapture(capture)
|
self.cap = cv2.VideoCapture(capture)
|
||||||
|
|
@ -23,41 +26,71 @@ class VideoReader():
|
||||||
def close(self):
|
def close(self):
|
||||||
self.cap.release()
|
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):
|
def __init__(self, capture, width, height, fps, use_dshowcapture=True):
|
||||||
self.device = None
|
self.device = None
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.fps = fps
|
self.fps = fps
|
||||||
if os.name == 'nt' and use_dshowcapture:
|
|
||||||
self.device = dshowcapture.DShowCapture()
|
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.device.capture_device(capture, self.width, self.height, self.fps)
|
||||||
else:
|
self.timeout = 1000
|
||||||
super(CameraReader, self).__init__(capture)
|
|
||||||
self.cap.set(3, width)
|
|
||||||
self.cap.set(4, height)
|
|
||||||
def is_open(self):
|
def is_open(self):
|
||||||
if self.device is None:
|
|
||||||
return super(CameraReader, self).is_open()
|
|
||||||
return self.device.capturing()
|
return self.device.capturing()
|
||||||
def is_ready(self):
|
def is_ready(self):
|
||||||
if self.device is None:
|
|
||||||
return super(CameraReader, self).is_ready()
|
|
||||||
return self.device.capturing()
|
return self.device.capturing()
|
||||||
def read(self):
|
def read(self):
|
||||||
if self.device is None:
|
img = self.device.get_frame(self.timeout)
|
||||||
return super(CameraReader, self).read()
|
|
||||||
img = self.device.get_frame(1000)
|
|
||||||
if img is None:
|
if img is None:
|
||||||
return False, None
|
return False, None
|
||||||
else:
|
else:
|
||||||
return True, img
|
return True, img
|
||||||
def close(self):
|
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:
|
class RawReader:
|
||||||
def __init__(self, width, height):
|
def __init__(self, width, height):
|
||||||
self.width = int(width)
|
self.width = int(width)
|
||||||
|
|
@ -90,6 +123,24 @@ def try_int(s):
|
||||||
except:
|
except:
|
||||||
return None
|
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():
|
class InputReader():
|
||||||
def __init__(self, capture, raw_rgb, width, height, fps, use_dshowcapture=False):
|
def __init__(self, capture, raw_rgb, width, height, fps, use_dshowcapture=False):
|
||||||
self.reader = None
|
self.reader = None
|
||||||
|
|
@ -99,7 +150,47 @@ class InputReader():
|
||||||
elif os.path.exists(capture):
|
elif os.path.exists(capture):
|
||||||
self.reader = VideoReader(capture)
|
self.reader = VideoReader(capture)
|
||||||
elif capture == str(try_int(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:
|
except Exception as e:
|
||||||
print("Error: " + str(e))
|
print("Error: " + str(e))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
REM pyinstaller --onefile ^
|
REM pyinstaller --onefile ^
|
||||||
REM --add-binary dshowcapture/dshowcapture_x86.dll;. ^
|
REM --add-binary dshowcapture/dshowcapture_x86.dll;. ^
|
||||||
REM --add-binary dshowcapture/dshowcapture_x64.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
|
REM facetracker.py
|
||||||
|
|
||||||
pyinstaller --onedir ^
|
pyinstaller --onedir ^
|
||||||
--add-binary dshowcapture/dshowcapture_x86.dll;. ^
|
--add-binary dshowcapture/dshowcapture_x86.dll;. ^
|
||||||
--add-binary dshowcapture/dshowcapture_x64.dll;. ^
|
--add-binary dshowcapture/dshowcapture_x64.dll;. ^
|
||||||
|
--add-binary escapi/escapi_x86.dll;. ^
|
||||||
|
--add-binary escapi/escapi_x64.dll;. ^
|
||||||
facetracker.py
|
facetracker.py
|
||||||
Loading…
Add table
Add a link
Reference in a new issue