Exemple #1
0
def main():
    # Now we can use these new Ops in Scanner:
    db = Database()

    # Download an example video
    example_video_path = util.download_video()

    # Ingest it into the database
    [input_table], _ = db.ingest_videos([('example', example_video_path)],
                                        force=True)

    frame = db.sources.FrameColumn()

    resized_frame_fn = db.ops.resize_fn(frame=frame, width=640, height=480)

    resized_frame_class = db.ops.ResizeClass(frame=frame,
                                             width=320,
                                             height=240)

    output = db.sinks.FrameColumn(columns={
        'frame1': resized_frame_fn,
        'frame2': resized_frame_class
    })

    job = Job(op_args={
        frame: input_table.column('frame'),
        output: 'example_python_op'
    })

    [table] = db.run(output=output, jobs=[job], force=True)

    table.column('frame1').save_mp4('01_resized_fn')
    table.column('frame2').save_mp4('01_resized_class')

    print('Finished! Two videos were saved to the current directory: '
          '01_resized_fn.mp4, 01_resized_class.mp4')
from scannerpy import Database, Job

# The following performs the same computation as main.py, but now on a collection
# of videos instead of just one

db = Database()

# This is the list of videos we are going to process formatted as
# (table_name, video_path).
videos_to_process = [('sample-clip-1', 'sample-clip-1.mp4'),
                     ('sample-clip-2', 'sample-clip-2.mp4'),
                     ('sample-clip-3', 'sample-clip-3.mp4')]

# Ingest the videos into the database
db.ingest_videos(videos_to_process)

# Define the same Computation Graph
frame = db.sources.FrameColumn()  # Read from the database
sampled_frame = db.streams.Stride(frame, 3)  # Select every third frame
resized = db.ops.Resize(frame=sampled_frame, width=640,
                        height=480)  # Resize input frame
output_frame = db.sinks.Column(columns={'frame':
                                        resized})  # Save resized frame

