Source code for crappy.blocks.gpuve

# coding: utf-8

from time import time
import numpy as np
from typing import Callable

try:
  from pycuda.tools import make_default_context
  from pycuda.driver import init as cuda_init
except (ModuleNotFoundError, ImportError):
  def cuda_init():
    print("PyCUDA is could not be imported, cannot use GPUVE block")
    raise ModuleNotFoundError("pycuda")

from ..tool import GPUCorrel as GPUCorrel_tool
from .camera import Camera


[docs]class GPUVE(Camera): """An optical Videoextensometry measuring the displacement of small areas using GPU accelerated DIC. This block simply returns the displacement of each region along `x` and `y` in pixel. It will not return the strain as it does not know how the patches are arranged. It should be done by another block or a condition if necessary. Important: ``patches`` must be a :obj:`list` of :obj:`tuple` of length `4`. Each tuple contains the origin and the size of each patch along `Y` and `X` respectively (i.e. `Oy, Ox, Ly, Lx`). """ def __init__(self, camera: str, patches: list, save_folder: str = None, verbose: bool = False, labels: list = None, fps_label: str = False, img_name: str = "{self.loops:06d}_{t-self.t0:.6f}", ext: str = 'tiff', save_period: int = 1, save_backend: str = None, transform: Callable = None, input_label: str = None, config: bool = True, cam_kwargs: dict = None, **kwargs) -> None: self.ready = False cam_kw = {} self.patches = patches # Kwargs to be given to the camera BLOCK # ie save_folder, config, etc... but NOT the labels cam_kw['save_folder'] = save_folder cam_kw['verbose'] = verbose cam_kw['fps_label'] = fps_label cam_kw['img_name'] = img_name cam_kw['ext'] = ext cam_kw['save_period'] = save_period cam_kw['save_backend'] = save_backend cam_kw['transform'] = transform cam_kw['input_label'] = input_label cam_kw['config'] = config self.verbose = cam_kw['verbose'] # Also, we keep the verbose flag if cam_kwargs is not None: cam_kw.update(cam_kwargs) Camera.__init__(self, camera, **cam_kw) self.transform = cam_kw.get("transform") # Creating the tuple of labels (to name the outputs) if labels is not None: assert len(labels) == len(patches) * 2,\ "The number of labels must be twice the number of patches (x and y)" self.labels = ['t(s)'] + list(labels) # Else if we got a default field as a string, # use this string (ex: fields=('x', 'y', 'r', 'exx', 'eyy')) else: self.labels = ['t(s)'] + sum([ [f'p{i}x', f'p{i}y'] for i in range(len(patches))], []) # Handle res parameters: if true, also return the residual self.res = kwargs.get("res", True) if self.res: self.labels += ("res",) self.cam_kwargs = {} if cam_kwargs is None else cam_kwargs self.save_folder = save_folder self.save_period = 1 self.kwargs = kwargs
[docs] def prepare(self, *_, **__) -> None: cuda_init() self.context = make_default_context() Camera.prepare(self, send_img=False) t, img = self.camera.read_image() if self.transform is not None: img = self.transform(img) self.correl = [] for oy, ox, h, w in self.patches: self.correl.append(GPUCorrel_tool((h, w), fields=['x', 'y'], context=self.context, levels=1, **self.kwargs)) self.loops = 0 self.nloops = 50 for c, (oy, ox, h, w) in zip(self.correl, self.patches): if self.transform is not None: c.set_orig( self.transform(img[oy:oy + h, ox:ox + w]).astype(np.float32)) else: c.set_orig(img[oy:oy + h, ox:ox + w].astype(np.float32)) c.prepare() self.last_t = time() - 1 t, img = self.camera.read_image() if self.save_folder: self.save(img, self.save_folder + "img_ref_%.5f.tiff" % (t - self.t0))
def loop(self) -> None: if self.verbose and self.loops % self.nloops == 0: t = time() print("[VE block] processed", self.nloops / (t - self.last_t), "ips") self.last_t = t self.loops += 1 t, img = self.get_img() out = [t - self.t0] # + self.correl.get_disp( # self.transform(img).astype(np.float32)).tolist() for c, (oy, ox, h, w) in zip(self.correl, self.patches): if self.transform is not None: out.extend(c.get_disp(self.transform( img[oy:oy + h, ox:ox + w]).astype(np.float32)).tolist()) else: out.extend(c.get_disp( img[oy:oy + h, ox:ox + w].astype(np.float32)).tolist()) if self.res: pass # TODO self.send(out)