示例#1
0
    def save(self):
        # flush cached game
        if len(self.cur_game.hits) > 0:
            self.games.append(self.cur_game)

        self.process_game_data()
        self.save_highlights()
        output_path = '%s/%s.json' % (scv.config['path']['output'],
                                      self.video_id)
        with open(output_path, 'w') as fp:

            json.dump([game.__dict__ for game in self.games], fp)
            scv.log('Saved JSON data to %s' % output_path)
示例#2
0
    def save_highlights(self):
        i = 0
        fps = int(self.video.get(5))
        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        size = (int(self.video.get(3)), int(self.video.get(4)))
        videos = []

        for game in self.games:
            # save kills
            for death in game.deaths:
                patient = death[1]
                agent = int(
                    not patient)  # this won't support more than two players

                i += 1
                video_path = '%s/ko-%s-%s-%s-%d.avi' % (
                    scv.config['path']['output'], game.fighters[agent],
                    game.fighters[patient], self.video_id, i)
                videos.append((video_path, death[0] - 5000, death[0] + 1000))

            # save combos
            for combo in game.combos:
                patient = combo[2]
                agent = int(
                    not patient)  # this won't support more than two players

                i += 1
                video_path = '%s/combo-%s-%s-%s-%d.avi' % (
                    scv.config['path']['output'], game.fighters[agent],
                    game.fighters[patient], self.video_id, i)
                videos.append((video_path, combo[0] - 1000, combo[1] + 250))

            # save videos
            for i, video in enumerate(videos):
                scv.log(('Saving video', i, video[0]))
                writer = cv2.VideoWriter(video[0], fourcc, fps, size)
                self.video.set(0, video[1])
                while self.video.get(0) < video[2]:
                    ret, frame = self.video.read()
                    writer.write(frame)
                writer.release()
示例#3
0
    def detect_state_oog(self, src_im):
        im_gray = cv2.cvtColor(src_im, cv2.COLOR_BGR2GRAY)
        matches, conf, scale = self.match_template(im_gray,
                                                   tpl_ssel,
                                                   threshold=0.7)
        if matches:
            im_h, im_w = im_gray.shape
            im_cropped = im_gray[0:im_h, 0:int(im_w / 2)]
            stage, _res, conf = knn_stages.identify(im_cropped)

            self.cur_game.stage = stage
            scv.log((self.cur_frame, 'Entering stage', stage),
                    scv.DEBUG_EVENTS)
        else:
            # TODO: Possibly do something with character selection page?
            #	Can potentially extract player tags and costumes
            # matches, conf, scale = self.match_template(src_im, tpl_csel)
            # if matches:
            # 	scv.log(('Found charselect template', matches, conf, scale), scv.DEBUG_DETECT)
            pass

        return scv.State.unknown
示例#4
0
    def process_video(self):
        if not self.video.isOpened():
            raise ValueError('Video is not loaded')

        while self.video.isOpened():
            ret, frame = self.video.read()
            if not ret: break

            # Update position counters
            self.cur_time = int(self.video.get(0))
            self.cur_frame = int(self.video.get(1))
            progress = int((self.cur_frame / self.total_frames) * 100)
            if progress != self.cur_progress:
                self.cur_progress = progress
                scv.log('Progress: %d%%' % progress)

            new_state = self.detect_state(frame)
            if self.state != new_state:
                scv.log(('State changed from %s to %s' %
                         (self.state, new_state), self.cur_time),
                        scv.DEBUG_EVENTS)
                self.state = new_state

            # Show video if debug flag set.
            # Navigate video with arrows, space pauses, Q quits
            if scv.debug_level & scv.DEBUG_VIDEO:
                if self.paused:
                    scv.log(('Frame %d: %0.2fs' %
                             (self.cur_frame, float(self.cur_time) / 1000), ))

                cv2.imshow('Smash4CV', frame)

                key = cv2.waitKey(0 if self.paused else 1)
                if key == 113:  # q(uit)
                    break
                elif key == 32:  # space (pause/unpause)
                    self.paused = not self.paused
                elif key == 65361:  # left arrow
                    self.paused = True
                    self.video.set(1, self.cur_frame - 2)
                elif key == 65363:  # right arrow
                    self.paused = True
