示例#1
0
def pims_transform_anime(global_config: dict, video_config: dict, video):
    """ Apply transformations to an anime video, using pims pipelines. """
    video = preprocess_anime(global_config, video_config, video)
    trans = [pims.pipeline(lambda img: resize(img, (ANIME_SIZE, ANIME_SIZE))),
             pims.pipeline(skimage.img_as_ubyte)
            ]
    return transform(trans, video)
示例#2
0
    def test_composed_pipelines(self):
        color_channel = pims.pipeline(_color_channel)
        rescale = pims.pipeline(_rescale)

        composed = rescale(color_channel(self.v, 0))

        expected = _rescale(_color_channel(self.v[0], 0))
        assert_image_equal(composed[0], expected)
示例#3
0
    def test_composed_pipelines(self):
        color_channel = pims.pipeline(_color_channel)
        rescale = pims.pipeline(_rescale)

        composed = rescale(color_channel(self.v, 0))

        expected = _rescale(_color_channel(self.v[0], 0))
        assert_image_equal(composed[0], expected)
示例#4
0
def processVideo(videoPath, outputFolder, shape='circle'):
    """
    Pipeline containing function to trim, mask and crop a video (provided by the process.csv file)
    shape: 'circle' or 'polygon'
    """

    print('processVideo called with: ', videoPath, outputFolder)
    outputFilename = os.path.join(
        outputFolder,
        os.path.split(videoPath)[-1].strip(".mp4") + "_processed.mp4")
    if os.path.exists(outputFilename):
        print(outputFilename, "already exists. Terminating!")
        return None

    # get the required data from the process.csv file
    df = pd.read_csv(os.path.join(os.path.split(videoPath)[0], "process.csv"),
                     index_col=0)
    start = df.loc[os.path.split(videoPath)[-1], 'start']
    end = df.loc[os.path.split(videoPath)[-1], 'end']

    # Shorten processed videos to 1h
    if end - start > 3600:
        end = 3600 + start

    if shape == 'circle':
        circle = literal_eval(df.loc[os.path.split(videoPath)[-1], 'circle'])
    # elif shape == 'polygon':
    #     vertices = np.array(literal_eval(df.loc[os.path.split(videoPath)[-1], 'vertices']))
    crop = literal_eval(df.loc[os.path.split(videoPath)[-1], 'crop'])

    video = pims.ImageIOReader(videoPath)
    fps = video.frame_rate

    # pipelines
    # masking pipeline
    masking_pipeline = pims.pipeline(maskFrame_circle)
    masking_kwargs = dict(circle=circle)
    masked_video = masking_pipeline(video, **masking_kwargs)
    # cropping pipeline
    cropping_pipeline = pims.pipeline(crop_frame)
    cropping_kwargs = dict(crop=crop)
    cropped_video = cropping_pipeline(masked_video, **cropping_kwargs)

    # writing to disk
    try:
        os.mkdir(outputFolder)
    except OSError:
        print(
            outputFolder,
            "already exists! Continuing with the process without creating it.")

    start_frame = int(start * fps)
    end_frame = int(end * fps)
    imageio.mimwrite(outputFilename,
                     cropped_video[start_frame:end_frame],
                     fps=fps)
    print('Completed: processVideo with parameters: ', videoPath, outputFolder)
示例#5
0
def maskVideo_rect(videoPath, outputFolder, reader='ImageIO'):
    """Function containing a pipeline which masks a desired ROI in a given video (provided by the maskROIs.csv file)
    and saves the result"""

    # get the maskCoords from the csv file
    df = pd.read_csv(os.path.join(os.path.split(videoPath)[0], "maskROIs.csv"),
                     index_col=0)
    maskCoords = tuple(df.loc[os.path.split(videoPath)[-1]])

    # reader
    if reader == 'ImageIO':
        video = pims.ImageIOReader(videoPath)
    elif reader == 'PyAV':
        video = pims.Video(videoPath)

    fps = video.frame_rate

    # pipeline
    r = maskCoords
    masking_pipeline = pims.pipeline(maskFrame_rect)
    kwargs = dict(maskCoords=r)
    processed_video = masking_pipeline(video, **kwargs)

    # writing to disk
    try:
        os.mkdir(outputFolder)
    except OSError:
        print(
            outputFolder,
            "already exists! Continuing with the process without creating it.")

    outputFilename = os.path.join(
        outputFolder,
        os.path.split(videoPath)[-1].strip(".mp4") + "_masked.mp4")
    imageio.mimwrite(outputFilename, processed_video, fps=fps)
