Ejemplo n.º 1
0
def get_mean_intensity():
    from tierpsy.analysis.compress.selectVideoReader import selectVideoReader
    video_file = '/Volumes/behavgenom_archive$/Avelino/screening/David_Miller/ATR/filter/atr_Ch1_04042017_150500.hdf5'
    #video_file = '/Volumes/behavgenom_archive$/Avelino/screening/David_Miller/ATR/filter/atr_Ch1_04042017_150500.mjpg'

    vid = selectVideoReader(video_file)
    video_stats = []
    tot_frames = 0
    while 1:
        ret, image = vid.read()
        if ret == 0:
            break
        
        tot_frames += 1
        print(tot_frames)
        
        if image.ndim == 3:
            image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
        
        dat = image[image>1]
        frame_stats = np.percentile(dat, [5, 50, 95])    
        video_stats.append(frame_stats)
    
    video_stats = np.array(video_stats)
    
    plt.plot(video_stats)
Ejemplo n.º 2
0
    def _init_buffer_video(self):
        ret = 1
        frame_n = 0


        vid = selectVideoReader(self.video_file)
        self.bgnd_buff = np.zeros((self.buff_size, vid.height, vid.width), vid.dtype)

        max_frames = self.buff_size*self.frame_gap
        while frame_n < max_frames:
            ret, image = vid.read()
            if ret==0:
                break
            
            if image.ndim == 3:
                image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
            
            if self._is_update_bgnd(frame_n):
                self.bgnd_ind = self._get_buf_ind(frame_n)
                self.bgnd_buff[self.bgnd_ind] = image

            #print(frame_n, self.bgnd_ind, self._is_update_bgnd(frame_n), self.frame_gap)
            
            frame_n += 1
        vid.release()

        self.last_frame = frame_n - 1

        if self.bgnd_ind is None:
            #no valid frames read
            self.bgnd_buff = None
        elif self.bgnd_ind<(self.bgnd_ind-1):
            #not many frames red
            self.bgnd_buff = self.bgnd_buff[:(self.bgnd_ind+1)]
def get_frame_from_raw(rawvidname):

    from tierpsy.analysis.compress.selectVideoReader import selectVideoReader

    vid = selectVideoReader(str(rawvidname))
    status, frame = vid.read_frame(0)
    assert status == 1, f'Something went wrong while reading {rawvidname}'
    return frame
def isGoodVideo(video_file):
    try:
        vid = selectVideoReader(video_file)
        # i have problems with corrupt videos that can create infinite loops...
        #it is better to test it before start a large taks
        vid.release()
        return True
    except OSError:
        # corrupt file, cannot read the size
        return False
Ejemplo n.º 5
0
    def init_buffer(self):
        ret = 1
        current_frame = 0

        vid = selectVideoReader(self.video_file)

        d_info = np.iinfo(vid.dtype)
        if self.is_light_background:
            init_value = d_info.min
        else:
            init_value = d_info.max

        self.buffer = np.full((self.buff_size, vid.height, vid.width),
                              init_value, vid.dtype)
        self.buffer_ind = -1

        max_frames = self.buff_size * self.frame_gap

        if vid.__class__.__name__ != 'readLoopBio':
            # for non-loopbio videos
            while current_frame < max_frames:
                ret, image = vid.read()
                #if not valid frame is returned return.
                if ret == 0:
                    break

                if image.ndim == 3:
                    image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

                if self.is_update_frame(current_frame):
                    self.update_buffer(image, current_frame)

                current_frame += 1
            self.last_frame = current_frame - 1

        else:
            # loopbio videos:
            for fc in range(self.buff_size):
                frame_to_read = fc * self.frame_gap
                ret, image = vid.read_frame(frame_to_read)
                # if not valid frame is returned return.
                if ret == 0:
                    break
                self.update_buffer(image, frame_to_read)
            self.last_frame = frame_to_read - self.frame_gap

        vid.release()

        if self.buffer_ind < 0:
            #no valid frames read
            self.buffer = None

        elif self.buffer_ind < (self.buff_size - 1):
            #not enough frames to fill the buffer, reduce its size
            self.buffer = self.buffer[:(self.buffer_ind + 1)]
