Пример #1
0
 def parse(self, file):
     """
     :param file: path to a video file.
     :return: self
     """
     container = av.open(file)
     step = int(self.delay) # every 100 frames of video
     warn("Video delay: ", str(step))
     currentframe = 0
     for packet in container.demux():
         for frame in packet.decode():
             currentframe += 1
             if currentframe >= step:
                 self.images.append(misc.fromimage(frame.to_image()))
                 currentframe = 0
     return self
Пример #2
0
 def parse(self, file):
     """
     :param file: path to a video file.
     :return: self
     """
     container = av.open(file)
     step = int(self.delay)  # every 100 frames of video
     warn("Video delay: ", str(step))
     currentframe = 0
     for packet in container.demux():
         for frame in packet.decode():
             currentframe += 1
             if currentframe >= step:
                 self.images.append(misc.fromimage(frame.to_image()))
                 currentframe = 0
     return self
Пример #3
0
    def process(self, canvasimg, images, img_areas, allocs):
        """
        :param canvasimg: packed canvas img
        :param images: frames of animation
        :param img_areas: changes
        :param allocs: position of changes
        :return:
        """
        imgpath = os.path.join(self.path, "packed.png")
        # save packed image
        misc.imsave(imgpath, canvasimg)

        # try pngquant
        # Don't completely fail if we don't have pngcrush
        if os.system("pngquant --ext=.png --force %s" % imgpath) != 0:
            console.warn(
                "pngquant not found",
                'Try installing pngquant for better results (http://pngquant.org/)'
            )

        # Generate JSON to represent the data
        timeline = []
        for i in range(len(images)):
            src_rects = img_areas[i]
            dst_rects = allocs[i]

            blitlist = []

            for j in range(len(src_rects)):
                assert isinstance(j, object)
                metadata = computemeta(src_rects[j], dst_rects[j])
                blitlist.append(metadata)

            timeline.append(blitlist)

        metadata = {}
        metadata['size'] = {
            "width": timeline[0][0][2],
            "height": timeline[0][0][3]
        }
        metadata['frames'] = timeline
        filemeta = open(os.path.join(self.path, "timeline.json"), 'wb')
        timeline = json.dumps(metadata, filemeta)
        filemeta.write(bytes(timeline, 'UTF-8'))
        filemeta.close()

        filemeta = open(os.path.join(self.path, 'example/example.timeline.js'), 'wb')
        filemeta.write(bytes("_timeline = ", 'UTF-8'))
        timeline = json.dumps(metadata, filemeta)
        filemeta.write(bytes(timeline, 'UTF-8'))
        filemeta.close()

        shutil.copyfile(
            os.path.join(
                os.path.split(os.path.abspath(os.path.dirname(__file__)))[0],
                './player/example.html'
            ),
            os.path.join(self.path, 'example/example.html')
        )

        shutil.copyfile(
            os.path.join(
                os.path.split(os.path.abspath(os.path.dirname(__file__)))[0],
                '../../player/dist/jquery.html5anim.min.js'
            ),
            os.path.join(self.path, 'example/jquery.html5anim.min.js')
        )

        console.success('Animation generated.', 'Check out output path: %s' % self.path)