def get_frames(file_path, frames, gaussian_filter_width=None, roi = None):
    """

    opens the video and returns the requested frames as numpy array

    Args:
        file_path: path to video file
        frames: integer or list of integers of the frames to be returned
        gaussian_filter_width: if not None apply Gaussian filter
        roi: region of interest, this allows to limit the search to a region of interest with the frame, the structure is
        roi = [roi_center, roi_dimension], where
            roi_center = [ro, co], roi_dimension = [h, w], where
            ro, co is the center of the roi (row, columns) and
            w, h is the width and the height of the roi

            Note that roi dimensions w, h should be odd numbers!


    """

    images = []
    if not hasattr(frames, '__len__'):
        frames = [frames]

    if not roi is None:
        [roi_center, roi_dimension] = roi

    v = pims.Video(file_path)
    video = rgb2gray_pipeline(v)

    if not gaussian_filter_width is None:
        gaussian_filter_pipeline = pipeline(gaussian_filter)
        video = gaussian_filter_pipeline(video, gaussian_filter_width)


    frame_shape = np.shape(video[frames[0]])



    for frame in frames:

        image = video[frame]

        # reduce image to roi
        if not roi is None:
            [roi_center, roi_dimension] = roi

            image_roi = image[
                        int(roi_center[0] - (roi_dimension[0] - 1) / 2): int(
                            roi_center[0] + (roi_dimension[0] + 1) / 2),
                        int(roi_center[1] - (roi_dimension[1] - 1) / 2): int(roi_center[1] + (roi_dimension[1] + 1) / 2)
                        ]
        else:
            image_roi = image

        images.append(image_roi)

    return images
示例#7
0
    def test_pipeline_with_args(self):
        color_channel = pims.pipeline(_color_channel)
        red = color_channel(self.v, 0)
        green = color_channel(self.v, 1)

        assert_image_equal(red[0], _color_channel(self.frame0, 0))
        assert_image_equal(green[0], _color_channel(self.frame0, 1))

        # Multiple pipelines backed by the same data are indep,
        # so this call to red is unaffected by green above.
        assert_image_equal(red[0], _color_channel(self.frame0, 0))
示例#8
0
    def test_pipeline_with_args(self):
        color_channel = pims.pipeline(_color_channel)
        red = color_channel(self.v, 0)
        green = color_channel(self.v, 1)

        assert_image_equal(red[0], _color_channel(self.frame0, 0))
        assert_image_equal(green[0], _color_channel(self.frame0, 1))

        # Multiple pipelines backed by the same data are indep,
        # so this call to red is unaffected by green above.
        assert_image_equal(red[0], _color_channel(self.frame0, 0))
示例#9
0
def transform_manga(config: dict, frames):
    """ Apply transformations to a sequence of manga pages. """
    # crop whitespace from the edges
    # top, bottom, left, right, color things
    box = config["crop"]
    trans = [lambda frames: pims.process.crop(frames,
                            ((box[0], box[1]), (box[2], box[3]), (0, 0))),
             # apply greyscale transformation
             pims.as_grey,
             # resize images
             pims.pipeline(lambda img: resize(img, (MANGA_SIZE, MANGA_SIZE))),
             to_ubyte
            ]
    return transform(trans, frames)
