def get_jpg_from_bucket(id, regex_string): """ Retrieve JPG image from S3 bucket with given regex. :param id: movie identifier :param regex_string: regex to filter objects in bucket :return: Image """ movie = Movie.query.get(id) if not movie: raise ValueError("Invalid movie with identifier %s" % id) if not movie.file_bucket: raise ValueError("Movie does not have a S3 bucket assigned") s3 = utils.get_s3() bucket_name = movie.file_bucket # Get all snapshots from bucket. regex = re.compile(regex_string) file_objects = [ f for f in list( map(lambda f: f.key, s3.Bucket(bucket_name).objects.all())) if regex.match(f) ] if not len(file_objects): raise ValueError("Could not locate snapshot") # Get first extracted frame of the movie. file = s3.Object(bucket_name, sorted(file_objects)[0]).get() # Return file with content headers. response = make_response(file["Body"].read()) response.headers["Content-Type"] = "image/jpeg" return response
def get_velocity_vectors(id): """ Retrieve JSON object with velocity vectors from the NetCDF file for a specific movie. :param id: movie identifier :return: JSON object with velocity vectors """ movie = Movie.query.get(id) if not movie: raise ValueError("Invalid movie with identifier %s" % id) s3 = utils.get_s3() bucket_name = movie.file_bucket file_stream = io.BytesIO() s3.Object(bucket_name, "velocity_filter.nc").download_fileobj(file_stream) file_stream.seek(0) ds = xr.open_dataset(file_stream, engine="h5netcdf") # extract vectors and convert to Highchart data array u = ds["v_x"].median(dim="time") v = ds["v_y"].median(dim="time") data = xyla(u, v) return jsonify(data)
def _clean_files(bucket): """ Clean Up Movie .tif files :param movie: bucket :return: None """ s3 = utils.get_s3() prefix = "proj" s3.Bucket(bucket).objects.filter(Prefix=prefix).delete()
def receive_after_update(mapper, connection, target): """ Clean up S3 bucket and files when movie gets deleted. :param mapper: :param connection: :param target: """ if target.file_bucket: s3 = utils.get_s3() if s3.Bucket(target.file_bucket) in s3.buckets.all(): s3.Bucket(target.file_bucket).objects.delete() s3.Bucket(target.file_bucket).delete()
def _save_file(self, data, filename): s3 = utils.get_s3() self.base_path = uuid.uuid4().hex bucket = self.base_path # Create bucket if it doesn't exist yet. if s3.Bucket(bucket) not in s3.buckets.all(): s3.create_bucket(Bucket=bucket) else: raise ValidationError("Bucket already exists") s3.Bucket(bucket).Object(self.data.filename).put(Body=data.read()) return self.data.filename
def extract_frames(movie, prefix="frame", start_frame=0, end_frame=0, logger=logging): """ Extract raw frames, only lens correct using camera lensParameters, and store in RGB photos :param movie: dict containing movie information :param camera: dict, camera properties, such as lensParameters, name :param prefix="frame": str, prefix of file names, used in storage bucket, normally not changed by user :param logger=logging: logger-object :return: None """ # open S3 bucket s3 = utils.get_s3() n = 0 logger.info( f"Writing movie {movie['file']['identifier']} to {movie['file']['bucket']}" ) # open file from bucket in memory bucket = movie["file"]["bucket"] fn = movie["file"]["identifier"] # make a temporary file s3.Bucket(bucket).download_file(fn, fn) for _t, img in OpenRiverCam.io.frames( fn, start_frame=start_frame, end_frame=end_frame, lens_pars=movie["camera_config"]["camera_type"]["lensParameters"]): # filename in bucket, following template frame_{4-digit_framenumber}_{time_in_milliseconds}.jpg dest_fn = "{:s}_{:04d}_{:06d}.jpg".format(prefix, n, int(_t * 1000)) logger.debug(f"Write frame {n} in {dest_fn} to S3") # encode img ret, im_en = cv2.imencode(".jpg", img) buf = io.BytesIO(im_en) # Seek beginning of bytestream buf.seek(0) # Put file in bucket s3.Object(bucket, dest_fn).put(Body=buf) n += 1 # clean up of temp file os.remove(fn) # API request to confirm frame extraction is finished. requests.post("{}/processing/extract_frames/{}".format( os.getenv("ORC_API_URL"), movie["id"]))
def upload_file(fn, bucket, dest=None, logger=logging): """ Uploads BytesIO obj representation of data in file 'fn' in bucket :param fn: str, full local path to file containing movie :param bucket: str, name of bucket, if it does not exist, it will be created :param dest=None: str, name of file in bucket, if left as None, the file name is stripped from fn :param logger=logging: logger-object :return: None """ if dest is None: dest = os.path.split(os.path.abspath(fn))[1] s3 = utils.get_s3() # Create bucket if it doesn't exist yet. if s3.Bucket(bucket) not in s3.buckets.all(): s3.create_bucket(Bucket=bucket) s3.Bucket(bucket).upload_file(fn, dest) logger.info(f"{fn} uploaded in {bucket}")
def extract_project_frames(movie, prefix="proj", logger=logging): """ Extract frames, lens correct, greyscale correct and project to defined AOI with GCPs, water level and camera position Results in GeoTIFF files in desired projection and resolution within bucket defined in movie :param movie: dict, movie information :param prefix="proj": str, prefix of file names, used in storage bucket, normally not changed by user :param logger=logging: logger-object :return: None """ # open S3 bucket camera_config = movie["camera_config"] s3 = utils.get_s3() n = 0 logger.info( f"Writing movie {movie['file']['identifier']} to {movie['file']['bucket']}" ) # open file from bucket in memory bucket = movie["file"]["bucket"] fn = movie["file"]["identifier"] # make a temporary file s3.Bucket(bucket).download_file(fn, fn) for _t, img in OpenRiverCam.io.frames( fn, grayscale=True, lens_pars=camera_config["camera_type"]["lensParameters"]): # filename in bucket, following template frame_{4-digit_framenumber}_{time_in_milliseconds}.jpg dest_fn = "{:s}_{:04d}_{:06d}.tif".format(prefix, n, int(_t * 1000)) logger.debug(f"Write frame {n} in {dest_fn} to S3") bbox = shape( camera_config["aoi"]["bbox"]["features"][0] ["geometry"]) # extract the one and only geometry from geojson # reproject frame with camera_config # inputs needed corr_img, transform = OpenRiverCam.cv.orthorectification( img=img, lensPosition=camera_config["lensPosition"], h_a=movie["h_a"], bbox=bbox, resolution=camera_config["resolution"], **camera_config["gcps"], ) if len(corr_img.shape) == 3: # RGB image raster = np.int8(reshape_as_raster(corr_img)) else: # b-w image (0-255) just add an axis raster = np.int8(np.expand_dims(corr_img, axis=0)) # write to temporary file OpenRiverCam.io.to_geotiff( "temp.tif", raster, transform, crs=camera_config["site"]["crs"], compress="deflate", ) # Put file in bucket s3.Bucket(bucket).upload_file("temp.tif", dest_fn) n += 1 # finally write last frame as .jpg for front end and write geotransform as .csv dest_fn = "reprojection_preview.jpg" trans_fn = "reprojection_preview.transform" # file name for geotransform ret, im_en = cv2.imencode(".jpg", corr_img) buf = io.BytesIO(im_en) # Seek beginning of bytestream buf.seek(0) # Put file in bucket s3.Object(bucket, dest_fn).put(Body=buf) # write the geotransform buf = io.BytesIO(str(transform).encode()) buf.seek(0) s3.Object(bucket, trans_fn).put(Body=buf) # clean up of temp file os.remove(fn) logger.info(f"{fn} successfully reprojected into frames in {bucket}")
def filter_piv(movie, filter_temporal_kwargs={}, filter_spatial_kwargs={}, logger=logging): """ Filters a PIV velocity dataset (derived with compute_piv) with several temporal and spatial filter. This removes noise, isolated velocities in space and time, and moving features that are not likely to be water related. Input keyword arguments to the filters can be provided in the request, through several dictionaries. :param movie: dict, contains file dictionary and camera_config :param filter_temporal_kwargs: dict with the following possible kwargs for temporal filtering (+default values if not provided): kwargs_angle, dict, containing the following keyword args: angle_expected=0.5 * np.pi -- expected angle in radians of flow velocity measured from upwards, clock-wise. In OpenRiverCam this is always 0.5*pi because we make sure water flows from left to right angle_bounds=0.25 * np.pi -- the maximum angular deviation from expected angle allowed. Velocities that are outside this bound are masked kwargs_std, dict, containing following keyword args: tolerance=1.0 -- maximum allowed std/mean ratio in a pixel. Individual time steps outside this ratio are filtered out. kwargs_velocity, dict, containing following keyword args: s_min=0.1 -- minimum velocity expected to be measured by piv in m/s. lower velocities per timestep are filtered out s_max=5.0 -- maximum velocity expected to be measured by piv in m/s. higher velocities per timestep are filtered out kwargs_corr, dict, containing following keyword args: corr_min=0.4 -- minimum correlation needed to accept a velocity on timestep basis. Le Coz in FUDAA-LSPIV suggest 0.4 kwargs_neighbour, dict, containing followiung keyword args: roll=5 -- amount of time steps in rolling window (centred) tolerance=0.5 -- Relative acceptable velocity of maximum found within rolling window :param filter_spatial_kwargs: dict with the following possible kwargs for spatial filtering (+default values if not provided): kwargs_nan, dict, containing following keyword args: tolerance=0.8 -- float, amount of NaNs in search window measured as a fraction of total amount of values [0-1] stride=1 --int, stride used to determine relevant neighbours kwargs_median, dict, containing following keyword args: tolerance=0.7 -- amount of standard deviations tolerance stride=1 -- int, stride used to determine relevant neighbours :param logger: logging object :return: """ # open S3 bucket s3 = utils.get_s3() logger.info(f"Filtering surface velocities in {movie['file']['bucket']}") # open file from bucket in memory bucket = movie["file"]["bucket"] fn = "velocity.nc" s3.Bucket(bucket).download_file(fn, "temp.nc") logger.debug("applying temporal filters") ds = OpenRiverCam.piv.filter_temporal("temp.nc", **filter_temporal_kwargs) logger.debug("applying spatial filters") ds = OpenRiverCam.piv.filter_spatial(ds, **filter_spatial_kwargs) # remove original file os.remove("temp.nc") encoding = {var: {"zlib": True} for var in ds} # write gridded netCDF with filtered velocities netCDF ds.to_netcdf("temp.nc", encoding=encoding) s3.Bucket(bucket).upload_file("temp.nc", "velocity_filter.nc") os.remove("temp.nc") logger.info(f"velocity_filter.nc successfully written in {bucket}")
def compute_q(movie, v_corr=0.85, quantile=[0.05, 0.25, 0.5, 0.75, 0.95], logger=logging): """ compute velocities over provided bathymetric cross section points, depth integrated velocities and river flow over several quantiles. :param movie: dict, contains file dictionary and camera_config :param v_corr: float (range: 0-1, typically close to 1), correction factor from surface to depth-average (default: 0.85) :param quantile: float or list of floats (range: 0-1) (default: 0.5) :return: None """ encoding = {} # open S3 bucket s3 = utils.get_s3() logger.info( f"Extracting cross section from velocities in {movie['file']['bucket']}" ) # open file from bucket in memory bucket = movie["file"]["bucket"] fn = "velocity_filter.nc" s3.Bucket(bucket).download_file(fn, "temp.nc") # retrieve velocities over cross section only (ds_points has time, points as dimension) ds_points = OpenRiverCam.io.interp_coords( "temp.nc", *zip(*movie["bathymetry"]["coords"])) # add the effective velocity perpendicular to cross-section ds_points["v_eff"] = OpenRiverCam.piv.vector_to_scalar( ds_points["v_x"], ds_points["v_y"]) # get the required quantiles ds_points = ds_points.quantile(quantile, dim="time") # fill missing velocities with logarithmic profile fit ds_points["v_eff_fill"] = OpenRiverCam.piv.velocity_fill( ds_points["zcoords"], ds_points["v_eff"], movie["camera_config"]["gcps"]["z_0"], movie["h_a"]) # integrate over depth with vertical correction ds_points["q"] = OpenRiverCam.piv.depth_integrate( ds_points["zcoords"], ds_points["v_eff_fill"], movie["camera_config"]["gcps"]["z_0"], movie["h_a"], v_corr=v_corr, ) # integrate over the width of the cross-section Q = OpenRiverCam.piv.integrate_flow(ds_points["q"]) # extract a callback from Q Q_dict = { "discharge_q{:02d}".format(int(float(q) * 100)): float(Q.sel(quantile=q)) for q in Q["quantile"] } # overwrite gridded netCDF with cross section netCDF ds_points.to_netcdf("temp.nc", encoding=encoding) s3.Bucket(bucket).upload_file("temp.nc", "q_depth.nc") logger.info(f"q_depth.nc successfully written in {bucket}") # overwrite gridded netCDF with cross section netCDF Q.to_netcdf("temp.nc", encoding=encoding) s3.Bucket(bucket).upload_file("temp.nc", "Q.nc") os.remove("temp.nc") logger.info(f"Q.nc successfully written in {bucket}") return Q_dict
def compute_piv(movie, prefix="proj", piv_kwargs={}, logger=logging): """ compute velocities over frame pairs, choosing frame interval, start / end frame. :param movie: dict, contains file dictionary and camera_config :param prefix: str, prefix of geotiff files assumed to be present in bucket :param piv_kwargs: str, arguments passed to piv algorithm, parameters are defined in docstring of openpiv.pyprocess.extended_search_area_piv :param logger: logger object :return: None """ var_names = ["v_x", "v_y", "s2n", "corr"] var_attrs = [ { "standard_name": "sea_water_x_velocity", "long_name": "Flow element center velocity vector, x-component", "units": "m s-1", "coordinates": "lon lat", }, { "standard_name": "sea_water_y_velocity", "long_name": "Flow element center velocity vector, y-component", "units": "m s-1", "coordinates": "lon lat", }, { "standard_name": "ratio", "long_name": "signal to noise ratio", "units": "", "coordinates": "lon lat", }, { "standard_name": "correlation_coefficient", "long_name": "correlation coefficient between frames", "units": "", "coordinates": "lon lat", }, ] encoding = {var: {"zlib": True} for var in var_names} start_time = datetime.strptime(movie["timestamp"], "%Y-%m-%dT%H:%M:%SZ") resolution = movie["camera_config"]["resolution"] aoi_window_size = movie["camera_config"]["aoi_window_size"] # open S3 bucket s3 = utils.get_s3() n = 0 logger.info( f"Computing velocities from projected frames in {movie['file']['bucket']}" ) # open file from bucket in memory bucket = movie["file"]["bucket"] # get files with the right prefix fns = s3.Bucket(bucket).objects.filter(Prefix=prefix) frame_b = None ms = None time, v_x, v_y, s2n, corr = [], [], [], [], [] for n, fn in enumerate(fns): # store previous time offset _ms = ms # determine time offset of frame from filename ms = timedelta(milliseconds=int(fn.key[-10:-4])) frame_a = frame_b # buf = io.BytesIO() fn.Object().download_file("temp.tif") # buf.seek(0) frame_b = OpenRiverCam.piv.imread("temp.tif") # rewind to beginning of file if (frame_a is not None) and (frame_b is not None): # we have two frames in memory, now estimate velocity logger.debug(f"Processing frame {n}") # determine time difference dt between frames dt = (ms - _ms).total_seconds() cols, rows, _v_x, _v_y, _s2n, _corr = OpenRiverCam.piv.piv( frame_a, frame_b, res_x=resolution, res_y=resolution, dt=dt, search_area_size=aoi_window_size, **piv_kwargs, ) v_x.append(_v_x), v_y.append(_v_y), s2n.append(_s2n), corr.append( _corr) time.append(start_time + ms) os.remove("temp.tif") # finally read GeoTiff transform from the first file for fn in fns.limit(1): logger.info(f"Retrieving coordinates of grid from {fn.key}") buf = io.BytesIO() fn.Object().download_fileobj(buf) buf.seek(0) xs, ys, lons, lats = OpenRiverCam.io.convert_cols_rows(buf, cols, rows) # prepare local axes spacing_x = np.diff(cols[0])[0] spacing_y = np.diff(rows[:, 0])[0] x = np.linspace( resolution / 2 * spacing_x, (len(cols[0]) - 0.5) * resolution * spacing_x, len(cols[0]), ) y = np.flipud( np.linspace( resolution / 2 * spacing_y, (len(rows[:, 0]) - 0.5) * resolution * spacing_y, len(rows[:, 0]), )) # prepare dataset dataset = OpenRiverCam.io.to_dataset( [v_x, v_y, s2n, corr], var_names, x, y, time=time, lat=lats, lon=lons, xs=xs, ys=ys, attrs=var_attrs, ) # write to file and to bucket dataset.to_netcdf("temp.nc", encoding=encoding) s3.Bucket(bucket).upload_file("temp.nc", "velocity.nc") os.remove("temp.nc") logger.info(f"velocity.nc successfully written in {bucket}")
from glob import glob import asyncio from random import randint from turkit2.common import HumanIO from turkit2.primitive import IImage, OText, OChoice from utils import get_client, get_s3 s3 = get_s3() image_placeholder = IImage(s3, 'turkit-testing') client = get_client() session = randint(0, 100) caption_reps = 3 vote_reps = 3 verbosity = 100 suggest_captions = HumanIO( client, [('prompt', image_placeholder), ('answer', OText('answer'))], f'Caption an image - {session}', '0.10', 'Suggest a sentence that describes the image displayed.', 600, 6000) vote_captions = HumanIO(client, [('prompt', image_placeholder), ('answer', OChoice('answer'))], f'Vote on image captions - {session}', '0.05', 'Pick the caption that describes the image the best', 600, 6000) image_paths = glob('imgs/*')
import boto3 from utils import get_s3 from turkit2.primitive import IImage from context import turkit2 # Retrieve a bucket's ACL s3 = get_s3(profile='anthony') im = IImage(s3, 'turkit-testing') print(im.render('imgs/dog2.jpg'))