Пример #4
0
    def generate(self, export):
        """
        Generate from self.images[] animation and send it to export
        :param export: Export class
        :return:
        """
        zero = self.images[0] - self.images[0]
        pairs = zip([zero] + self.images[:-1], self.images)
        diffs = [sign((b - a).max(2)) for a, b in pairs]

        if self.talk:
            console.warn("Looking for diffs")
        # Find different objects for each frame
        img_areas = [me.find_objects(me.label(d)[0]) for d in diffs]

        # Simplify areas
        img_areas = [simplify(x, SIMPLIFICATION_TOLERANCE) for x in img_areas]

        if self.talk:
            console.warn("Areas found and simplified")

        ih, iw, _ = shape(self.images[0])

        # Generate a packed image
        allocator = Allocator2D(MAX_PACKED_HEIGHT, iw)
        packed = zeros((MAX_PACKED_HEIGHT, iw, 3), dtype=uint8)

        # Sort the rects to be packed by largest size first, to improve the packing
        rects_by_size = []
        for i in range(len(self.images)):
            src_rects = img_areas[i]
            for j in range(len(src_rects)):
                rects_by_size.append((slice_tuple_size(src_rects[j]), i, j))
        rects_by_size.sort(reverse=True)

        if self.talk:
            console.warn("Areas sorted by size")

        allocs = [[None] * len(src_rects) for src_rects in img_areas]

        console.warn(
            "Packing",
            "num rects: {0} num frames: {1}".format(len(rects_by_size),
                                                    len(self.images)))
        t0 = time()
        counter = 0
        for size, i, j in rects_by_size:
            src = self.images[i]
            src_rects = img_areas[i]

            a, b = src_rects[j]
            sx, sy = b.start, a.start
            w, h = b.stop - b.start, a.stop - a.start

            # finding matching rectangle is very expensive and its disabled for now.
            # existing = find_matching_rect(
            #  allocator.bitmap,
            #  allocator.num_used_rows,
            #  packed,
            #  src,
            #  sx,
            #  sy,
            #  w,
            #  h
            # )
            # if existing:
            #     dy, dx = existing
            #     allocs[i][j] = (dy, dx)
            # else:
            counter += 1
            if self.talk:
                console.warn(
                    "Allocation area ({0}/{1}): ".format(
                        counter, len(rects_by_size)),
                    "{0}x{1} ({2})".format(i, j, size))

            dy, dx = allocator.allocate(w, h)
            allocs[i][j] = (dy, dx)
            packed[dy:dy + h, dx:dx + w] = src[sy:sy + h, sx:sx + w]

        console.success("Packing finished", "took: %s" % (time() - t0))

        packed = packed[0:allocator.num_used_rows]
        export.process(packed, self.images, img_areas, allocs)
Пример #5
0
    def generate(self, export):
        """
        Generate from self.images[] animation and send it to export
        :param export: Export class
        :return:
        """
        zero = self.images[0] - self.images[0]
        pairs = zip([zero] + self.images[:-1], self.images)
        diffs = [sign((b - a).max(2)) for a, b in pairs]

        if self.talk:
            console.warn("Looking for diffs")
        # Find different objects for each frame
        img_areas = [me.find_objects(me.label(d)[0]) for d in diffs]

        # Simplify areas
        img_areas = [simplify(x, SIMPLIFICATION_TOLERANCE) for x in img_areas]

        if self.talk:
            console.warn("Areas found and simplified")

        ih, iw, _ = shape(self.images[0])

        # Generate a packed image
        allocator = Allocator2D(MAX_PACKED_HEIGHT, iw)
        packed = zeros((MAX_PACKED_HEIGHT, iw, 3), dtype=uint8)


        # Sort the rects to be packed by largest size first, to improve the packing
        rects_by_size = []
        for i in range(len(self.images)):
            src_rects = img_areas[i]
            for j in range(len(src_rects)):
                rects_by_size.append((slice_tuple_size(src_rects[j]), i, j))
        rects_by_size.sort(reverse=True)

        if self.talk:
            console.warn("Areas sorted by size")


        allocs = [[None] * len(src_rects) for src_rects in img_areas]

        console.warn(
            "Packing",
            "num rects: {0} num frames: {1}".format(
                len(rects_by_size),
                len(self.images)
            )
        )
        t0 = time()
        counter = 0
        for size, i, j in rects_by_size:
            src = self.images[i]
            src_rects = img_areas[i]

            a, b = src_rects[j]
            sx, sy = b.start, a.start
            w, h = b.stop - b.start, a.stop - a.start

            # finding matching rectangle is very expensive and its disabled for now.
            # existing = find_matching_rect(
            #  allocator.bitmap,
            #  allocator.num_used_rows,
            #  packed,
            #  src,
            #  sx,
            #  sy,
            #  w,
            #  h
            # )
            # if existing:
            #     dy, dx = existing
            #     allocs[i][j] = (dy, dx)
            # else:
            counter += 1
            if self.talk:
                console.warn("Allocation area ({0}/{1}): ".format(
                    counter,
                    len(rects_by_size)
                ), "{0}x{1} ({2})".format(i, j, size))

            dy, dx = allocator.allocate(w, h)
            allocs[i][j] = (dy, dx)
            packed[dy:dy+h, dx:dx+w] = src[sy:sy+h, sx:sx+w]

        console.success("Packing finished", "took: %s" % (time() - t0))

        packed = packed[0:allocator.num_used_rows]
        export.process(packed, self.images, img_areas, allocs)