示例#10
0
    def export_video(self, filename=None, rate=None, **kwargs):
        """For a list of kwargs, see pims.export"""
        # TODO Save the canvas instead of the reader (including annotations)
        presets = dict(avi=dict(codec='libx264', quality=23),
                       mp4=dict(codec='mpeg4', quality=5),
                       mov=dict(codec='mpeg4', quality=5),
                       wmv=dict(codec='wmv2', quality=0.005))

        str_filter = ";;".join(['All files (*.*)',
                                'H264 video (*.avi)',
                                'MPEG4 video (*.mp4 *.mov)',
                                'Windows Media Player video (*.wmv)'])

        if filename is None:
            try:
                cur_dir = os.path.dirname(self.reader.filename)
            except AttributeError:
                cur_dir = ''
            filename = QtWidgets.QFileDialog.getSaveFileName(self,
                                                             "Export Movie",
                                                             cur_dir,
                                                             str_filter)
            if isinstance(filename, tuple):
                # Handle discrepancy between PyQt4 and PySide APIs.
                filename = filename[0]

        ext = os.path.splitext(filename)[-1]
        if ext[0] == '.':
            ext = ext[1:]
        try:
            _kwargs = presets[ext]
        except KeyError:
            raise ValueError("Extension '.{}' is not a known format.".format(ext))

        _kwargs.update(kwargs)

        if rate is None:
            try:
                rate = float(self.reader.frame_rate)
            except AttributeError or ValueError:
                rate = 25.

        self.reader.iter_axes = 't'
        self.status = 'Saving to {}'.format(filename)

        # PIMS v0.4 export() has a bug having to do with float precision
        # fix that here using limit_denominator() from fractions
        export(pipeline(to_rgb_uint8)(self.reader, autoscale=self.autoscale, force_color=self.force_color), filename,
               Fraction(rate).limit_denominator(66535), **kwargs)
        self.status = 'Done saving {}'.format(filename)
示例#11
0
    def test_pipeline_simple(self):
        rescale = pims.pipeline(_rescale)
        rescaled_v = rescale(self.v[:1])

        assert_image_equal(rescaled_v[0], _rescale(self.frame0))
示例#12
0
    def test_pipeline_simple(self):
        rescale = pims.pipeline(_rescale)
        rescaled_v = rescale(self.v[:1])

        assert_image_equal(rescaled_v[0], _rescale(self.frame0))
