diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c251333 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__/ +.ipynb_checkpoints/ +*test* +*.pyc +write_camera_details.py +camera_details.json diff --git a/README.md b/README.md index 5891d50..9791ba8 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,10 @@ This software package was written by [Gary Kane](https://github.com/gkane26), po 1. Install the latest driver for your camera. You can find the driver from The Imaging Source website: https://www.theimagingsource.com/products/. **If you add new cameras to an existing system, make sure to update the driver!** 1. Clone this repository. Open command prompt (type "cmd" into the search bar and hit enter), then type:

-``git clone https://github.com/AdaptiveMotorControlLab/camera_control`` +``git clone https://github.com/AdaptiveMotorControlLab/Camera_Control`` 2. Open the camera control directory, **right-click 'install1.bat' and select 'Run as administrator'**

-This script will install imaging source libraries, ffmpeg for command prompt, and create a new conda environment 'camera27'. Upon completion, the window will close suddenly. +This script will install imaging source libraries, ffmpeg for command prompt, and create a new conda environment 'camera36'. Upon completion, the window will close suddenly. 3. Run 'install2.bat'.

This script will finish setting up the conda environment and create a desktop shortcut to open the GUI. @@ -35,7 +35,7 @@ This script will finish setting up the conda environment and create a desktop sh - name = camera name - crop = cropping parameters - rotate = rotation angle of image - - exposure = integer exposure values; can edit this in the GUI + - exposure = exposure in ms; can edit this in the GUI - output_dir = default directory to save videos; can edit this in the GUI - Example: @@ -43,7 +43,7 @@ This script will finish setting up the conda environment and create a desktop sh cam_0 = {'name' : 'Cog Rig', 'crop' : {'top' : 150, 'left' : 225, 'height' : 250, 'width' : 300}, 'rotate' : 0, - 'exposure' : -14, + 'exposure' : .003, 'output_dir' : 'C:/Users/user1/Desktop/video'} diff --git a/camera_control_GUI.py b/camera_control_GUI.py index f05a372..f1ab7e1 100644 --- a/camera_control_GUI.py +++ b/camera_control_GUI.py @@ -8,9 +8,7 @@ GUI to record from imaging source cameras during experiments """ -from Tkinter import Entry, Label, Button, StringVar, IntVar, Tk, END, Radiobutton -import tkFileDialog -import ttk +from tkinter import Entry, Label, Button, StringVar, IntVar, Tk, END, Radiobutton, filedialog, ttk import numpy as np import datetime import os @@ -21,7 +19,6 @@ import threading import json import nidaqmx -import write_camera_details class CamGUI(object): @@ -43,8 +40,9 @@ def __init__(self): self.selectCams() def browse_output(self): - filepath = tkFileDialog.askdirectory() - self.output.set(filepath) + if len(self.vid_out) == 0: + filepath = filedialog.askdirectory() + self.output.set(filepath) def init_cam(self, num): # create pop up window during setup @@ -92,7 +90,7 @@ def set_exposure(self, num): cam_check_window.mainloop() cam_check_window.destroy() else: - self.cam[num].set_exposure(int(self.exposure[num].get())) + self.cam[num].set_exposure(float(self.exposure[num].get())) def lv_interrupt(self, task_handle, signal_type, callback_data): @@ -247,6 +245,7 @@ def start_record(self): self.vid_start_time = time.time() t = [] for i in range(len(self.cam)): + self.cam[i].set_frame_rate(int(self.fps.get())) t.append(threading.Thread(target=self.record_on_thread, args=(i,))) t[-1].daemon = True t[-1].start() @@ -320,6 +319,9 @@ def save_vid(self, compress=False, delete=False): def close_window(self): + if self.record_on.get(): + return + self.end_labview() if not self.setup: self.done = True diff --git a/camera_env.yaml b/camera_env.yaml deleted file mode 100644 index 7388340..0000000 --- a/camera_env.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: camera27 -channels: - - defaults -dependencies: - - certifi=2018.11.29=py27_0 - - pip=18.1=py27_0 - - python=2.7.15=hcb6e200_5 - - setuptools=40.6.3=py27_0 - - sqlite=3.26.0=h0c8e037_0 - - vc=9=h7299396_1 - - vs2008_runtime=9.00.30729.1=hfaea7d5_1 - - wheel=0.32.3=py27_0 - - wincertstore=0.2=py27hf04cefb_0 - - pip: - - ffmpy==0.2.2 - - future==0.17.1 - - numpy==1.16.0 - - opencv-python==4.0.0.21 - - nidaqmx diff --git a/camera_env.yml b/camera_env.yml new file mode 100644 index 0000000..b3e0a41 --- /dev/null +++ b/camera_env.yml @@ -0,0 +1,20 @@ +name: camera36 +channels: + - defaults +dependencies: + - certifi=2019.9.11=py36_0 + - pip=19.2.3=py36_0 + - python=3.6.9=h5500b2f_0 + - setuptools=41.2.0=py36_0 + - sqlite=3.29.0=he774522_0 + - vc=14.1=h0510ff6_4 + - vs2015_runtime=14.16.27012=hf0eaf9b_0 + - wheel=0.33.6=py36_0 + - wincertstore=0.2=py36h7fe50ca_0 + - pip: + - ffmpy==0.2.2 + - imutils==0.5.3 + - nidaqmx==0.5.7 + - numpy==1.16.0 + - opencv-python==4.1.1.26 + - six==1.12.0 diff --git a/ic_camera.py b/ic_camera.py index b7af7b9..167629d 100644 --- a/ic_camera.py +++ b/ic_camera.py @@ -8,20 +8,20 @@ camera class for imaging source cameras - helps load correct settings """ -from pyicic.IC_ImagingControl import * +import tisgrabber as ic import numpy as np import os import json import cv2 +import ctypes as C path = os.path.dirname(os.path.realpath(__file__)) dets_file = os.path.normpath(path + '/camera_details.json') -with open(dets_file) as f: - cam_details = json.load(f) +cam_details = json.load(open(dets_file, 'r')) class ICCam(object): - def __init__(self, cam_num=0, rotate=None, crop=None, exposure=None, format='Y800 (720x540)'): + def __init__(self, cam_num=0, rotate=None, crop=None, exposure=None): ''' Params ------ @@ -31,65 +31,56 @@ def __init__(self, cam_num=0, rotate=None, crop=None, exposure=None, format='Y80 default = None, uses default parameters specific to camera ''' - self.ic_ic = IC_ImagingControl() - self.ic_ic.init_library() - self.cam_num = cam_num self.rotate = rotate if rotate is not None else cam_details[str(self.cam_num)]['rotate'] self.crop = crop if crop is not None else cam_details[str(self.cam_num)]['crop'] self.exposure = exposure if exposure is not None else cam_details[str(self.cam_num)]['exposure'] - self.cam = self.ic_ic.get_device(self.ic_ic.get_unique_device_names()[self.cam_num]) - self.cam.open() - self.cam.set_video_format(format) + self.cam = ic.TIS_CAM() + self.cam.open(self.cam.GetDevices()[cam_num].decode()) self.add_filters() def add_filters(self): if self.rotate != 0: - h_r = self.cam.create_frame_filter('Rotate Flip') - self.cam.add_frame_filter_to_device(h_r) - self.cam.frame_filter_set_parameter(h_r, 'Rotation Angle', self.rotate) - - h_c = self.cam.create_frame_filter('ROI') - self.cam.add_frame_filter_to_device(h_c) - self.cam.frame_filter_set_parameter(h_c, 'Top', self.crop['top']) - self.cam.frame_filter_set_parameter(h_c, 'Left', self.crop['left']) - self.cam.frame_filter_set_parameter(h_c, 'Height', self.crop['height']) - self.cam.frame_filter_set_parameter(h_c, 'Width', self.crop['width']) + h_r = self.cam.CreateFrameFilter(b'Rotate Flip') + self.cam.AddFrameFilter(h_r) + self.cam.FilterSetParameter(h_r, b'Rotation Angle', self.rotate) + + h_c = self.cam.CreateFrameFilter(b'ROI') + self.cam.AddFrameFilter(h_c) + self.cam.FilterSetParameter(h_c, b'Top', self.crop['top']) + self.cam.FilterSetParameter(h_c, b'Left', self.crop['left']) + self.cam.FilterSetParameter(h_c, b'Height', self.crop['height']) + self.cam.FilterSetParameter(h_c, b'Width', self.crop['width']) self.size = (self.crop['width'], self.crop['height']) - self.cam.gain.auto = False - self.cam.exposure.auto = False - self.cam.exposure.value = self.exposure - + def set_frame_rate(self, fps): + self.cam.SetFrameRate(fps) def set_exposure(self, val): - try: - val = int(round(val)) - val = val if val < self.cam.exposure.max-1 else self.cam.exposure.max-1 - val = val if val > self.cam.exposure.min else self.cam.exposure.min - self.cam.exposure.value = val - except: - pass + val = 1 if val > 1 else val + val = 0 if val < 0 else val + self.cam.SetPropertyAbsoluteValue("Exposure", "Value", val) def get_exposure(self): - return self.cam.exposure.value + exposure = [0] + self.cam.GetPropertyAbsoluteValue("Exposure", "Value", exposure) + return round(exposure[0], 3) def get_image(self): - data, width, height, depth = self.cam.get_image_data() - frame = np.ndarray(buffer=data, - dtype=np.uint8, - shape=(height, width, depth)) + self.cam.SnapImage() + frame = self.cam.GetImageEx() return cv2.flip(frame,0) def get_image_dimensions(self): - _, width, height, _ = self.cam.get_image_data() + im = self.get_image() + height = im.shape[0] + width = im.shape[1] return (width, height) - def start(self, show_display=True): - self.cam.enable_continuous_mode(True) - self.cam.start_live(show_display=show_display) + def start(self, show_display=1): + self.cam.SetContinuousMode(0) + self.cam.StartLive(show_display) def close(self): - self.cam.stop_live() - self.cam.close() + self.cam.StopLive() diff --git a/install1.bat b/install1.bat index 81d7088..222e9d4 100644 --- a/install1.bat +++ b/install1.bat @@ -31,6 +31,6 @@ powershell [System.Environment]::SetEnvironmentVariable('PATH', '%NEW_PATH%', 'M echo. echo. -echo Create New Conda Environment: camera27 +echo Create New Conda Environment: camera36 call activate.bat -conda env create -f camera_env.yaml +conda env create -f camera_env.yml diff --git a/install2.bat b/install2.bat index fb6be92..65b0cf9 100644 --- a/install2.bat +++ b/install2.bat @@ -1,13 +1,8 @@ echo OFF -@setlocal enableextensions -@cd /d "%~dp0" - echo. echo. -echo Install Imaging Source Python Package -call activate camera27 -pip install git+https://github.com/morefigs/py-ic-imaging-control +echo Initialize system setup via write_camera_details.py file copy write_camera_details_TEMPLATE.py write_camera_details.py python write_camera_details.py @@ -16,7 +11,7 @@ echo. echo. echo Write Shortcut File to the Desktop echo call activate.bat > C:%HOMEPATH%\Desktop\cameraGUI.bat -echo call activate camera27 >> C:%HOMEPATH%\Desktop\cameraGUI.bat +echo call activate camera36 >> C:%HOMEPATH%\Desktop\cameraGUI.bat echo cd %cd% >> C:%HOMEPATH%\Desktop\cameraGUI.bat echo python camera_control_GUI.py >> C:%HOMEPATH%\Desktop\cameraGUI.bat diff --git a/tisgrabber.py b/tisgrabber.py new file mode 100644 index 0000000..f1728a3 --- /dev/null +++ b/tisgrabber.py @@ -0,0 +1,813 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon Nov 21 09:44:40 2016 + +@author: Daniel Vassmer, Stefan_Geissler +From: https://github.com/TheImagingSource/IC-Imaging-Control-Samples/tree/master/Python + +modified 10/3/2019 by Gary Kane - https://github.com/gkane26 +post-doctoral fellow @ the Adaptive Motor Control Lab +https://github.com/AdaptiveMotorControlLab +""" + +from enum import Enum + +import ctypes as C +import os +import sys +import numpy as np + +class SinkFormats(Enum): + Y800 = 0 + RGB24 = 1 + RGB32 = 2 + UYVY = 3 + Y16 = 4 + +ImageFileTypes = {'BMP':0, 'JPEG':1} + + +class GrabberHandle(C.Structure): + pass +GrabberHandle._fields_ = [('unused', C.c_int)] + +############################################################################## + +### GK Additions from: https://github.com/morefigs/py-ic-imaging-control + +class FilterParameter(C.Structure): + pass +FilterParameter._fields_ = [('Name', C.c_char * 30), + ('Type', C.c_int)] + + +class FrameFilterHandle(C.Structure): + pass +FrameFilterHandle._fields_ = [('pFilter', C.c_void_p), + ('bHasDialog', C.c_int), + ('ParameterCount', C.c_int), + ('Parameters', C.POINTER(FilterParameter))] + +############################################################################## + +class TIS_GrabberDLL(object): + if sys.maxsize > 2**32 : + __tisgrabber = C.windll.LoadLibrary("tisgrabber_x64.dll") + else: + __tisgrabber = C.windll.LoadLibrary("tisgrabber.dll") + + def __init__(self, **keyargs): + """Initialize the Albatross from the keyword arguments.""" + self.__dict__.update(keyargs) + + + GrabberHandlePtr = C.POINTER(GrabberHandle) + +#################################### + +# Initialize the ICImagingControl class library. This function must be called +# only once before any other functions of this library are called. +# @param szLicenseKey IC Imaging Control license key or NULL if only a trial version is available. +# @retval IC_SUCCESS on success. +# @retval IC_ERROR on wrong license key or other errors. +# @sa IC_CloseLibrary + InitLibrary = __tisgrabber.IC_InitLibrary(None) + +# Get the number of the currently available devices. This function creates an +# internal array of all connected video capture devices. With each call to this +# function, this array is rebuild. The name and the unique name can be retrieved +# from the internal array using the functions IC_GetDevice() and IC_GetUniqueNamefromList. +# They are usefull for retrieving device names for opening devices. +# +# @retval >= 0 Success, count of found devices. +# @retval IC_NO_HANDLE Internal Error. +# +# @sa IC_GetDevice +# @sa IC_GetUniqueNamefromList + get_devicecount = __tisgrabber.IC_GetDeviceCount + get_devicecount.restype = C.c_int + get_devicecount.argtypes = None + +# Get unique device name of a device specified by iIndex. The unique device name +# consist from the device name and its serial number. It allows to differ between +# more then one device of the same type connected to the computer. The unique device name +# is passed to the function IC_OpenDevByUniqueName +# +# @param iIndex The number of the device whose name is to be returned. It must be +# in the range from 0 to IC_GetDeviceCount(), +# @return Returns the string representation of the device on success, NULL +# otherwise. +# +# @sa IC_GetDeviceCount +# @sa IC_GetUniqueNamefromList +# @sa IC_OpenDevByUniqueName + + get_unique_name_from_list = __tisgrabber.IC_GetUniqueNamefromList + get_unique_name_from_list.restype = C.c_char_p + get_unique_name_from_list.argtypes = (C.c_int,) + +# Creates a new grabber handle and returns it. A new created grabber should be +# release with a call to IC_ReleaseGrabber if it is no longer needed. +# @sa IC_ReleaseGrabber + create_grabber = __tisgrabber.IC_CreateGrabber + create_grabber.restype = GrabberHandlePtr + create_grabber.argtypes = None + +# Open a video capture by using its UniqueName. Use IC_GetUniqueName() to +# retrieve the unique name of a camera. +# +# @param hGrabber Handle to a grabber object +# @param szDisplayName Memory that will take the display name. +# +# @sa IC_GetUniqueName +# @sa IC_ReleaseGrabber + open_device_by_unique_name = __tisgrabber.IC_OpenDevByUniqueName + open_device_by_unique_name.restype = C.c_int + open_device_by_unique_name.argtypes = (GrabberHandlePtr, + C.c_char_p) + + + set_videoformat = __tisgrabber.IC_SetVideoFormat + set_videoformat.restype = C.c_int + set_videoformat.argtypes = (GrabberHandlePtr, + C.c_char_p) + + set_framerate = __tisgrabber.IC_SetFrameRate + set_framerate.restype = C.c_int + set_framerate.argtypes = (GrabberHandlePtr, + C.c_float) + + +# Returns the width of the video format. + get_video_format_width = __tisgrabber.IC_GetVideoFormatWidth + get_video_format_width.restype = C.c_int + get_video_format_width.argtypes = (GrabberHandlePtr,) + +# returns the height of the video format. + get_video_format_height = __tisgrabber.IC_GetVideoFormatHeight + get_video_format_height.restype = C.c_int + get_video_format_height.argtypes = (GrabberHandlePtr,) + + +# Get the number of the available video formats for the current device. +# A video capture device must have been opened before this call. +# +# @param hGrabber The handle to the grabber object. +# +# @retval >= 0 Success +# @retval IC_NO_DEVICE No video capture device selected. +# @retval IC_NO_HANDLE No handle to the grabber object. +# +# @sa IC_GetVideoFormat + GetVideoFormatCount = __tisgrabber.IC_GetVideoFormatCount + GetVideoFormatCount.restype = C.c_int + GetVideoFormatCount.argtypes = (GrabberHandlePtr,) + +# Get a string representation of the video format specified by iIndex. +# iIndex must be between 0 and IC_GetVideoFormatCount(). +# IC_GetVideoFormatCount() must have been called before this function, +# otherwise it will always fail. +# +# @param hGrabber The handle to the grabber object. +# @param iIndex Number of the video format to be used. +# +# @retval Nonnull The name of the specified video format. +# @retval NULL An error occured. +# @sa IC_GetVideoFormatCount + GetVideoFormat = __tisgrabber.IC_GetVideoFormat + GetVideoFormat.restype = C.c_char_p + GetVideoFormat.argtypes = (GrabberHandlePtr, + C.c_int,) + +# Get the number of the available input channels for the current device. +# A video capture device must have been opened before this call. +# +# @param hGrabber The handle to the grabber object. +# +# @retval >= 0 Success +# @retval IC_NO_DEVICE No video capture device selected. +# @retval IC_NO_HANDLE No handle to the grabber object. +# +# @sa IC_GetInputChannel + GetInputChannelCount = __tisgrabber.IC_GetInputChannelCount + GetInputChannelCount.restype = C.c_int + GetInputChannelCount.argtypes = (GrabberHandlePtr,) + +# Get a string representation of the input channel specified by iIndex. +# iIndex must be between 0 and IC_GetInputChannelCount(). +# IC_GetInputChannelCount() must have been called before this function, +# otherwise it will always fail. +# @param hGrabber The handle to the grabber object. +# @param iIndex Number of the input channel to be used.. +# +# @retval Nonnull The name of the specified input channel +# @retval NULL An error occured. +# @sa IC_GetInputChannelCount + GetInputChannel = __tisgrabber.IC_GetInputChannel + GetInputChannel.restype = C.c_char_p + GetInputChannel.argtypes = (GrabberHandlePtr, + C.c_int,) + + +# Get the number of the available video norms for the current device. +# A video capture device must have been opened before this call. +# +# @param hGrabber The handle to the grabber object. +# +# @retval >= 0 Success +# @retval IC_NO_DEVICE No video capture device selected. +# @retval IC_NO_HANDLE No handle to the grabber object. +# +# @sa IC_GetVideoNorm + GetVideoNormCount = __tisgrabber.IC_GetVideoNormCount + GetVideoNormCount.restype = C.c_int + GetVideoNormCount.argtypes = (GrabberHandlePtr,) + + +# Get a string representation of the video norm specified by iIndex. +# iIndex must be between 0 and IC_GetVideoNormCount(). +# IC_GetVideoNormCount() must have been called before this function, +# otherwise it will always fail. +# +# @param hGrabber The handle to the grabber object. +# @param iIndex Number of the video norm to be used. +# +# @retval Nonnull The name of the specified video norm. +# @retval NULL An error occured. +# @sa IC_GetVideoNormCount + GetVideoNorm = __tisgrabber.IC_GetVideoNorm + GetVideoNorm.restype = C.c_char_p + GetVideoNorm.argtypes = (GrabberHandlePtr, + C.c_int,) + + + SetFormat = __tisgrabber.IC_SetFormat + SetFormat.restype = C.c_int + SetFormat.argtypes = (GrabberHandlePtr, + C.c_int,) + GetFormat = __tisgrabber.IC_GetFormat + GetFormat.restype = C.c_int + GetFormat.argtypes = (GrabberHandlePtr,) + + +# Start the live video. +# @param hGrabber The handle to the grabber object. +# @param iShow The parameter indicates: @li 1 : Show the video @li 0 : Do not show the video, but deliver frames. (For callbacks etc.) +# @retval IC_SUCCESS on success +# @retval IC_ERROR if something went wrong. +# @sa IC_StopLive + + StartLive = __tisgrabber.IC_StartLive + StartLive.restype = C.c_int + StartLive.argtypes = (GrabberHandlePtr, + C.c_int,) + + StopLive = __tisgrabber.IC_StopLive + StopLive.restype = C.c_int + StopLive.argtypes = (GrabberHandlePtr,) + + + SetHWND = __tisgrabber.IC_SetHWnd + SetHWND.restype = C.c_int + SetHWND.argtypes = (GrabberHandlePtr, + C.c_int,) + + +# Snaps an image. The video capture device must be set to live mode and a +# sink type has to be set before this call. The format of the snapped images depend on +# the selected sink type. +# +# @param hGrabber The handle to the grabber object. +# @param iTimeOutMillisek The Timeout time is passed in milli seconds. A value of -1 indicates, that +# no time out is set. +# +# +# @retval IC_SUCCESS if an image has been snapped +# @retval IC_ERROR if something went wrong. +# @retval IC_NOT_IN_LIVEMODE if the live video has not been started. +# +# @sa IC_StartLive +# @sa IC_SetFormat + + SnapImage=__tisgrabber.IC_SnapImage + SnapImage.restype = C.c_int + SnapImage.argtypes = (GrabberHandlePtr, + C.c_int,) + + +# Retrieve the properties of the current video format and sink type +# @param hGrabber The handle to the grabber object. +# @param *lWidth This recieves the width of the image buffer. +# @param *lHeight This recieves the height of the image buffer. +# @param *iBitsPerPixel This recieves the count of bits per pixel. +# @param *format This recieves the current color format. +# @retval IC_SUCCESS on success +# @retval IC_ERROR if something went wrong. + + GetImageDescription = __tisgrabber.IC_GetImageDescription + GetImageDescription.restype = C.c_int + GetImageDescription.argtypes = (GrabberHandlePtr, + C.POINTER(C.c_long), + C.POINTER(C.c_long), + C.POINTER(C.c_int), + C.POINTER(C.c_int),) + + + + + GetImagePtr = __tisgrabber.IC_GetImagePtr + GetImagePtr.restype = C.c_void_p + GetImagePtr.argtypes = (GrabberHandlePtr,) + + +# ############################################################################ + ShowDeviceSelectionDialog = __tisgrabber.IC_ShowDeviceSelectionDialog + ShowDeviceSelectionDialog.restype = GrabberHandlePtr + ShowDeviceSelectionDialog.argtypes = (GrabberHandlePtr,) + +# ############################################################################ + + ShowPropertyDialog = __tisgrabber.IC_ShowPropertyDialog + ShowPropertyDialog.restype = GrabberHandlePtr + ShowPropertyDialog.argtypes = (GrabberHandlePtr,) + +# ############################################################################ + IsDevValid = __tisgrabber.IC_IsDevValid + IsDevValid.restype = C.c_int + IsDevValid.argtypes = (GrabberHandlePtr,) + +# ############################################################################ + + LoadDeviceStateFromFile = __tisgrabber.IC_LoadDeviceStateFromFile + LoadDeviceStateFromFile.restype = GrabberHandlePtr + LoadDeviceStateFromFile.argtypes = (GrabberHandlePtr,C.c_char_p) + +# ############################################################################ + SaveDeviceStateToFile = __tisgrabber.IC_SaveDeviceStateToFile + SaveDeviceStateToFile.restype = C.c_int + SaveDeviceStateToFile.argtypes = (GrabberHandlePtr,C.c_char_p) + + + GetCameraProperty = __tisgrabber.IC_GetCameraProperty + GetCameraProperty.restype = C.c_int + GetCameraProperty.argtypes = (GrabberHandlePtr, + C.c_int, + C.POINTER(C.c_long),) + + SetCameraProperty = __tisgrabber.IC_SetCameraProperty + SetCameraProperty.restype = C.c_int + SetCameraProperty.argtypes = (GrabberHandlePtr, + C.c_int, + C.c_long,) + + + SetPropertyValue = __tisgrabber.IC_SetPropertyValue + SetPropertyValue.restype = C.c_int + SetPropertyValue.argtypes = (GrabberHandlePtr, + C.c_char_p, + C.c_char_p, + C.c_int, ) + + + GetPropertyValue = __tisgrabber.IC_GetPropertyValue + GetPropertyValue.restype = C.c_int + GetPropertyValue.argtypes = (GrabberHandlePtr, + C.c_char_p, + C.c_char_p, + C.POINTER(C.c_long), ) + + +# ############################################################################ + SetPropertySwitch = __tisgrabber.IC_SetPropertySwitch + SetPropertySwitch.restype = C.c_int + SetPropertySwitch.argtypes= (GrabberHandlePtr, + C.c_char_p, + C.c_char_p, + C.c_int,) + + GetPropertySwitch = __tisgrabber.IC_GetPropertySwitch + GetPropertySwitch.restype = C.c_int + GetPropertySwitch.argtypes= (GrabberHandlePtr, + C.c_char_p, + C.c_char_p, + C.POINTER(C.c_long),) +# ############################################################################ + + IsPropertyAvailable = __tisgrabber.IC_IsPropertyAvailable + IsPropertyAvailable.restype = C.c_int + IsPropertyAvailable.argtypes= (GrabberHandlePtr, + C.c_char_p, + C.c_char_p,) + + PropertyOnePush = __tisgrabber.IC_PropertyOnePush + PropertyOnePush.restype = C.c_int + PropertyOnePush.argtypes = (GrabberHandlePtr, + C.c_char_p, + C.c_char_p, ) + + + SetPropertyAbsoluteValue = __tisgrabber.IC_SetPropertyAbsoluteValue + SetPropertyAbsoluteValue.restype = C.c_int + SetPropertyAbsoluteValue.argtypes = (GrabberHandlePtr, + C.c_char_p, + C.c_char_p, + C.c_float, ) + + GetPropertyAbsoluteValue = __tisgrabber.IC_GetPropertyAbsoluteValue + GetPropertyAbsoluteValue.restype = C.c_int + GetPropertyAbsoluteValue.argtypes = (GrabberHandlePtr, + C.c_char_p, + C.c_char_p, + C.POINTER(C.c_float), ) + + # definition of the frameready callback + FRAMEREADYCALLBACK = C.CFUNCTYPE(C.c_void_p,C.c_int, C.POINTER(C.c_ubyte), C.c_ulong, C.py_object ) + + # set callback function + SetFrameReadyCallback = __tisgrabber.IC_SetFrameReadyCallback + SetFrameReadyCallback.restype = C.c_int + SetFrameReadyCallback.argtypes = [GrabberHandlePtr, FRAMEREADYCALLBACK, C.py_object] + + SetContinuousMode = __tisgrabber.IC_SetContinuousMode + + SaveImage = __tisgrabber.IC_SaveImage + SaveImage.restype = C.c_int + SaveImage.argtypes = [C.c_void_p, C.c_char_p, C.c_int, C.c_int ] + + OpenVideoCaptureDevice = __tisgrabber.IC_OpenVideoCaptureDevice + OpenVideoCaptureDevice.restype = C.c_int + OpenVideoCaptureDevice.argtypes = [C.c_void_p, C.c_char_p] + +# ############################################################################ + + ### GK Additions - adding frame filters. Pieces copied from: https://github.com/morefigs/py-ic-imaging-control + + CreateFrameFilter = __tisgrabber.IC_CreateFrameFilter + CreateFrameFilter.restype = C.c_int + CreateFrameFilter.argtypes = (C.c_char_p, C.POINTER(FrameFilterHandle)) + + AddFrameFilter = __tisgrabber.IC_AddFrameFilterToDevice + AddFrameFilter.restype = C.c_int + AddFrameFilter.argtypes = (GrabberHandlePtr, C.POINTER(FrameFilterHandle)) + + FilterGetParameter = __tisgrabber.IC_FrameFilterGetParameter + FilterGetParameter.restype = C.c_int + FilterGetParameter.argtypes = (C.POINTER(FrameFilterHandle), + C.c_char_p, + C.c_void_p) + + FilterSetParameter = __tisgrabber.IC_FrameFilterSetParameterInt + FilterSetParameter.restype = C.c_int + FilterSetParameter.argtypes = (C.POINTER(FrameFilterHandle), + C.c_char_p, + C.c_int) + +# ############################################################################ + + +class TIS_CAM(object): + @property + def callback_registered(self): + return self._callback_registered + + def __init__(self): + + self._handle = C.POINTER(GrabberHandle) + self._handle = TIS_GrabberDLL.create_grabber() + self._callback_registered = False + self._frame = {'num' : -1, + 'ready' : False} + + def s(self,strin): + if sys.version[0] == "2": + return strin + if type(strin) == "byte": + return strin + return strin.encode("utf-8") + + def SetFrameReadyCallback(self, CallbackFunction, data): + """ Set a callback function, which is called, when a new frame arrives. + + CallbackFunction : The callback function + + data : a self defined class with user data. + """ + return TIS_GrabberDLL.SetFrameReadyCallback( self._handle, CallbackFunction, data ) + + def SetContinuousMode(self, Mode): + ''' Determines, whether new frames are automatically copied into memory. + + :param Mode: If 0, all frames are copied automatically into memory. This is recommened, if the camera runs in trigger mode. + If 1, then snapImages must be called to get a frame into memory. + :return: None + ''' + return TIS_GrabberDLL.SetContinuousMode(self._handle, Mode) + + def open(self,unique_device_name): + """ Open a device + + unique_device_name : The name and serial number of the device to be opened. The device name and serial number are separated by a space. + """ + test = TIS_GrabberDLL.open_device_by_unique_name(self._handle, + self.s(unique_device_name)) + + return test + + def close(self): + TIS_GrabberDLL.close_device(self._handle) + + def ShowDeviceSelectionDialog(self): + self._handle = TIS_GrabberDLL.ShowDeviceSelectionDialog(self._handle) + + def ShowPropertyDialog(self): + self._handle = TIS_GrabberDLL.ShowPropertyDialog(self._handle) + + def IsDevValid(self): + return TIS_GrabberDLL.IsDevValid(self._handle) + + def SetHWND(self, Hwnd): + return TIS_GrabberDLL.SetHWND(self._handle, Hwnd) + + def SaveDeviceStateToFile(self, FileName): + return TIS_GrabberDLL.SaveDeviceStateToFile(self._handle, self.s(FileName)) + + def LoadDeviceStateFromFile(self,FileName): + self._handle = TIS_GrabberDLL.LoadDeviceStateFromFile(self._handle,self.s(FileName)) + + + def SetVideoFormat(self,Format): + return TIS_GrabberDLL.set_videoformat(self._handle, self.s(Format)) + + def SetFrameRate(self,FPS): + return TIS_GrabberDLL.set_framerate(self._handle, FPS) + + def get_video_format_width(self): + return TIS_GrabberDLL.get_video_format_width(self._handle) + + def get_video_format_height(self): + return TIS_GrabberDLL.get_video_format_height(self._handle) + + + def GetDevices(self): + self._Devices=[] + iDevices = TIS_GrabberDLL.get_devicecount() + for i in range(iDevices): + self._Devices.append(TIS_GrabberDLL.get_unique_name_from_list(i)) + return self._Devices + + + def GetVideoFormats(self): + self._Properties=[] + iVideoFormats = TIS_GrabberDLL.GetVideoFormatCount(self._handle) + for i in range(iVideoFormats): + self._Properties.append(TIS_GrabberDLL.GetVideoFormat(self._handle,i)) + return self._Properties + + def GetInputChannels(self): + self.InputChannels=[] + InputChannelscount = TIS_GrabberDLL.GetInputChannelCount(self._handle) + for i in range (InputChannelscount): + self.InputChannels.append(TIS_GrabberDLL.GetInputChannel(self._handle,i)) + return self.InputChannels + + def GetVideoNormCount(self): + self.GetVideoNorm=[] + GetVideoNorm_Count=TIS_GrabberDLL.GetVideoNormCount(self._handle) + for i in range(GetVideoNorm_Count): + self.GetVideoNorm.append(TIS_GrabberDLL.GetVideoNorm(self._handle, i)) + return self.GetVideoNorm + + + def SetFormat(self, Format): + ''' SetFormat + Sets the pixel format in memory + @param Format Sinkformat enumeration + ''' + TIS_GrabberDLL.SetFormat(self._handle, Format.value) + + def GetFormat(self): + val = TIS_GrabberDLL.GetFormat(self._handle) + if val == 0: + return SinkFormats.Y800 + if val == 2: + return SinkFormats.RGB32 + if val == 1: + return SinkFormats.RGB24 + if val == 3: + return SinkFormats.UYVY + if val == 4: + return SinkFormats.Y16 + return SinkFormats.RGB24 + + + def StartLive(self, showlive = 1): + """ + Start the live video stream. + + showlive: 1 : a live video is shown, 0 : the live video is not shown. + """ + Error = TIS_GrabberDLL.StartLive(self._handle, showlive) + return Error + + def StopLive(self): + """ + Stop the live video. + """ + Error = TIS_GrabberDLL.StopLive(self._handle) + return Error + + + def SnapImage(self): + Error = TIS_GrabberDLL.SnapImage(self._handle, 2000) + return Error + + + def GetImageDescription(self): + lWidth=C.c_long() + lHeight= C.c_long() + iBitsPerPixel=C.c_int() + COLORFORMAT=C.c_int() + + Error = TIS_GrabberDLL.GetImageDescription(self._handle, lWidth, + lHeight,iBitsPerPixel,COLORFORMAT) + return (lWidth.value,lHeight.value,iBitsPerPixel.value,COLORFORMAT.value) + + def GetImagePtr(self): + ImagePtr = TIS_GrabberDLL.GetImagePtr(self._handle) + + return ImagePtr + + def GetImage(self): + BildDaten = self.GetImageDescription()[:4] + lWidth=BildDaten[0] + lHeight= BildDaten[1] + iBitsPerPixel=BildDaten[2]//8 + + buffer_size = lWidth*lHeight*iBitsPerPixel*C.sizeof(C.c_uint8) + img_ptr = self.GetImagePtr() + + Bild = C.cast(img_ptr, C.POINTER(C.c_ubyte * buffer_size)) + + + img = np.ndarray(buffer = Bild.contents, + dtype = np.uint8, + shape = (lHeight, + lWidth, + iBitsPerPixel)) + return img + + def GetImageEx(self): + """ Return a numpy array with the image data tyes + If the sink is Y16 or RGB64 (not supported yet), the dtype in the array is uint16, othereise it is uint8 + """ + BildDaten = self.GetImageDescription()[:4] + lWidth=BildDaten[0] + lHeight= BildDaten[1] + iBytesPerPixel=BildDaten[2]//8 + + buffer_size = lWidth*lHeight*iBytesPerPixel*C.sizeof(C.c_uint8) + img_ptr = self.GetImagePtr() + + Bild = C.cast(img_ptr, C.POINTER(C.c_ubyte * buffer_size)) + + pixeltype = np.uint8 + + if BildDaten[3] == 4: #SinkFormats.Y16: + pixeltype = np.uint16 + iBytesPerPixel = 1 + + img = np.ndarray(buffer = Bild.contents, + dtype = pixeltype, + shape = (lHeight, + lWidth, + iBytesPerPixel)) + return img + + + def GetCameraProperty(self,iProperty): + lFocusPos = C.c_long() + Error = TIS_GrabberDLL.GetCameraProperty(self._handle,iProperty, lFocusPos) + return (lFocusPos.value) + + def SetCameraProperty(self,iProperty,iValue): + Error = TIS_GrabberDLL.SetCameraProperty(self._handle,iProperty, iValue) + return (Error) + + def SetPropertyValue(self, Property, Element, Value ): + error = TIS_GrabberDLL.SetPropertyValue(self._handle, + self.s(Property), + self.s(Element), + Value) + return error + + + def GetPropertyValue(self, Property, Element ): + Value = C.c_long() + error = TIS_GrabberDLL.GetPropertyValue(self._handle, + self.s(Property), + self.s(Element), + Value) + return Value.value + + + + def PropertyAvailable(self, Property): + Null = None + error = TIS_GrabberDLL.IsPropertyAvailable(self._handle, + self.s(Property), + Null) + return error + + + def SetPropertySwitch(self, Property, Element, Value): + error = TIS_GrabberDLL.SetPropertySwitch(self._handle, + self.s(Property), + self.s(Element), + Value) + return error + + def GetPropertySwitch(self, Property, Element, Value): + lValue = C.c_long() + error = TIS_GrabberDLL.GetPropertySwitch(self._handle, + self.s(Property), + self.s(Element), + lValue) + Value[0] = lValue.value + return error + + def PropertyOnePush(self, Property, Element ): + error = TIS_GrabberDLL.PropertyOnePush(self._handle, + self.s(Property), + self.s(Element )) + return error + + def SetPropertyAbsoluteValue(self, Property, Element, Value ): + error = TIS_GrabberDLL.SetPropertyAbsoluteValue(self._handle, + self.s(Property), + self.s(Element), + Value) + return error + + def GetPropertyAbsoluteValue(self, Property, Element,Value ): + """ Get a property value of absolute values interface, e.g. seconds or dB. + Example code: + ExposureTime=[0] + Camera.GetPropertyAbsoluteValue("Exposure","Value", ExposureTime) + print("Exposure time in secods: ", ExposureTime[0]) + + :param Property: Name of the property, e.g. Gain, Exposure + :param Element: Name of the element, e.g. "Value" + :param Value: Object, that receives the value of the property + :returns: 0 on success + """ + lValue = C.c_float() + error = TIS_GrabberDLL.GetPropertyAbsoluteValue(self._handle, + self.s(Property), + self.s(Element), + lValue) + Value[0] = lValue.value + return error + + + def SaveImage(self,FileName, FileType, Quality=75): + ''' Saves the last snapped image. Can by of type BMP or JPEG. + :param FileName : Name of the mage file + :param FileType : Determines file type, can be "JPEG" or "BMP" + :param Quality : If file typ is JPEG, the qualitly can be given from 1 to 100. + :return: Error code + ''' + return TIS_GrabberDLL.SaveImage(self._handle, self.s(FileName), IC.ImageFileTypes[self.s(FileType)],Quality) + + def openVideoCaptureDevice(self, DeviceName): + ''' Open the device specified by DeviceName + :param DeviceName: Name of the device , e.g. "DFK 72AUC02" + :returns: 1 on success, 0 otherwise. + ''' + return TIS_GrabberDLL.OpenVideoCaptureDevice(self._handle, self.s(DeviceName)) + + def CreateFrameFilter(self, name): + frame_filter_handle = FrameFilterHandle() + + err = TIS_GrabberDLL.CreateFrameFilter(C.c_char_p(name), C.byref(frame_filter_handle)) + if err != 1: + raise Exception("ERROR CREATING FILTER") + return frame_filter_handle + + def AddFrameFilter(self, frame_filter_handle): + err = TIS_GrabberDLL.AddFrameFilter(self._handle, frame_filter_handle) + return err + + def FilterGetParameter(self, frame_filter_handle, parameter_name): + data = C.c_int() + + err = TIS_GrabberDLL.FilterGetParameter(frame_filter_handle, parameter_name, C.byref(data)) + return err + + def FilterSetParameter(self, frame_filter_handle, parameter_name, data): + if type(data) is int: + err = TIS_GrabberDLL.FilterSetParameter(frame_filter_handle, + C.c_char_p(parameter_name), + C.c_int(data)) + return err + else: + raise Exception('Unknown set parameter type') diff --git a/write_camera_details_TEMPLATE.py b/write_camera_details_TEMPLATE.py index 96aa942..ed91c0f 100644 --- a/write_camera_details_TEMPLATE.py +++ b/write_camera_details_TEMPLATE.py @@ -20,13 +20,13 @@ cam_0 = {'name' : 'Cog Rig', 'crop' : {'top' : 150, 'left' : 225, 'height' : 250, 'width' : 300}, 'rotate' : 0, - 'exposure' : -14, + 'exposure' : .003, 'output_dir' : 'C:/Users/user1/Desktop/video/RIG6_DATA/cog_rig/video'} cam_1 = {'name' : 'Neuro Rig', 'crop' : {'top' : 200, 'left' : 140, 'height' : 325, 'width' : 200}, 'rotate' : 90, - 'exposure' : -6, + 'exposure' : .003, 'output_dir' : 'C:/Users/user1/Desktop/video/RIG6_DATA/cog_rig/video'} subs = ['test1', 'test2', 'test3'] # optional, can manually enter subject for each session.