Ejemplo n.º 6
0
    def _init_buffer(self):
        ret = 1
        frame_n = 0

        vid = selectVideoReader(self.video_file)


        d_info = np.iinfo(vid.dtype)
        if self.is_light_background:
            init_value = d_info.min
        else:
            init_value = d_info.max


        self._buffer = np.full((self.buff_size, vid.height, vid.width), init_value, vid.dtype)
        

        max_frames = self.buff_size*self.frame_gap
        while frame_n < max_frames:
            ret, image = vid.read()

            #if not valid frame is returned return.
            if ret == 0:
                break

            if image.ndim == 3:
                image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
            
            if self._is_update_bgnd(frame_n):
                if image.sum() == 0.:
                    #here i am assuming that if there is an old black image the video finished
                    break
                
                self._buffer_ind = self._get_buf_ind(frame_n)
                self._buffer[self._buffer_ind] = image

            frame_n += 1
        vid.release()

        self.last_frame = frame_n - 1

        if self._buffer_ind is None:
            #no valid frames read
            self._buffer = None
        
        elif self._buffer_ind<(self._buffer_ind-1):
            #not many frames red
            self._buffer = self._buffer[:(self._buffer_ind+1)]
Ejemplo n.º 7
0
def well_reader(hdf5_fname, well_name):
    """
    well_reader Generator yielding the image data of a well frame by frame

    Parameters
    ----------
    hdf5_fname : str or Path
        path to the hdf5 file
        (a masked metadata.hdf5 or a results metadata_featuresN.hdf5)
    well_name : str
        name of the well to read the data of

    Yields
    -------
    numpy array
        one frame cropped at the well's boundaries
    """
    # take hdf5 file and well name
    # get wall boundaries
    # find raw video
    # get the reader
    # while loop with generator returning only the right portion of the frame

    # read boundaries
    r_min, r_max, c_min, c_max = read_well_boundaries(hdf5_fname, well_name)

    # get raw video
    raw_fname = hdf52raw(hdf5_fname)
    assert os.path.exists(raw_fname), f'Cannot find {raw_fname}'

    # initalise reader
    vid = selectVideoReader(raw_fname)

    # start with reading a frame.
    # then at every iteration read the next one but do not return it yet
    # this avoids having an empty frame at the end when
    # the reader returns (0, None)
    status, image = vid.read()

    while status > 0:
        status, next_image = vid.read()
        roi = image[r_min:r_max, c_min:c_max].copy()
        # prep for next loop
        image = next_image
        yield roi
    def init_buffer(self):
        ret = 1
        current_frame = 0

        vid = selectVideoReader(self.video_file)
        
        d_info = np.iinfo(vid.dtype)
        if self.is_light_background:
            init_value = d_info.min
        else:
            init_value = d_info.max


        self.buffer = np.full((self.buff_size, vid.height, vid.width), init_value, vid.dtype)
        self.buffer_ind = -1

        max_frames = self.buff_size*self.frame_gap
        while current_frame < max_frames:
            ret, image = vid.read()
            #if not valid frame is returned return.
            if ret == 0:
                break

            if image.ndim == 3:
                image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
            
            if self.is_update_frame(current_frame):
                self.update_buffer(image, current_frame)
            
            current_frame += 1
        vid.release()

        self.last_frame = current_frame - 1

        if self.buffer_ind < 0:
            #no valid frames read
            self.buffer = None
        
        elif self.buffer_ind < (self.buff_size - 1):
            #not enough frames to fill the buffer, reduce its size
            self.buffer = self.buffer[:(self.buffer_ind+1)]