def extract_motion(filepath, target_path=None,  gaussian_filter_width=2, use_trackpy =False, show_progress = True,
                   trackpy_parameters = None, min_frames = 0, max_frames = None, roi = None, dynamic_roi = False, center_of_mass=False):
    """
    Takes in a bead video, and saves the bead's extracted position in every frame in a csv, and
    (optionally) an uncorrupted version of the video
    filepath: path to an avi file of the bead
    target_path: (optional) if None same as video path

    gaussian_filter_width: width (in pixels) of the gaussian used to smooth the video

    use_trackpy: if True use Trackpy to better localize the brightest point, need to provid trackpy_parameters

    show_progress: if True show progress (use when called from ipython notebook)

    trackpy_parameters: parameters for trackpy (only needed if use_trackpy is True)

    min_frames: first frame to analyze, usefull for debugging, if start from first frame
    max_frames: max number of frames to analyze, usefull for debugging, if none do entire video

    roi: region of interest, this allows to limit the search to a region of interest with the frame, the structure is
        roi = [roi_center, roi_dimension], where
            roi_center = [ro, co], roi_dimension = [h, w], where
            ro, co is the center of the roi (row, columns) and
            w, h is the width and the height of the roi

            Note that roi dimensions w, h should be odd numbers!
            Note that the order of the dimensions is vertical, horizontal, that is NOT x,y!

    dynamic_roi: if True, dynamically track the roi, ie. the center of the roi of the next frame is the detected position of the currenrt frame. If false the roi is static

    center_of_mass: calculate the position from the center of mass

    returns: path to .csv file
    """


    if target_path is None:
        target_path = os.path.dirname(filepath)

    assert os.path.isdir(target_path)

    if use_trackpy:
        assert 'diameter' in trackpy_parameters
        if not 'minmass' in trackpy_parameters:
            trackpy_parameters['minmass'] = None
        trackpy_parameters['missing_frames'] = []

    target_filename = os.path.join(target_path, os.path.basename(filepath).replace('.avi',  '_data_globalmax.csv'))

    v = pims.Video(filepath)
    processed_v = rgb2gray_pipeline(v)

    gaussian_filter_pipeline = pipeline(gaussian_filter)
    filtered = gaussian_filter_pipeline(processed_v, gaussian_filter_width)

    if max_frames is None:
        max_frames=len(filtered)
    else:
        # make sure max_frames is integer
        max_frames =int(max_frames)

    if show_progress:
        f = FloatProgress(min=min_frames, max=max_frames)  # instantiate the bar
        display(f)  # display the bar
    start_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print('start time:\t{:s}'.format(start_time))



    image_size = np.shape(filtered[0]) # size of image
    # find the maximum brightness pixel for every frame, corresponding to some consistent point at the bead
    max_coors = []
    skipped_frames_idx = []


    if not roi is None:

        [roi_center, roi_dimension] = roi

        for i in [0, 1]:
            # assert that roi fits in the image
            assert roi_center[i] + (roi_dimension[i]+1) / 2 <= image_size[i]
            assert roi_center[i] - (roi_dimension[i]+1) / 2 >= 0

            # assert that roi_dimension are odd
            assert roi_dimension[i] % 2 == 1

    cols = ['y bright', 'x bright']
    if center_of_mass:
        cols = cols + ['x com', 'y com']
    if use_trackpy:
        cols = cols + ['x tp', 'y tp']
        
    # we use range in this loop so that we can catch the CannotReadFrameError in the line where we try to access the next image
    for index in range(min_frames, max_frames):
        try:
            image = filtered[index]
        except CannotReadFrameError:
            skipped_frames_idx.append(index)

        po, roi = get_position(image, roi, dynamic_roi=dynamic_roi, center_of_mass=center_of_mass, use_trackpy=use_trackpy,
                         trackpy_parameters=trackpy_parameters)

        if po is None:
            trackpy_parameters['missing_frames'].append(index)
        else:
            max_coors.append(po)


        if index % 1000 == 0:
            if show_progress:
                f.value += 1000

        if not max_frames is None:
            if index>max_frames:
                break

    df = pd.DataFrame(max_coors, columns=cols)
    df.to_csv(target_filename)
    end_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print('end time:\t{:s}'.format(end_time))
    print('file written to:\n{:s}'.format(target_filename))


    info = {
        'filename_xy_position': target_filename,
        'image_size':np.shape(filtered[0]),
        'gaussian_filter_width':gaussian_filter_width,
        'N_frames':len(filtered),
        'use_trackpy':use_trackpy,
        'center_of_mass':center_of_mass,
        'start_time':start_time,
        'end_time':end_time,
        'max_frames':max_frames,
        'skipped_frames_idx':skipped_frames_idx,
        'N_skipped_frames': len(skipped_frames_idx),
        'roi' : roi
    }

    # convert time back to datetime so that we can calculate the duration
    start_time = datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
    end_time = datetime.datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
    info['extract. duration (min)'] = (end_time - start_time).seconds / 60


    if use_trackpy:
        info.update({
            'trackpy_parameters': trackpy_parameters
        })

    if info['N_skipped_frames']>100:
        print('WARNING: more than 100 frames corrupted in this video!!')

    return info
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import scipy.optimize as sopt
import glob

from tqdm import tqdm

import pims
from pims import pipeline
from skimage.color import rgb2gray
rgb2gray_pipeline = pipeline(rgb2gray)
from scipy.ndimage.filters import gaussian_filter
from scipy.ndimage.measurements import center_of_mass

import trackpy as tp
# status bar

from IPython.display import display

from imageio.core import CannotReadFrameError


import datetime
import yaml
import sys
import subprocess


示例#15
0
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import scipy.optimize as sopt
import pims
import scipy.spatial
import scipy.ndimage
from collections import Counter
import glob

import trackpy as tp
from pims import pipeline
from skimage.color import rgb2gray
rgb2gray_pipeline = pipeline(rgb2gray)


from joblib import Parallel, delayed
import multiprocessing
num_cores = multiprocessing.cpu_count()



def get_maxcoors(image, image_size):
    pixel_max = np.argmax(image)
    return(pixel_max%image_size, pixel_max/image_size)

def get_maxcoors_array(image_array, image_size):
    maxes  = []
    for image in image_array:
        pixel_max = np.argmax(image)