def classify(self, video_path: str, data_home: str, output_path: str = None, compress_rate: float = 0.2, limit: int = None): # TODO model? cut_result_json = os.path.join(data_home, 'cut_result.json') res = None stable = None if os.path.isfile(cut_result_json): res = VideoCutResult.load(cut_result_json) stable, _ = res.get_range(limit=limit) cl = SVMClassifier(compress_rate=compress_rate) cl.load(data_home) cl.train() classify_result = cl.classify(video_path, stable) # --- draw --- r = Reporter() r.add_dir_link(data_home) r.draw( classify_result, report_path=os.path.join(output_path or data_home, 'report.html'), cut_result=res, )
def test_default(): # --- classify --- cl = SVMClassifier() cl.load(CUTTER_RESULT_DIR) cl.train() cl.save_model(MODEL_PATH, overwrite=True) cl.classify(VIDEO_PATH, boost_mode=False)
def _classify( video: typing.Union[str, VideoObject], data_home: str = None, model: str = None, # optional: these args below are sent for `cutter` compress_rate: float = 0.2, target_size: typing.Tuple[int, int] = None, limit_range: typing.List[VideoCutRange] = None, ) -> ClassifierResult: """ classify a video with some tagged pictures optional: if you have changed the default value in `cut`, you'd better keep them(offset and limit) equal. :param video: video path or object :param data_home: output path (dir) :param model: LinearSVC model (path) :param compress_rate: before_pic * compress_rate = after_pic. default to 0.2 :param target_size: (100, 200) :param limit_range: :return: typing.List[ClassifierResult] """ if isinstance(video, str): video = VideoObject(video) assert data_home or model, "classification should based on dataset or trained model" cl = SVMClassifier(compress_rate=compress_rate, target_size=target_size) if model: cl.load_model(model) else: cl.load(data_home) cl.train() return cl.classify(video, limit_range=limit_range)
def test_hook(): # init hook hook = ExampleHook() hook1 = ExampleHook(overwrite=True) hook2 = IgnoreHook(size=(0.5, 0.5), overwrite=True) frame_home = os.path.join(PROJECT_PATH, 'frame_save_dir') hook3 = FrameSaveHook(frame_home) hook4 = CropHook( size=(0.5, 0.5), offset=(0., 0.5), overwrite=True, ) hook5 = RefineHook() hook6 = InvalidFrameDetectHook() hook7 = TemplateCompareHook({ 'amazon': IMAGE_PATH, }) # --- cutter --- cutter = VideoCutter(compress_rate=0.8) # add hook cutter.add_hook(hook) cutter.add_hook(hook1) cutter.add_hook(hook2) cutter.add_hook(hook3) cutter.add_hook(hook4) cutter.add_hook(hook5) cutter.add_hook(hook6) cutter.add_hook(hook7) res = cutter.cut(VIDEO_PATH) stable, unstable = res.get_range() assert len(stable) == 2, 'count of stable range is not correct' data_home = res.pick_and_save( stable, 5, ) assert os.path.isdir(data_home), 'result dir not existed' # --- classify --- cl = SVMClassifier() cl.load(data_home) cl.train() classify_result = cl.classify(VIDEO_PATH, stable) # --- draw --- r = Reporter() report_path = os.path.join(data_home, 'report.html') r.draw( classify_result, report_path=report_path, cut_result=res, ) assert os.path.isfile(report_path) # hook check assert os.path.isdir(frame_home) assert hook6.result assert hook7.result
def test_save_and_load(): # test save and load cl = SVMClassifier() cl.load_model(MODEL_PATH) classify_result = cl.classify(VIDEO_PATH) # --- draw --- _draw_report(classify_result)
def test_work_with_cutter(): cl = SVMClassifier() cl.load_model(MODEL_PATH) stable, _ = cutter_res.get_range() classify_result = cl.classify(VIDEO_PATH, stable) # --- draw --- _draw_report(classify_result)
def test_keep_data(): cl = SVMClassifier() cl.load_model(MODEL_PATH) stable, _ = cutter_res.get_range() classify_result = cl.classify(VIDEO_PATH, stable, keep_data=True) # todo findit bug here image_object = toolbox.imread(IMAGE_PATH)[0:20, 0:20] assert classify_result.data[0].contain_image(image_object=image_object)
def one_step(self, video_path: str, output_path: str = None, threshold: float = 0.95, frame_count: int = 5, compress_rate: float = 0.2, offset: int = 3, limit: int = None): """ one step => cut, classifier, draw :param video_path: your video path :param output_path: output path (dir) :param threshold: float, 0-1, default to 0.95. decided whether a range is stable. larger => more unstable ranges :param frame_count: default to 5, and finally you will get 5 frames for each range :param compress_rate: before_pic * compress_rate = after_pic. default to 0.2 :param offset: it will change the way to decided whether two ranges can be merged before: first_range.end == second_range.start after: first_range.end + offset >= secord_range.start :param limit: ignore some ranges which are too short, 5 means ignore stable ranges which length < 5 :return: """ # --- cutter --- cutter = VideoCutter() res = cutter.cut(video_path, compress_rate=compress_rate) stable, unstable = res.get_range( threshold=threshold, limit=limit, offset=offset, ) data_home = res.pick_and_save(stable, frame_count, to_dir=output_path) res_json_path = os.path.join(data_home, 'cut_result.json') res.dump(res_json_path) # --- classify --- cl = SVMClassifier(compress_rate=compress_rate) cl.load(data_home) cl.train() classify_result = cl.classify(video_path, stable) # --- draw --- r = Reporter() r.draw( classify_result, report_path=os.path.join(data_home, 'report.html'), cut_result=res, # kwargs of get_range # otherwise these thumbnails may become different threshold=threshold, limit=limit, offset=offset, )
def test_result(): cl = SVMClassifier() cl.load_model(MODEL_PATH) stable, _ = cutter_res.get_range() classify_result = cl.classify(VIDEO_PATH, stable, keep_data=True) assert classify_result.to_dict() classify_result.mark_range(1, 3, "0") classify_result.mark_range_unstable(1, 3) classify_result.get_important_frame_list()
def test_default(): # --- classify --- cl = SVMClassifier() cl.load(CUTTER_RESULT_DIR) cl.train() cl.save_model(MODEL_PATH, overwrite=True) classify_result = cl.classify(VIDEO_PATH) # --- draw --- _draw_report(classify_result)
def test_dump_and_load(): cl = SVMClassifier() cl.load_model(MODEL_PATH) classify_result = cl.classify(VIDEO_PATH, boost_mode=False) json_path = "classify_result.json" classify_result.dump(json_path) res_from_file = ClassifierResult.load(json_path) assert classify_result.dumps() == res_from_file.dumps()
def test_save_and_load(): cl = SVMClassifier() cl.load_model(MODEL_PATH) classify_result = cl.classify(VIDEO_PATH) result_file = "save.json" reporter = Reporter() reporter.save(result_file, classify_result) assert os.path.isfile(result_file) classify_result_after = Reporter.load(result_file) assert len(classify_result) == len(classify_result_after) for i, j in zip(classify_result, classify_result_after): assert i.to_dict() == j.to_dict()
def test_result(): cl = SVMClassifier() cl.load_model(MODEL_PATH) stable, _ = cutter_res.get_range() classify_result = cl.classify(VIDEO_PATH, stable, keep_data=True) assert classify_result.to_dict() classify_result.mark_range(1, 3, "0") classify_result.mark_range_unstable(1, 3) classify_result.get_important_frame_list() classify_result.get_stage_range() classify_result.get_specific_stage_range("0") classify_result.get_not_stable_stage_range() assert classify_result.first("1").frame_id == 20 assert classify_result.last("1").frame_id == 21
def test_hook(): # init hook hook = ExampleHook() hook1 = ExampleHook() hook2 = IgnoreHook(size=(0.5, 0.5)) frame_home = os.path.join(PROJECT_PATH, "frame_save_dir") hook3 = FrameSaveHook(frame_home) hook4 = CropHook(size=(0.5, 0.5), offset=(0.0, 0.5)) hook5 = RefineHook() hook6 = InterestPointHook() hook7 = TemplateCompareHook({"amazon": IMAGE_PATH}) # --- cutter --- cutter = VideoCutter(compress_rate=0.9) # add hook cutter.add_hook(hook) cutter.add_hook(hook1) cutter.add_hook(hook2) cutter.add_hook(hook3) cutter.add_hook(hook4) cutter.add_hook(hook5) cutter.add_hook(hook6) cutter.add_hook(hook7) res = cutter.cut(VIDEO_PATH) stable, unstable = res.get_range() assert len(stable) == 2, "count of stable range is not correct" data_home = res.pick_and_save(stable, 5) assert os.path.isdir(data_home), "result dir not existed" # --- classify --- cl = SVMClassifier() cl.load(data_home) cl.train() classify_result = cl.classify(VIDEO_PATH, stable) # --- draw --- r = Reporter() report_path = os.path.join(data_home, "report.html") r.draw(classify_result, report_path=report_path, cut_result=res) assert os.path.isfile(report_path) # hook check assert os.path.isdir(frame_home) assert hook6.result assert hook7.result
def one_step(self, video_path: str, output_path: str = None, threshold: float = 0.95, frame_count: int = 5, compress_rate: float = 0.2, limit: int = None): """ one step => cut, classifier, draw :param video_path: your video path :param output_path: output path (dir) :param threshold: float, 0-1, default to 0.95. decided whether a range is stable. larger => more unstable ranges :param frame_count: default to 5, and finally you will get 5 frames for each range :param compress_rate: before_pic * compress_rate = after_pic. default to 0.2 :param limit: ignore some ranges which are too short, 5 means ignore stable ranges which length < 5 :return: """ # --- cutter --- cutter = VideoCutter() res = cutter.cut(video_path, compress_rate=compress_rate) stable, unstable = res.get_range( threshold=threshold, limit=limit, ) data_home = res.pick_and_save(stable, frame_count, to_dir=output_path) res_json_path = os.path.join(data_home, 'cut_result.json') res.dump(res_json_path) # --- classify --- cl = SVMClassifier(compress_rate=compress_rate) cl.load(data_home) cl.train() classify_result = cl.classify(video_path, stable) # --- draw --- r = Reporter() r.add_dir_link(data_home) r.draw( classify_result, report_path=os.path.join(data_home, 'report.html'), cut_result=res, )
def test_save_and_load(): cl = SVMClassifier() cl.load_model(MODEL_PATH) classify_result = cl.classify(VIDEO_PATH, boost_mode=False) result_file = "save.json" reporter = Reporter() reporter.add_extra("some_name", "some_value") reporter.save(result_file, classify_result) assert os.path.isfile(result_file) classify_result_after = Reporter.load(result_file) assert classify_result.get_length() == classify_result_after.get_length() for i, j in zip(classify_result.data, classify_result_after.data): assert i.to_dict() == j.to_dict() assert isinstance(reporter.get_stable_stage_sample(classify_result), np.ndarray)
def classify( video: typing.Union[str, VideoObject], data_home: str = None, model: str = None, # optional: these args below are sent for `cutter` compress_rate: float = 0.2, target_size: typing.Tuple[int, int] = None, offset: int = 3, limit: int = None, threshold: float = 0.95, ) -> ClassifierResult: """ classify a video with some tagged pictures optional: if you have changed the default value in `cut`, you'd better keep them(offset and limit) equal. :param video: video path or object :param data_home: output path (dir) :param model: LinearSVC model (path) :param compress_rate: before_pic * compress_rate = after_pic. default to 0.2 :param target_size: (100, 200) :param offset: it will change the way to decided whether two ranges can be merged before: first_range.end == second_range.start after: first_range.end + offset >= secord_range.start :param limit: ignore some ranges which are too short, 5 means ignore stable ranges which length < 5 :param threshold: cutter threshold :return: typing.List[ClassifierResult] """ if isinstance(video, str): video = VideoObject(video) assert data_home or model, "classification should based on dataset or trained model" cl = SVMClassifier(compress_rate=compress_rate, target_size=target_size) if model: cl.load_model(model) else: cl.load(data_home) cl.train() # re cut cut_result, _ = cut(video, compress_rate=compress_rate, threshold=threshold) stable, _ = cut_result.get_range(offset=offset, limit=limit) return cl.classify(video, stable)
def calculate_result(_cl, _SVM_or_Keras, _param, _from_movie_2_picture, _model_file, _video_path_for_forecast): if _SVM_or_Keras == '1\n': print('使用SVM进行预测') cl = SVMClassifier( # 默认情况下使用 HoG 进行特征提取。你可以将其关闭从而直接对原始图片进行训练与测试:feature_type='raw' feature_type="hog", # 默认为0.2,即将图片缩放为0.2倍。主要为了提高计算效率,如果你担心影响分析效果,可以将其提高 compress_rate=_param[0], ) # 加载待训练数据 cl.load_model(_model_file) elif _SVM_or_Keras == '2\n': # 分析视频_聚类 print('使用KerasClassifier进行预测') cl = KerasClassifier( compress_rate=_param[0], # 在使用时需要保证数据集格式统一(与训练集)。因为 train_model.py 用了 600x800,所以这里设定成一样的 # target_size=(600, 800), ) cl.load_model(_model_file) # 开始预测 _forecast_result = [] # 获取forecast文件夹的mp4文件列表 forecast_video_list = public_fun.get_mp4file_name(_video_path_for_forecast) for i in forecast_video_list: # 分析视频_切割视频 stable = get_data.get_range('forecast', i, _param, _from_movie_2_picture) classify_result = cl.classify(i, stable, keep_data=True) result_dict = classify_result.to_dict() _forecast_result.append( public_fun.write_result_to_local(i, _from_movie_2_picture, result_dict, classify_result)) # _forecast_result = [['5.mp4', '3.161888888888889', '1', # '4.155888888888889', '1', '8.040888888888889', '1']] return _forecast_result
def _train( data_home: str, save_to: str, compress_rate: float = 0.2, target_size: typing.Tuple[int, int] = None, ): """ build a trained model with a dataset :param data_home: output path (dir) :param save_to: model will be saved to this path :param compress_rate: before_pic * compress_rate = after_pic. default to 0.2 :param target_size: (100, 200) """ assert os.path.isdir(data_home), f"dir {data_home} not existed" assert not os.path.isfile(save_to), f"file {save_to} already existed" cl = SVMClassifier(compress_rate=compress_rate, target_size=target_size) cl.load(data_home) cl.train() cl.save_model(save_to)
def train_model_SVM(_train_picture_path, _model_file_name): cl = SVMClassifier( # 默认情况下使用 HoG 进行特征提取 # 你可以将其关闭从而直接对原始图片进行训练与测试:feature_type='raw' feature_type="hog", # 默认为0.2,即将图片缩放为0.2倍 # 主要为了提高计算效率 # 如果你担心影响分析效果,可以将其提高 compress_rate=0.2, # 或者直接指定尺寸 # 当压缩率与指定尺寸同时传入时,优先以指定尺寸为准 # target_size=(200, 400), ) # 加载待训练数据 cl.load(_train_picture_path) # 在加载数据完成之后需要先训练 cl.train() cl.save_model(_model_file_name, overwrite=True) return cl
def analyse( video: typing.Union[str, VideoObject], output_path: str, pre_load: bool = True, threshold: float = 0.98, offset: int = 3, boost_mode: bool = True, ): """ designed for https://github.com/williamfzc/stagesepx/issues/123 """ if isinstance(video, str): video = VideoObject(video, pre_load=pre_load) cutter = VideoCutter() res = cutter.cut(video) stable, unstable = res.get_range( threshold=threshold, offset=offset, ) with tempfile.TemporaryDirectory() as temp_dir: res.pick_and_save( stable, 5, to_dir=temp_dir, ) cl = SVMClassifier() cl.load(temp_dir) cl.train() classify_result = cl.classify(video, stable, boost_mode=boost_mode) r = Reporter() r.draw( classify_result, report_path=output_path, unstable_ranges=unstable, cut_result=res, )
def test_result(): cl = SVMClassifier() cl.load_model(MODEL_PATH) stable, _ = cutter_res.get_range() classify_result = cl.classify(VIDEO_PATH, stable, keep_data=True) assert classify_result.to_dict() classify_result.mark_range(1, 3, "0") classify_result.mark_range_unstable(1, 3) classify_result.get_important_frame_list() classify_result.get_stage_range() classify_result.get_specific_stage_range("0") classify_result.get_not_stable_stage_range() classify_result.mark_range_ignore(23, 24) classify_result.time_cost_between("0", "1") assert classify_result.contain("1") assert classify_result.first("1").frame_id == 20 assert classify_result.last("1").frame_id == 21 assert classify_result.is_order_correct(["0", "0", "1", "2"]) assert classify_result.is_order_correct(["0", "0", "2"]) assert classify_result.is_order_correct(["0", "1"]) assert classify_result.is_order_correct(["0", "2"]) assert classify_result.is_order_correct(["1", "2"])
def handle(self, video_path: str) -> bool: super(NormalHandler, self).handle(video_path) video = VideoObject(video_path) if self.preload: video.load_frames() # --- cutter --- cutter = VideoCutter() res = cutter.cut(video) stable, unstable = res.get_range(threshold=0.98, offset=3) data_home = res.pick_and_save(stable, self.frame_count, to_dir=self.result_path) # --- classify --- cl = SVMClassifier() cl.load(data_home) cl.train() self.classifier_result = cl.classify(video, stable) # --- draw --- r = Reporter() r.draw(self.classifier_result, report_path=self.result_report_path) return True
def run(config: typing.Union[dict, str]): """ run with config :param config: config file path, or a preload dict :return: """ class _VideoUserConfig(BaseModel): path: str pre_load: bool = True fps: int = None class _CutterUserConfig(BaseModel): threshold: float = None frame_count: int = None offset: int = None limit: int = None block: int = None # common compress_rate: float = None target_size: typing.Tuple[int, int] = None class _ClassifierType(Enum): SVM = "svm" KERAS = "keras" class _ClassifierUserConfig(BaseModel): boost_mode: bool = None classifier_type: _ClassifierType = _ClassifierType.SVM model: str = None # common compress_rate: float = None target_size: typing.Tuple[int, int] = None class _CalcOperatorType(Enum): BETWEEN = "between" DISPLAY = "display" class _CalcOperator(BaseModel): name: str calc_type: _CalcOperatorType args: dict = dict() class _CalcUserConfig(BaseModel): output: str = None ignore_error: bool = None operators: typing.List[_CalcOperator] = None class _ExtraUserConfig(BaseModel): save_train_set: str = None class UserConfig(BaseModel): output: str video: _VideoUserConfig cutter: _CutterUserConfig = _CutterUserConfig() classifier: _ClassifierUserConfig = _ClassifierUserConfig() calc: _CalcUserConfig = _CalcUserConfig() extras: _ExtraUserConfig = _ExtraUserConfig() if isinstance(config, str): # path config_path = pathlib.Path(config) assert config_path.is_file(), f"no config file found in {config_path}" # todo: support different types in the future assert config_path.as_posix().endswith( ".json"), "config file should be json format" with open(config_path, encoding=constants.CHARSET) as f: config = json.load(f) config = UserConfig(**config) logger.info(f"config: {config}") # main flow video = VideoObject( # fmt: off path=config.video.path, fps=config.video.fps, ) if config.video.pre_load: video.load_frames() # cut cutter = VideoCutter( # fmt: off compress_rate=config.cutter.compress_rate, target_size=config.cutter.target_size, ) res = cutter.cut( # fmt: off video=video, block=config.cutter.block, ) stable, unstable = res.get_range( # fmt: off threshold=config.cutter.threshold, offset=config.cutter.offset, ) with tempfile.TemporaryDirectory() as temp_dir: # classify if config.classifier.classifier_type is _ClassifierType.SVM: cl = SVMClassifier( # fmt: off compress_rate=config.classifier.compress_rate, target_size=config.classifier.target_size, ) elif config.classifier.classifier_type is _ClassifierType.KERAS: from stagesepx.classifier.keras import KerasClassifier cl = KerasClassifier( # fmt: off compress_rate=config.classifier.compress_rate, target_size=config.classifier.target_size, ) # validation has been applied by pydantic # so no `else` if config.classifier.model: # no need to retrain model_path = pathlib.Path(config.classifier.model) assert model_path.is_file(), f"file {model_path} not existed" cl.load_model(model_path) else: # train a new model train_set_dir = config.extras.save_train_set or temp_dir os.makedirs(train_set_dir, exist_ok=True) res.pick_and_save( # fmt: off stable, frame_count=config.cutter.frame_count, to_dir=train_set_dir, ) cl.train(data_path=train_set_dir) # start classifying classify_result = cl.classify( # fmt: off video, stable, boost_mode=config.classifier.boost_mode, ) # calc def _calc_display() -> dict: # jsonify return json.loads(classify_result.dumps()) def _calc_between(*, from_stage: str = None, to_stage: str = None) -> dict: assert classify_result.contain( from_stage), f"no stage {from_stage} found in result" assert classify_result.contain( to_stage), f"no stage {to_stage} found in result" from_frame = classify_result.last(from_stage) to_frame = classify_result.first(to_stage) cost = to_frame.timestamp - from_frame.timestamp return { "from": from_frame.frame_id, "to": to_frame.frame_id, "cost": cost, } _calc_func_dict = { _CalcOperatorType.BETWEEN: _calc_between, _CalcOperatorType.DISPLAY: _calc_display, } calc_output = config.calc.output if calc_output: output_path = pathlib.Path(calc_output) assert not output_path.is_file(), f"file {output_path} already existed" result = [] for each_calc in config.calc.operators: func = _calc_func_dict[each_calc.calc_type] try: func_ret = func(**each_calc.args) except Exception as e: if not config.calc.ignore_error: raise logger.warning(e) func_ret = traceback.format_exc() calc_ret = { "name": each_calc.name, "type": each_calc.calc_type.value, "result": func_ret, } result.append(calc_ret) with open(output_path, "w", encoding=constants.CHARSET) as f: json.dump(result, f) # draw r = Reporter() r.draw( # fmt: off classify_result, report_path=config.output, )
def test_boost(): cl = SVMClassifier() cl.load_model(MODEL_PATH) classify_result = cl.classify(VIDEO_PATH, boost_mode=True) assert classify_result
# 采样结果保存的位置 # 不指定的话则会在当前位置生成文件夹并返回它的路径 # './cut_result', # prune被用于去除重复阶段(>=0.4.4) # float(0-1.0),设置为0.9时,如果两个stage相似度超过0.9,他们会合并成一个类别 prune=None, ) # --- classify --- cl = SVMClassifier( # 默认情况下使用 HoG 进行特征提取 # 你可以将其关闭从而直接对原始图片进行训练与测试:feature_type='raw' feature_type="hog", # 默认为0.2,即将图片缩放为0.2倍 # 主要为了提高计算效率 # 如果你担心影响分析效果,可以将其提高 compress_rate=0.2, # 或者直接指定尺寸 # 当压缩率与指定尺寸同时传入时,优先以指定尺寸为准 # target_size=(200, 400), ) # 加载数据 cl.load(data_home) # 在加载数据完成之后需要先训练 cl.train() # 在训练后你可以把模型保存起来 # cl.save_model('model.pkl') # 或者直接读取已经训练好的模型 # cl.load_model('model.pkl')
stable, _ = res.get_range() # 检查最后一个阶段中是否包含图片 person.png # 这种做法会在阶段中间取一帧进行模板匹配 # 当然,这种做法并不常用,最常用还是用于检测最终结果而不是中间量 # 值得注意,这里的模板匹配会受到压缩率的影响 # 虽然已经做了分辨率拟合,但是如果压缩率过高,依旧会出现图像难以辨认而导致的误判 # 正常来说没什么问题 match_result = stable[-1].contain_image(amazon_image_path, engine_template_scale=(0.5, 2, 5)) print(match_result) # 分别输出:最可能存在的坐标、相似度、计算是否正常完成 # {'target_point': [550, 915], 'target_sim': 0.9867244362831116, 'ok': True} data_home = res.pick_and_save(stable, 5) cl = SVMClassifier() cl.load(data_home) cl.train() classify_result = cl.classify(video_path, stable, keep_data=True) result_dict = classify_result.to_dict() final_result: dict = {} for each_stage, each_frame_list in result_dict.items(): # 你可以通过对这些阶段进行目标检测,以确认他们符合你的预期 # 注意,如阶段名称为负数,意味着这个阶段是处在变化中,非稳定 # 例如,检测每一个阶段的中间帧是否包含特定图片 middle_id: int = int((len(each_frame_list) - 1) / 2) # 分别检测 amazon.png 与 phone.png (这两张是手动选出来的标志物) amazon_image_res = each_frame_list[middle_id].contain_image(
from stagesepx.cutter import VideoCutter from stagesepx.classifier import SVMClassifier from stagesepx.reporter import Reporter from stagesepx.video import VideoObject video_path = "../videos/long.mp4" video = VideoObject(video_path) video.load_frames() # --- cutter --- cutter = VideoCutter() res = cutter.cut(video) stable, unstable = res.get_range() data_home = res.pick_and_save(stable, 5) # --- classify --- cl = SVMClassifier(compress_rate=0.4) cl.load(data_home) cl.train() classify_result = cl.classify(video, stable, keep_data=True) result_dict = classify_result.to_dict() # --- draw --- r = Reporter() r.draw(classify_result)
from stagesepx.classifier import SVMClassifier from stagesepx.reporter import Reporter # 默认情况下使用 HoG 进行特征提取 # 你可以将其关闭从而直接对原始图片进行训练与测试:feature_type='raw' cl = SVMClassifier(feature_type='hog') # 基本与SSIM分类器的流程一致 # 但它对数据的要求可能有所差别,具体参见 cut.py 中的描述 data_home = './cut_result' cl.load(data_home) # 在加载数据完成之后需要先训练 cl.train() # # 在训练后你可以把模型保存起来 # cl.save_model('model.pkl') # # 或者直接读取已经训练好的模型 # cl.load_model('model.pkl') # 开始分类 res = cl.classify( '../test.mp4', # 步长,可以自行设置用于平衡效率与颗粒度 # 默认为1,即每帧都检测 step=1, ) # 为了更方便的可读性,stagesepx已经内置了图表绘制功能 # 你可以直接把分析结果绘制成图表 report = Reporter()
# 采样结果保存的位置 # 不指定的话则会在当前位置生成文件夹并返回它的路径 # './cut_result', # prune被用于去除重复阶段(>=0.4.4) # float(0-1.0),设置为0.9时,如果两个stage相似度超过0.9,他们会合并成一个类别 prune=None, ) # --- classify --- cl = SVMClassifier( # 默认情况下使用 HoG 进行特征提取 # 你可以将其关闭从而直接对原始图片进行训练与测试:feature_type='raw' feature_type='hog', # 默认为0.2,即将图片缩放为0.2倍 # 主要为了提高计算效率 # 如果你担心影响分析效果,可以将其提高 compress_rate=0.2, ) # 加载数据 cl.load(data_home) # 在加载数据完成之后需要先训练 cl.train() # 在训练后你可以把模型保存起来 # cl.save_model('model.pkl') # 或者直接读取已经训练好的模型 # cl.load_model('model.pkl') # 注意,如果在classify方法指定了范围