# Create multiple jobs now, one for each video we want to process
jobs = []
for table_name, _ in videos_to_process:
    job = Job(
        op_args={
            frame: db.table(table_name).column(
                'frame'),  # Column to read input frames from
Exemple #3
0
port = sp.check_output('''
kubectl get svc/scanner-master -o json | \
jq '.spec.ports[0].nodePort' -r
''',
                       shell=True).strip().decode('utf-8')

master = '{}:{}'.format(ip, port)

print('Connecting to Scanner database...')
db = Database(master=master, start_cluster=False, config_path='./config.toml')

print('Running Scanner job...')
example_video_path = 'sample.mp4'
[input_table], _ = db.ingest_videos([('example', example_video_path)],
                                    force=True,
                                    inplace=True)

print(db.summarize())

frame = db.sources.FrameColumn()
r_frame = db.ops.Resize(frame=frame, width=320, height=240)
output_op = db.sinks.Column(columns={'frame': r_frame})
job = Job(op_args={
    frame: db.table('example').column('frame'),
    output_op: 'example_frame'
})

output_tables = db.run(output=output_op, jobs=[job], force=True)

output_tables[0].column('frame').save_mp4('resized_video')
Exemple #4
0
from scannerpy import Database, Job

# Ingest a video into the database
db = Database()
db.ingest_videos([('example_table', 'sample-clip.mp4')])

# Define a Computation Graph
frame = db.sources.FrameColumn()  # Read from the database
sampled_frame = db.ops.Stride(frame, 3)  # Select every third frame
resized = db.ops.Resize(frame=sampled_frame, width=640,
                        height=480)  # Resize input frame
output_frame = db.sinks.Column(columns={'frame':
                                        resized})  # Save resized frame

job = Job(
    op_args={
        frame: db.table('example_table').column(
            'frame'),  # Column to read input frames from
        output_frame: 'resized_example'  # Name of output table
    })

# Execute the computation graph and return a handle to the newly produced tables
output_tables = db.run(output=output_frame, jobs=[job], force=True)

# Save the resized video as an mp4 file
output_tables[0].column('frame').save_mp4('resized-video')
Exemple #5
0
def main(movie_path):
    total_start = time.time()

    print('Detecting shots in movie {}'.format(movie_path))
    movie_name = os.path.basename(movie_path)

    # Use GPU kernels if we have a GPU
    db = Database()

    print('Loading movie into Scanner database...')
    s = time.time()

    if db.has_gpu():
        device = DeviceType.GPU
    else:
        device = DeviceType.CPU

    ############ ############ ############ ############
    # 0. Ingest the video into the database
    ############ ############ ############ ############
    [movie_table], _ = db.ingest_videos([(movie_name, movie_path)], force=True)
    print('Time: {:.1f}s'.format(time.time() - s))
    print('Number of frames in movie: {:d}'.format(movie_table.num_rows()))

    s = time.time()
    ############ ############ ############ ############
    # 1. Run Histogram over the entire video in Scanner
    ############ ############ ############ ############
    print('Computing a color histogram for each frame...')
    frame = db.sources.FrameColumn()
    histogram = db.ops.Histogram(frame=frame, device=device)
    output = db.sinks.Column(columns={'histogram': histogram})
    job = Job(op_args={
        frame: movie_table.column('frame'),
        output: movie_name + '_hist'
    })
    [hists_table] = db.run(output=output, jobs=[job], force=True)
    print('\nTime: {:.1f}s, {:.1f} fps'.format(
        time.time() - s,
        movie_table.num_rows() / (time.time() - s)))

    s = time.time()
    ############ ############ ############ ############
    # 2. Load histograms and compute shot boundaries
    #    in python
    ############ ############ ############ ############
    print('Computing shot boundaries...')
    # Read histograms from disk
    hists = [
        h for h in hists_table.column('histogram').load(parsers.histograms)
    ]
    boundaries = compute_shot_boundaries(hists)
    print('Found {:d} shots.'.format(len(boundaries)))
    print('Time: {:.1f}s'.format(time.time() - s))

    s = time.time()
    ############ ############ ############ ############
    # 3. Create montage in Scanner
    ############ ############ ############ ############
    print('Creating shot montage...')

    row_length = min(16, len(boundaries))
    rows_per_item = 1
    target_width = 256

    # Compute partial row montages that we will stack together
    # at the end
    frame = db.sources.FrameColumn()
    gather_frame = frame.sample()
    sliced_frame = gather_frame.slice()
    montage = db.ops.Montage(frame=sliced_frame,
                             num_frames=row_length * rows_per_item,
                             target_width=target_width,
                             frames_per_row=row_length,
                             device=device)
    sampled_montage = montage.sample()
    output = db.sinks.Column(
        columns={'montage': sampled_montage.unslice().lossless()})

    item_size = row_length * rows_per_item

    starts_remainder = len(boundaries) % item_size
    evenly_divisible = (starts_remainder == 0)
    if not evenly_divisible:
        boundaries = boundaries[0:len(boundaries) - starts_remainder]

    job = Job(
        op_args={
            frame:
            movie_table.column('frame'),
            gather_frame:
            db.sampler.gather(boundaries),
            sliced_frame:
            db.partitioner.all(item_size),
            sampled_montage: [
                db.sampler.gather([item_size - 1])
                for _ in range(len(boundaries) / item_size)
            ],
            output:
            'montage_image'
        })
    [montage_table] = db.run(output=output, jobs=[job], force=True)

    # Stack all partial montages together
    montage_img = np.zeros((1, target_width * row_length, 3), dtype=np.uint8)
    for img in montage_table.column('montage').load():
        img = np.flip(img, 2)
        montage_img = np.vstack((montage_img, img))

    print('')
    print('Time: {:.1f}s'.format(time.time() - s))

    ############ ############ ############ ############
    # 4. Write montage to disk
    ############ ############ ############ ############
    cv2.imwrite('shots.jpg', montage_img)
    print('Successfully generated shots.jpg')
    print('Total time: {:.2f} s'.format(time.time() - total_start))
def main():
    db = Database()

    example_video_path = util.download_video()
    [input_table], _ = db.ingest_videos([('example', example_video_path)],
                                        force=True)

    videos = []

    # Many ops simply involve applying some processing to their inputs and then
    # returning their outputs. But there are also many operations in video
    # processing that require the ability to see adjacent frames (such as for
    # computing optical flow), need to keep state over time (such as for tracking
    # objects), or need to process multiple elements for efficiency reasons (such as
    # batching for DNNs).

    # Scanner ops therefore have several optional attributes that enable them to
    # support these forms of operations:

    # 1. Device Type:
    #   Ops can specify that they require CPUs or GPUs by declaring their device
    #   type. By default, the device_type is DeviceType.CPU.

    @scannerpy.register_python_op(device_type=DeviceType.CPU)
    def device_resize(config, frame: FrameType) -> FrameType:
        return cv2.resize(frame, (config.args['width'], config.args['height']))

    frame = db.sources.FrameColumn()
    resized_frame = db.ops.device_resize(frame=frame, width=640, height=480)
    output = db.sinks.FrameColumn(columns={'frame': resized_frame})

    job = Job(op_args={
        frame: input_table.column('frame'),
        output: 'example_resize'
    })

    [table] = db.run(output=output, jobs=[job], force=True)

    table.column('frame').save_mp4('02_device_resize')

    videos.append('02_device_resize.mp4')

    # 2. Batch:
    #   The Op can receive multiple elements at once to enable SIMD or
    #   vector-style processing.

    @scannerpy.register_python_op(batch=10)
    def batch_resize(config,
                     frame: Sequence[FrameType]) -> Sequence[FrameType]:
        output_frames = []
        for fr in frame:
            output_frames.append(
                cv2.resize(fr, (config.args['width'], config.args['height'])))
        return output_frames

    # Here we specify that the resize op should receive a batch of 10
    # input elements at once. Logically, each element is still processed
    # independently but multiple elements are provided to enable efficient
    # batch processing. If there are not enough elements left in a stream,
    # the Op may receive less than a batch worth of elements.

    frame = db.sources.FrameColumn()
    resized_frame = db.ops.batch_resize(frame=frame,
                                        width=640,
                                        height=480,
                                        batch=10)
    output = db.sinks.FrameColumn(columns={'frame': resized_frame})

    job = Job(op_args={
        frame: input_table.column('frame'),
        output: 'example_batch_resize'
    })

    [table] = db.run(output=output, jobs=[job], force=True)

    table.column('frame').save_mp4('02_batch_resize')

    videos.append('02_batch_resize.mp4')

    # 3. Stencil:
    #   The Op requires a window of input elements (for example, the
    #   previous and next element) at the same time to produce an
    #   output.

    # Here, we use the stencil attribute to write an optical flow op which
    # computes flow between the current and next frame.
    @scannerpy.register_python_op(stencil=[0, 1])
    def optical_flow(config, frame: Sequence[FrameType]) -> FrameType:
        gray1 = cv2.cvtColor(frame[0], cv2.COLOR_BGR2GRAY)
        gray2 = cv2.cvtColor(frame[1], cv2.COLOR_BGR2GRAY)
        flow = cv2.calcOpticalFlowFarneback(gray1, gray2, None, 0.5, 3, 15, 3,
                                            5, 1.2, 0)
        return flow

    # This op visualizes the flow field by converting it into an rgb image
    @scannerpy.register_python_op()
    def visualize_flow(config, flow: FrameType) -> FrameType:
        hsv = np.zeros(shape=(flow.shape[0], flow.shape[1], 3), dtype=np.uint8)
        hsv[..., 1] = 255

        mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
        hsv[..., 0] = ang * 180 / np.pi / 2
        hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
        rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
        return rgb

    frame = db.sources.FrameColumn()
    # This next line is using a feature we'll discuss in the next tutorial, but you
    # can think of it as selecting a subset of elements from the stream (here,
    # frames 0 to 30)
    range_frame = db.streams.Range(frame, 0, 30)
    flow = db.ops.optical_flow(frame=range_frame, stencil=[0, 1])
    flow_viz = db.ops.visualize_flow(flow=flow)
    output = db.sinks.FrameColumn(columns={'flow_viz': flow_viz})

    job = Job(op_args={
        frame: input_table.column('frame'),
        output: 'example_flow'
    })

    [table] = db.run(output=output, jobs=[job], force=True)

    table.column('flow_viz').save_mp4('02_flow')

    videos.append('02_flow.mp4')

    # 4. Bounded State:
    #   For each output, the Op requires at least W sequential
    #   "warmup" elements before it can produce a valid output.
    #   For example, if the output of this Op is sampled
    #   sparsely, this guarantees that the Op can "warmup"
    #   its state on a stream of W elements before producing the
    #   requested output.

    import subprocess

    @scannerpy.register_python_op(bounded_state=60)
    class BackgroundSubtraction(scannerpy.Kernel):
        def __init__(self, config):
            self.config = config
            self.alpha = config.args['alpha']
            self.thresh = config.args['threshold']

        # Reset is called when the kernel switches to a new part of the stream
        # and so shouldn't maintain it's previous state
        def reset(self):
            self.average_image = None

        def execute(self, frame: FrameType) -> FrameType:
            if self.average_image is None:
                self.average_image = frame

            mask = np.abs(frame - self.average_image) < 255 * self.thresh
            mask = np.any(mask, axis=2)

            masked_image = np.copy(frame)
            wmask = np.where(mask)
            masked_image[wmask[0], wmask[1], :] = 0

            self.average_image = (self.average_image * (1.0 - self.alpha) +
                                  frame * self.alpha)

            return masked_image

    # Here we wrote an op that performs background subtraction by keeping a
    # running average image over the past frames. We set `bounded_state=60`
    # to indicate that this kernel needs at least 60 frames before the output
    # should be considered reasonable.

    # First, we download a static camera video from youtube
    # subprocess.check_call(
    #     'youtube-dl -f 137 \'https://youtu.be/cVHqFqNz7eM\' -o test.mp4',
    #     shell=True)
    # [static_table], _ = db.ingest_videos([('static_video', 'test.mp4')],
    #                                     force=True)
    static_table = input_table

    # Then we perform background subtraction and indicate we need 60 prior
    # frames to produce correct output
    frame = db.sources.FrameColumn()
    masked_frame = db.ops.BackgroundSubtraction(frame=frame,
                                                alpha=0.05,
                                                threshold=0.05,
                                                bounded_state=60)
    # Here, we say that we only want the outputs for this range of frames
    sampled_frame = db.streams.Range(masked_frame, 0, 120)
    output = db.sinks.Column(columns={'frame': sampled_frame})
    job = Job(op_args={
        frame: static_table.column('frame'),
        output: 'masked_video',
    })
    [table] = db.run(output=output, jobs=[job], force=True)

    table.column('frame').save_mp4('02_masked')

    videos.append('02_masked.mp4')

    # 5. Unbounded State:
    #     This Op will always process all preceding elements of
    #     its input streams before producing a requested output.
    #     This means that sampling operations after this Op
    #     can not change how many inputs it receives. In the next
    #     tutorial, we will show how this can be relaxed for
    #     sub-streams of the input.
    @scannerpy.register_python_op(unbounded_state=True)
    class Example(scannerpy.Kernel):
        def __init__(self, config):
            pass

        def reset(self):
            pass

        def execute(self, frame: FrameType) -> bytes:
            pass

    print('Finished! The following videos were written: {:s}'.format(
        ', '.join(videos)))
Exemple #7
0
def main():
    db = Database()

    example_video_path = util.download_video()
    [input_table], _ = db.ingest_videos([('example', example_video_path)],
                                        force=True)

    frame = db.sources.FrameColumn()

    # When working with bounded or unbounded stateful operations, it is sometimes
    # useful to introduce boundaries between sequences of frames which restrict
    # state being shared between them. For example, if you are tracking objects
    # in a movie, you likely do not want the same trackers when the camera changes
    # scenes since the objects you were tracking are no longer there!

    # Scanner provides support for limiting state propagation across frames through
    # "slicing" operations.
    sliced_frame = db.streams.Slice(frame, db.partitioner.all(50))
    # Here, we sliced the input frame stream into chunks of 50 elements. What this
    # means is that any ops which process 'sliced_frame' will *only* be able to
    # maintain state within each chunk of 50 elements.

    # For example, let's say we grab the background subtraction op from the previous
    # tutorial (02_op_attributes) and want to run it on a static camera video which
    # sometimes jumps forward in time:
    @scannerpy.register_python_op(bounded_state=60)
    class BackgroundSubtraction(scannerpy.Kernel):
        def __init__(self, config):
            self.config = config
            self.alpha = config.args['alpha']
            self.thresh = config.args['threshold']

        def reset(self):
            self.average_image = None

        def execute(self, frame: FrameType) -> FrameType:
            if self.average_image is None:
                self.average_image = frame

            mask = np.abs(frame - self.average_image) < 255 * self.thresh
            mask = np.any(mask, axis=2)

            masked_image = np.copy(frame)
            wmask = np.where(mask)
            masked_image[wmask[0], wmask[1], :] = 0

            self.average_image = (self.average_image * (1.0 - self.alpha) +
                                  frame * self.alpha)

            return masked_image

    # First, we download the static camera video from youtube
    # subprocess.check_call(
    #     'youtube-dl -f 137 \'https://youtu.be/cVHqFqNz7eM\' -o test.mp4',
    #     shell=True)
    # [static_table], _ = db.ingest_videos([('static_video', 'test.mp4')],
    #                                     force=True)
    static_table = input_table

    frame = db.sources.FrameColumn()

    # Imagine that there are scene changes at frames 1100, 1200, and 1500, To tell
    # scanner that we do not want background subtraction to cross these boundaries,
    # we can create a 'partitioner' which splits the input.
    scene_partitions = db.partitioner.ranges([(1100, 1200), (1200, 1500)])

    # Now we slice the input frame sequence into these two partitions using a
    # slice operation
    sliced_frame = db.streams.Slice(frame, partitioner=scene_partitions)

    # Then we perform background subtraction and indicate we need 60 prior
    # frames to produce correct output
    masked_frame = db.ops.BackgroundSubtraction(frame=sliced_frame,
                                                alpha=0.02,
                                                threshold=0.05,
                                                bounded_state=60)
    # Since the background subtraction operation is done, we can unslice the
    # sequence to join it back into a single contiguous stream. You must unslice
    # sequences before feeding them back into sinks
    unsliced_frame = db.streams.Unslice(masked_frame)

    output = db.sinks.Column(columns={'frame': unsliced_frame})
    job = Job(op_args={
        frame: static_table.column('frame'),
        output: '04_masked_video',
    })
    [table] = db.run(output=output, jobs=[job], force=True)

    table.column('frame').save_mp4('04_masked')

    videos = []
    videos.append('04_masked.mp4')

    print('Finished! The following videos were written: {:s}'.format(
        ', '.join(videos)))
Exemple #8
0
        return frame


if len(sys.argv) <= 1:
    print('Usage: main.py <video_file>')
    exit(1)

movie_path = sys.argv[1]
print('Detecting poses in video {}'.format(movie_path))
movie_name = os.path.splitext(os.path.basename(movie_path))[0]

db = Database()
video_path = movie_path
if not db.has_table(movie_name):
    print('Ingesting video into Scanner ...')
    db.ingest_videos([(movie_name, video_path)], force=True)
input_table = db.table(movie_name)

sampler = db.streams.Range
sampler_args = {'start': 120, 'end': 480}

[poses_table] = pipelines.detect_poses(db, [input_table.column('frame')],
                                       sampler, sampler_args,
                                       '{:s}_poses'.format(movie_name))

print('Drawing on frames...')
frame = db.sources.FrameColumn()
sampled_frame = sampler(frame)
poses = db.sources.Column()
drawn_frame = db.ops.PoseDraw(frame=sampled_frame, poses=poses)
output = db.sinks.Column(columns={'frame': drawn_frame})
Exemple #9
0
import subprocess
import cv2
import sys
import os.path
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../..')
import util
import numpy as np

util.download_video()

db = Database()

video_path = util.download_video()
if True or not db.has_table('example'):
    print('Ingesting video into Scanner ...')
    db.ingest_videos([('example', video_path)], force=True)

input_table = db.table('example')

descriptor = NetDescriptor.from_file(db, 'nets/faster_rcnn_coco.toml')
caffe_args = db.protobufs.CaffeArgs()
caffe_args.net_descriptor.CopyFrom(descriptor.as_proto())
caffe_args.batch_size = 1

frame = db.ops.FrameInput()
caffe_frame = db.ops.CaffeInput(frame=frame,
                                args=caffe_args,
                                device=DeviceType.CPU)
cls_prob, rois, fc7 = db.ops.FasterRCNN(caffe_input=caffe_frame,
                                        args=caffe_args,
                                        device=DeviceType.GPU)
Exemple #10
0
        masked_image = np.copy(frame)
        wmask = np.where(mask)
        masked_image[wmask[0], wmask[1], :] = 0

        self.average_image = (self.average_image * (1.0 - self.alpha) +
                              frame * self.alpha)

        return masked_image


# First, we download the static camera video from youtube
subprocess.check_call(
    'youtube-dl -f 137 \'https://youtu.be/cVHqFqNz7eM\' -o test.mp4',
    shell=True)
[static_table], _ = db.ingest_videos([('static_video', 'test.mp4')],
                                     force=True)

frame = db.sources.FrameColumn()

# We know that there are scene change at frames 5100, 5400, and 5730, To tell
# scanner that we do not want background subtraction to cross these boundaries,
# we can create a 'partitioner' which splits the input. For demonstration, we
# are going to split into only two sequences (5100, 5350) and (5400, 5830).
scene_partitions = db.partitioner.ranges([(5100, 5350), (5400, 5830)])
# Since the second sequence (5400, 5830) has a scene change in it at frame 5730,
# we will see smearing in the output video.

# Now we slice the input frame sequence into these two partitions using a
# slice operation
sliced_frame = db.streams.Slice(frame, partitioner=scene_partitions)
import sys
import os.path

sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/..')
import util

################################################################################
# This tutorial provides an overview of the more advanced features of Scanner  #
# ops and when you would want to use them.                                     #
################################################################################

db = Database()

example_video_path = util.download_video()
[input_table], _ = db.ingest_videos([('example', example_video_path)],
                                    force=True)

videos = []

# Many ops simply involve applying some processing to their inputs and then
# returning their outputs. But there are also many operations in video
# processing that require the ability to see adjacent frames (such as for
# computing optical flow), need to keep state over time (such as for tracking
# objects), or need to process multiple elements for efficiency reasons (such as
# batching for DNNs).

# Scanner ops therefore have several optional attributes that enable them to
# support these forms of operations:

# 1. Device Type:
#   Ops can specify that they require CPUs or GPUs by declaring their device
Exemple #12
0
# This file shows a sample end-to-end pipeline that ingests a video into       #
# Scanner, runs a computation, and extracts the results.                       #
################################################################################

# Initialize a connection to the Scanner database. Loads configuration from the
# ~/.scanner.toml configuration file.
db = Database()

# Create a Scanner table from our video in the format (table name,
# video path). If any videos fail to ingest, they'll show up in the failed
# list. If force is true, it will overwrite existing tables of the same
# name.
example_video_path = util.download_video()
[input_table
 ], failed = db.ingest_videos([('example', example_video_path),
                               ('thisshouldfail', 'thisshouldfail.mp4')],
                              force=True)

print(db.summarize())
print('Failures:', failed)

# Scanner processes videos by forming a graph of operations that operate
# on input frames from a table and produce outputs to a new table.

# FrameColumn declares that we want to read from a table column that
# represents a video frame.
frame = db.sources.FrameColumn()

# These frames are input into a Histogram op that computes a color histogram
# for each frame.
hist = db.ops.Histogram(frame=frame)
Exemple #13
0
        # result = np.dstack((template, template, template))*255

        out = rgb.astype(np.uint8)
        return out



movie_path = '/home/krematas/Mountpoints/grail/data/barcelona/test.mp4'
print('Detecting faces in movie {}'.format(movie_path))
movie_name = os.path.splitext(os.path.basename(movie_path))[0]

mask_path = '/home/krematas/Mountpoints/grail/data/barcelona/mask.mp4'
db = Database()
print('Ingesting video into Scanner ...')
input_tables, failed = db.ingest_videos([(movie_name, movie_path), ('mask', mask_path)], force=True)

print(db.summarize())
print('Failures:', failed)

cam_data = np.load('/home/krematas/Mountpoints/grail/data/barcelona/calib/00114.npy').item()


# db.register_op('Calibrate', [('frame', ColumnType.Video), ('mask', ColumnType.Video)], [('resized', ColumnType.Video)])

# Custom Python kernels for ops reside in a separate file, here calibrate_kernel.py.
# cwd = '/home/krematas/code/scanner/examples/apps/soccer'
# db.register_python_kernel('Calibrate', DeviceType.CPU, cwd + '/calibrate_kernel.py')

frame = db.sources.FrameColumn()
mask = db.sources.FrameColumn()
Exemple #14
0
from scannerpy import Database, DeviceType, Job
from scannerpy.stdlib import parsers
import os.path as osp
import numpy as np

db = Database()

if not db.has_table('example'):
    db.ingest_videos([('example', 'example.mp4')])
input_table = db.table('example')

frame, frame_info = input_table.as_op().all(warmup_size = 1)

flow = db.ops.OpticalFlow(
    frame = frame, frame_info = frame_info,
    device=DeviceType.GPU)

job = Job(columns = [flow, frame_info], name = 'example_flows')

output_table = db.run(job)

vid_flows = [flow for _, flow in output_table.load(['flow', 'frame_info'], parsers.flow)]
np.save('flows.npy', vid_flows)
Exemple #15
0
def main():
    # Initialize a connection to the Scanner database. Loads configuration from the
    # ~/.scanner.toml configuration file.
    db = Database()

    # Create a Scanner table from our video in the format (table name,
    # video path). If any videos fail to ingest, they'll show up in the failed
    # list. If force is true, it will overwrite existing tables of the same
    # name.
    example_video_path = util.download_video()
    _, failed = db.ingest_videos([('example', example_video_path),
                                  ('example2', example_video_path),
                                  ('thisshouldfail', 'thisshouldfail.mp4')],
                                 force=True)

    print(db.summarize())
    print('Failures:', failed)

    # Scanner processes videos by forming a graph of operations that operate
    # on input frames from a table and produce outputs to a new table.

    # FrameColumn declares that we want to read from a table column that
    # represents a video frame.
    frame = db.sources.FrameColumn()

    # These frames are input into a Histogram op that computes a color histogram
    # for each frame.
    hist = db.ops.Histogram(frame=frame)

    # Finally, any columns provided to Output will be saved to the output
    # table at the end of the computation. Here, 'hist' is the name of the
    # column for the output table.
    output_op = db.sinks.Column(columns={'hist': hist})

    # A job defines a table you want to create. In op_args, we bind the
    # FrameColumn from above to the table we want to read from and name
    # the output table 'example_hist' by binding a string to output_op.
    job = Job(op_args={
        frame: db.table('example').column('frame'),
        output_op: 'example_hist'
    })

    job2 = Job(op_args={
        frame: db.table('example2').column('frame'),
        output_op: 'example_hist2'
    })

    # This executes the job and produces the output table. You'll see a progress
    # bar while Scanner is computing the outputs.
    output_tables = db.run(output=output_op, jobs=[job, job2], force=True)

    # Load the histograms from a column of the output table. The
    # readers.histograms function converts the raw bytes output by Scanner
    # into a numpy array for each channel.
    video_hists = output_tables[0].column('hist').load(readers.histograms)

    # Loop over the column's values, a set of 3 histograms (for each color channel) per element.
    num_rows = 0
    for frame_hists in video_hists:
        assert len(frame_hists) == 3
        assert frame_hists[0].shape[0] == 16
        num_rows += 1
    assert num_rows == db.table('example').num_rows()
Exemple #16
0
        '--video-path',
        type=str,
        required=True,
        help=('Path to video to process.'))

    args = p.parse_args()

    weights_path = args.weights_path
    config_path = args.config_path
    movie_path = args.video_path

    print('Detecting objects in movie {}'.format(movie_path))
    movie_name = os.path.splitext(os.path.basename(movie_path))[0]

    db = Database()
    [input_table], failed = db.ingest_videos(
        [('example', movie_path)], force=True)

    frame = db.sources.FrameColumn()
    strided_frame = db.streams.Range(frame, 0, 60)

    # Call the newly created object detect op
    cls_boxes, cls_segms, cls_keyps = db.ops.Detectron(
        frame=strided_frame,
        config_path=config_path,
        weights_path=weights_path,
        device=DeviceType.GPU)

    objdet_frame = db.ops.DetectronVizualize(
       frame=strided_frame,
       cls_boxes=cls_boxes,
       cls_segms=cls_segms,
Exemple #17
0
from scannerpy import Database, Job

db = Database()

# Ingest a video into the database
# The input is formatted as a list of (table_name, video_path).
db.ingest_videos([('sample-clip', 'sample-clip.mp4')], force=True)

# Define a Computation Graph
frame = db.sources.FrameColumn()  # Read from the database
sampled_frame = db.streams.Stride(frame, 3)  # Select every third frame
resized = db.ops.Resize(frame=sampled_frame, width=640,
                        height=480)  # Resize input frame
output_frame = db.sinks.Column(columns={'frame':
                                        resized})  # Save resized frame

# Bind arguments to the source and sink nodes
job = Job(
    op_args={
        frame: db.table(table_name).column(
            'frame'),  # Column to read input frames from
        output_frame: 'resized-{:s}'.format(table_name)  # Name of output table
    })

# Execute the computation graph and return a handle to the newly produced tables
output_tables = db.run(output=output_frame, jobs=[job], force=True)

# Save the resized video as an mp4 file
output_tables[0].column('frame').save_mp4(output_tables[0].name())
Exemple #18
0
import os.path as osp
import numpy as np
import time
import sys

if len(sys.argv) <= 1:
    print('Usage: main.py <video_file>')
    exit(1)

video_path = sys.argv[1]
print('Performing optical flow on {}...'.format(video_path))
video_name = os.path.splitext(os.path.basename(video_path))[0]

db = Database()
if not db.has_table(video_name):
    db.ingest_videos([(video_name, video_path)])
input_table = db.table(video_name)

frame = db.sources.FrameColumn()
flow = db.ops.OpticalFlow(
    frame = frame,
    device=DeviceType.CPU)
sampled_flow = db.streams.Range(flow, 0, 60)
output = db.sinks.Column(columns={'flow': sampled_flow})

job = Job(op_args={
    frame: input_table.column('frame'),
    output: input_table.name() + '_flow'
})
[output_table] = db.run(output=output, jobs=[job],
                        pipeline_instances_per_node=1, force=True)
Exemple #19
0
        image_paths = os.listdir(dir_name)
        image_paths = [os.path.join(dir_name, p) for p in image_paths]
        print('Ingesting images into Scanner ...')
        [input_table] = pipelines.ingest_images(db,
                                                image_paths,
                                                dir_name,
                                                force=True)
        table_name = dir_name
    elif os.path.isfile(sys.argv[1]):
        is_movie = True
        movie_path = sys.argv[1]
        print('Detecting faces in movie {}'.format(movie_path))
        movie_name = os.path.splitext(os.path.basename(movie_path))[0]

        print('Ingesting video into Scanner ...')
        [input_table], _ = db.ingest_videos([(movie_name, movie_path)],
                                            force=True)
        table_name = movie_name
    else:
        usage()
        exit(1)

    sampler = db.streams.All
    sampler_args = {}

    print('Detecting faces...')
    [bboxes_table] = pipelines.detect_faces(db, [input_table.column('frame')],
                                            sampler, sampler_args,
                                            table_name + '_faces')

    print('Drawing faces onto frames...')
    frame = db.sources.FrameColumn()