Beispiel #1
0
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
Beispiel #2
0
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)
Beispiel #3
0
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()
Beispiel #4
0
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()
Beispiel #5
0
    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
Beispiel #6
0
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"]))
Beispiel #7
0
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}")
Beispiel #8
0
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}")
Beispiel #9
0
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}")
Beispiel #10
0
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
Beispiel #11
0
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}")
Beispiel #12
0
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/*')
Beispiel #13
0
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'))