示例#5
0
    def detect_state(self, src_im):
        state = scv.State.unknown

        unknown_regions = 0
        if self.state == scv.State.ingame:
            # Continued in-game state
            for i, (x, y) in enumerate(self.regions):
                # Extract ROI
                x1 = int(x - (self.template_scale * 73))
                x2 = int(x + (self.template_scale * 75))
                y1 = int(y - (self.template_scale * 10))
                y2 = int(y + (self.template_scale * 61))
                region_im = src_im[y1:y2, x1:x2]

                region_im = cv2.resize(region_im, (100, 50))

                # Detect name if no good match yet
                if i not in self.cur_game.fighters:
                    name_im = region_im[40:50, 0:67]
                    name_im = cv2.cvtColor(name_im, cv2.COLOR_BGR2GRAY)
                    cv2.imshow('name', name_im)

                    name, _res, name_conf = knn_names.identify(name_im)
                    if name_conf <= 2000:
                        scv.log(('Detected fighter', i, name),
                                scv.DEBUG_DETECT)
                        self.cur_game.fighters[i] = name

                # Detect digits and compare
                digits_im = region_im[10:40, 30:100]
                digits = self.read_digits(digits_im)

                # Death must be detected continously for 15 frames to trigger
                if digits == scv.DETECT_DEAD:
                    self.death_cache[i] -= 1
                    if self.death_cache[i] > -15:
                        digits = scv.DETECT_UNKNOWN

                # Add event when changed
                if digits > scv.DETECT_UNKNOWN and digits != self.digit_cache[
                        i]:
                    if digits != scv.DETECT_DEAD:
                        self.death_cache[i] = 0
                        self.cur_game.hits.append((self.cur_time, i, digits))
                        scv.log(
                            (self.cur_frame, self.cur_game.fighters[i] if i
                             in self.cur_game.fighters else 'Fighter %d/%d' %
                             (i, len(self.regions)), '%d%%' % digits),
                            scv.DEBUG_EVENTS)
                    else:
                        self.cur_game.deaths.append((self.cur_time, i))
                        scv.log(
                            (self.cur_frame, self.cur_game.fighters[i] if i
                             in self.cur_game.fighters else 'Fighter %d/%d' %
                             (i, len(self.regions)), 'died'), scv.DEBUG_EVENTS)
                    self.digit_cache[i] = digits

                if digits == scv.DETECT_UNKNOWN:
                    unknown_regions += 1

                # Show ROIs while debugging
                if scv.debug_level & scv.DEBUG_VIDEO:
                    cv2.circle(src_im, (x, y), 4, (0, 255, 0), 2)
                    cv2.rectangle(src_im, (x1, y1), (x2, y2), (0, 0, 255), 1)

            state = scv.State.ingame

        if state != scv.State.ingame or unknown_regions == len(self.regions):
            im_gray = cv2.cvtColor(src_im, cv2.COLOR_BGR2GRAY)
            im_h, im_w = im_gray.shape
            is_loading = self.detect_state_loading(im_gray)

            if is_loading:
                if self.state != scv.State.loading:
                    # Entering loading state
                    if self.state == scv.State.ingame:
                        # Save any previously detected game
                        if len(self.cur_game.hits) > 0:
                            self.games.append(self.cur_game)

                        # Reset game state
                        self.cur_game = SmashGame(start=self.cur_time)

                    # Attempt to detect out-of-game state data from recent frame
                    self.video.set(1, self.cur_frame - 21)
                    ret, state_im = self.video.read()
                    detected_state = self.detect_state_oog(state_im)

                    # Reset video to original position
                    self.video.set(1, self.cur_frame + 1)

                else:
                    # In the middle of loading state
                    pass

                state = scv.State.loading
            elif self.state == scv.State.loading or self.state == scv.State.unknown:
                # Exiting loading state
                # Attempt to detect an in-game state in coming frame
                self.video.set(1, self.cur_frame + 29)
                ret, state_im = self.video.read()
                regions, scale = self.detect_state_ig(state_im)
                if regions:
                    # Initialize in-game state
                    self.regions = regions
                    self.template_scale = scale
                    self.digit_cache = [0] * len(regions)
                    self.death_cache = [0] * len(regions)

                    state = scv.State.ingame

                # Reset video to original position
                self.video.set(1, self.cur_frame + 1)

        return state