Ejemplo n.º 9
0
def compressVideo(video_file,
                  masked_image_file,
                  mask_param,
                  expected_fps=25,
                  microns_per_pixel=None,
                  bgnd_param={},
                  buffer_size=-1,
                  save_full_interval=-1,
                  max_frame=1e32,
                  is_extract_timestamp=False,
                  fovsplitter_param={}):
    '''
    Compresses video by selecting pixels that are likely to have worms on it and making the rest of
    the image zero. By creating a large amount of redundant data, any lossless compression
    algorithm will dramatically increase its efficiency. The masked images are saved as hdf5 with gzip compression.
    The mask is calculated over a minimum projection of an image stack. This projection preserves darker regions
    (or brighter regions, in the case of fluorescent labelling)
    where the worm has more probability to be located. Additionally it has the advantage of reducing
    the processing load by only requiring to calculate the mask once per image stack.
     video_file --  original video file
     masked_image_file --
     buffer_size -- size of the image stack used to calculate the minimal projection and the mask
     save_full_interval -- have often a full image is saved
     max_frame -- last frame saved (default a very large number, so it goes until the end of the video)
     mask_param -- parameters used to calculate the mask
    '''

    #get the default values if there is any bad parameter
    output = compress_defaults(masked_image_file,
                               expected_fps,
                               buffer_size=buffer_size,
                               save_full_interval=save_full_interval)

    buffer_size = output['buffer_size']
    save_full_interval = output['save_full_interval']

    if len(bgnd_param) > 0:
        is_bgnd_subtraction = True
        assert bgnd_param['buff_size'] > 0 and bgnd_param['frame_gap'] > 0
    else:
        is_bgnd_subtraction = False

    if len(fovsplitter_param) > 0:
        is_fov_tosplit = True
        assert all(key in fovsplitter_param
                   for key in ['total_n_wells', 'whichsideup', 'well_shape'])
        assert fovsplitter_param['total_n_wells'] > 0
    else:
        is_fov_tosplit = False

    # processes identifier.
    base_name = masked_image_file.rpartition('.')[0].rpartition(os.sep)[-1]

    # select the video reader class according to the file type.
    vid = selectVideoReader(video_file)

    # delete any previous  if it existed
    with tables.File(masked_image_file, "w") as mask_fid:
        pass

    #Extract metadata
    if is_extract_timestamp:
        # extract and store video metadata using ffprobe
        #NOTE: i cannot calculate /timestamp until i am sure of the total number of frames
        print_flush(base_name + ' Extracting video metadata...')
        expected_frames = store_meta_data(video_file, masked_image_file)

    else:
        expected_frames = 1

    # Initialize background subtraction if required

    if is_bgnd_subtraction:
        print_flush(base_name + ' Initializing background subtraction.')
        bgnd_subtractor = BackgroundSubtractorVideo(video_file, **bgnd_param)

    # intialize some variables
    max_intensity, min_intensity = np.nan, np.nan
    frame_number = 0
    full_frame_number = 0
    image_prev = np.zeros([])

    # Initialise FOV splitting if needed
    if is_bgnd_subtraction:
        img_fov = bgnd_subtractor.bgnd.astype(np.uint8)
    else:
        ret, img_fov = vid.read()
        # close and reopen the video, to restart from the beginning
        vid.release()
        vid = selectVideoReader(video_file)

    if is_fov_tosplit:
        # TODO: change class creator so it only needs the video name? by using
        # Tierpsy's functions such as selectVideoReader it can then read the first image by itself

        camera_serial = parse_camera_serial(masked_image_file)

        fovsplitter = FOVMultiWellsSplitter(img_fov,
                                            camera_serial=camera_serial,
                                            px2um=microns_per_pixel,
                                            **fovsplitter_param)
        wells_mask = fovsplitter.wells_mask
    else:
        wells_mask = None

    # initialize timers
    print_flush(base_name + ' Starting video compression.')

    if expected_frames == 1:
        progressTime = TimeCounter('Compressing video.')
    else:
        #if we know the number of frames display it in the progress
        progressTime = TimeCounter('Compressing video.', expected_frames)

    with tables.File(masked_image_file, "r+") as mask_fid:

        #initialize masks groups
        attr_params = dict(expected_fps=expected_fps,
                           microns_per_pixel=microns_per_pixel,
                           is_light_background=int(
                               mask_param['is_light_background']))
        mask_dataset, full_dataset, mean_intensity = initMasksGroups(
            mask_fid, expected_frames, vid.height, vid.width, attr_params,
            save_full_interval)

        if is_bgnd_subtraction:
            bg_dataset = createImgGroup(mask_fid,
                                        "/bgnd",
                                        1,
                                        vid.height,
                                        vid.width,
                                        is_expandable=False)
            bg_dataset[0, :, :] = img_fov

        if vid.dtype != np.uint8:
            # this will worm as flags to be sure that the normalization took place.
            normalization_range = mask_fid.create_earray(
                '/',
                'normalization_range',
                atom=tables.Float32Atom(),
                shape=(0, 2),
                expectedrows=expected_frames,
                filters=TABLE_FILTERS)

        while frame_number < max_frame:

            ret, image = vid.read()
            if ret != 0:
                # increase frame number
                frame_number += 1

                # opencv can give an artificial rgb image. Let's get it back to
                # gray scale.
                if image.ndim == 3:
                    image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

                if image.dtype != np.uint8:
                    # normalise image intensities if the data type is other
                    # than uint8
                    image, img_norm_range = normalizeImage(image)
                    normalization_range.append(img_norm_range)

                #limit the image range to 1 to 255, 0 is a reserved value for the background
                assert image.dtype == np.uint8
                image = np.clip(image, 1, 255)

                # Add a full frame every save_full_interval
                if frame_number % save_full_interval == 1:
                    full_dataset.append(image[np.newaxis, :, :])
                    full_frame_number += 1

                # buffer index
                ind_buff = (frame_number - 1) % buffer_size

                # initialize the buffer when the index correspond to 0
                if ind_buff == 0:
                    Ibuff = np.zeros((buffer_size, vid.height, vid.width),
                                     dtype=np.uint8)

                # add image to the buffer
                Ibuff[ind_buff, :, :] = image.copy()
                mean_int = np.mean(image)
                assert mean_int >= 0
                mean_intensity.append(np.array([mean_int]))

            else:
                # sometimes the last image is all zeros, control for this case
                if np.all(Ibuff[ind_buff] == 0):
                    frame_number -= 1
                    ind_buff -= 1

                # close the buffer
                Ibuff = Ibuff[:ind_buff + 1]

            # mask buffer and save data into the hdf5 file
            if (ind_buff == buffer_size - 1 or ret == 0) and Ibuff.size > 0:
                if is_bgnd_subtraction:
                    Ibuff_b = bgnd_subtractor.apply(Ibuff, frame_number)
                else:
                    Ibuff_b = Ibuff

                #calculate the max/min in the of the buffer
                img_reduce = reduceBuffer(Ibuff_b,
                                          mask_param['is_light_background'])

                mask = getROIMask(img_reduce,
                                  wells_mask=wells_mask,
                                  **mask_param)

                Ibuff *= mask

                # now apply the well_mask if is MWP
                if is_fov_tosplit:
                    fovsplitter.apply_wells_mask(
                        Ibuff)  # Ibuff will be modified after this

                # add buffer to the hdf5 file
                frame_first_buff = frame_number - Ibuff.shape[0]
                mask_dataset.append(Ibuff)

            if frame_number % 500 == 0:
                # calculate the progress and put it in a string
                progress_str = progressTime.get_str(frame_number)
                print_flush(base_name + ' ' + progress_str)

            # finish process
            if ret == 0:
                break

        # now that the whole video is read, we definitely have a better estimate
        # for its number of frames. so set the save_interval again
        if is_bgnd_subtraction:
            # bg_dataset._v_attrs['save_interval'] = len(vid)
            # the above line is not accurate when using ffmpeg,
            # it's just safer to do:
            bg_dataset._v_attrs['save_interval'] = mask_dataset.shape[0]

        # close the video
        vid.release()

    # save fovsplitting data
    if is_fov_tosplit:
        fovsplitter.write_fov_wells_to_file(masked_image_file)
        if fovsplitter.is_dubious:
            print(f'Check {masked_image_file} for plate alignment')

    read_and_save_timestamp(masked_image_file)
    print_flush(base_name + ' Compressed video done.')