pyskl代码解析(3)

1.demo_skeleton.py

FONTFACE = cv2.FONT_HERSHEY_DUPLEX
# FONTSCALE = 0.75
FONTSCALE = 2
FONTCOLOR = (255, 255, 255)  # BGR, white
THICKNESS = 1
# LINETYPE = 1
LINETYPE = 2

(1)这一部分是用来对标签颜色大小线的粗细进行的设置。修改试一下。

原图像

修改后

(2)从main函数开始看

1)首先main函数先args = parse_args()解析命令行参数,通过调用这个函数,你可以获取到用户在命令行中传递给程序的参数值。

假设命令行输入

python demo/demo_skeleton.py demo/ntu_sample.avi demo/demo.mp4

参数包括输入视频,输出视频。其他参数就会选择默认的选项,例如

parser.add_argument(
        '--config',
        default='configs/posec3d/slowonly_r50_ntu120_xsub/joint.py',
        help='skeleton action recognition config file path')
    parser.add_argument(
        '--checkpoint',
        default='https://download.openmmlab.com/mmaction/pyskl/ckpt/posec3d/slowonly_r50_ntu120_xsub/joint.pth',
        help='skeleton action recognition checkpoint file/url')
    parser.add_argument(
        '--det-config',
        default='demo/faster_rcnn_r50_fpn_1x_coco-person.py',
        help='human detection config file path (from mmdet)')
    parser.add_argument(
        '--det-checkpoint',
        default=('https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco-person/'
                 'faster_rcnn_r50_fpn_1x_coco-person_20201216_175929-d022e227.pth'),
        help='human detection checkpoint file/url')
    parser.add_argument(
        '--pose-config',
        default='demo/hrnet_w32_coco_256x192.py',
        help='human pose estimation config file path (from mmpose)')
    parser.add_argument(
        '--pose-checkpoint',
        default='https://download.openmmlab.com/mmpose/top_down/hrnet/hrnet_w32_coco_256x192-c78dce93_20200708.pth',
        help='human pose estimation checkpoint file/url')
    parser.add_argument(
        '--det-score-thr',
        type=float,
        default=0.9,
        help='the threshold of human detection score')
    parser.add_argument(
        '--label-map',
        default='tools/data/label_map/nturgbd_120.txt',
        help='label map file')
    parser.add_argument(
        '--device', type=str, default='cuda:0', help='CPU/CUDA device option')
    parser.add_argument(
        '--short-side',
        type=int,
        default=480,
        help='specify the short-side length of the image')

这里面default都是默认情况下的选择。命令行没有输入这些,那麽就会按照默认的进行执行。

2)第二行代码就是对输入的视频进行的处理

frame_paths, original_frames = frame_extraction(args.video,
                                                    args.short_side)

这里调用了一个函数frame_extraction帧提取参数有两个分别是命令行中输入的视频,以及默认的图像的大小设置。可以试一下将大小修改后的视频情况。默认是480帧

parser.add_argument(
        '--short-side',
        type=int,
        default=480,
        help='specify the short-side length of the image')

我们设置成260帧看一下效果

原始图像

改变后的图像

可以看到提取帧变少,视频变得模糊,但是为什么左上角的字也变大了呢。可以看一下你这个函数的代码。

target_dir = osp.join('./tmp', osp.basename(osp.splitext(video_path)[0]))
    os.makedirs(target_dir, exist_ok=True)

这段代码第一行会将视频文件名与./tmp结合在一起形成./tmp/video_path_name

第二行是创建这个目录./tmp/video_path_name,如果存在不会报错,如果不存在则会报错。

但是目录里面没有形成文件,把exist_ok参数设置为False试一下。它不仅没有报错而且也没有在tmp中生成帧。

他生成了然后用完了之后又自动将这个文件给删掉了。可以看到这个功能是在./tmp/video_path_name放各个帧的图片。

 frame_tmpl = osp.join(target_dir, 'img_{:06d}.jpg')

这行代码定义了一个字符串模板,用于后续创建保存帧的文件名。模板中的{:06d}表示一个六位的整数,例如000001000002等。所以,对于每一个提取的帧,都会生成一个如img_000001.jpgimg_000002.jpg等的文件名。

vid = cv2.VideoCapture(video_path)

这行代码使用OpenCV库中的VideoCapture函数打开一个视频文件,并返回一个视频对象。通过这个视频对象,我们可以逐帧读取视频,或者获取视频的一些基本信息,如帧率、分辨率等。

frames = []
    frame_paths = []

这两行代码初始化两个空列表,frames用于存储提取的帧,而frame_paths用于存储这些帧的文件路径。

frames = []:定义一个空列表,用于存储提取的帧。

frame_paths = []:定义一个空列表,用于存储这些帧的文件路径。

这两行代码是提取视频帧前的准备工作,为后续的循环读取视频帧和保存帧做准备。

flag, frame = vid.read()

这行代码从视频中读取一帧。如果读取成功,flagTrue,否则为False。读取到的帧数据会存储在frame变量中。

这里的vid.read()函数会返回两个值:

  • flag:一个布尔值,表示是否成功读取了一帧。如果成功读取,则为True,否则为False
  • frame:读取到的帧数据,是一个NumPy数组。

通过这行代码,我们可以逐帧读取视频,并对每一帧进行处理或保存。

    while flag:
        if new_h is None:
            h, w, _ = frame.shape
            new_w, new_h = mmcv.rescale_size((w, h), (short_side, np.Inf))

这段代码的目的是调整视频帧的大小,以适应指定的短边尺寸。

  1. new_h, new_w = None, None:初始化new_hnew_wNone。这两个变量将用于存储调整大小后的帧的宽度和高度。
  2. while flag::这是一个循环,会一直执行直到flag变为False。在上面的代码中,flagframe是通过vid.read()函数得到的,其中flag是一个布尔值,表示是否成功读取了一帧。
  3. if new_h is None::检查new_h是否为None。如果是,说明还没有对帧进行过尺寸调整。
  4. h, w, _ = frame.shape:使用NumPy的shape属性获取当前帧的高度、宽度和通道数。这里只关心高度和宽度,所以用下划线_忽略通道数。
  5. new_w, new_h = mmcv.rescale_size((w, h), (short_side, np.Inf)):使用mmcv.rescale_size函数重新调整帧的大小。这个函数接受原始的宽度和高度作为第一个参数,以及新的短边尺寸作为第二个参数。这里将长边设置为无穷大(由np.Inf表示)以确保只对短边进行缩放。

这段代码的目的是确保提取的帧的短边尺寸与指定的短边尺寸相匹配,这在某些应用中可能是必要的,例如在视频处理或机器视觉任务中,可能需要对视频帧进行统一的尺寸处理。

frame = mmcv.imresize(frame, (new_w, new_h))

        frames.append(frame)
        frame_path = frame_tmpl.format(cnt + 1)
        frame_paths.append(frame_path)

        cv2.imwrite(frame_path, frame)
        cnt += 1
        flag, frame = vid.read()

这段代码是在处理视频帧,具体来说,它执行以下操作:

  1. frame = mmcv.imresize(frame, (new_w, new_h)):使用mmcv.imresize函数调整帧的大小。这里,帧的宽度和高度被设置为new_wnew_h,这是通过前面的代码计算得到的。
  2. frames.append(frame):将调整大小后的帧添加到frames列表中。
  3. frame_path = frame_tmpl.format(cnt + 1):使用之前定义的模板frame_tmpl生成保存帧的文件名。这里使用cnt + 1作为文件名的占位符,其中cnt是一个计数器,用于跟踪已经处理的帧数。
  4. frame_paths.append(frame_path):将生成的文件路径添加到frame_paths列表中。
  5. cv2.imwrite(frame_path, frame):使用OpenCV的imwrite函数将帧保存到指定的文件路径。
  6. cnt += 1:增加计数器cnt的值,以便下一次迭代时生成下一个文件名。
  7. flag, frame = vid.read():再次从视频中读取一帧。如果读取成功,则继续循环;否则,循环结束。

这段代码的主要目的是从视频中逐帧提取并保存调整大小后的帧。提取的帧被保存在指定的目录中,并按照指定的文件命名模板进行命名。

所以这可以解答一下前面的问题,short_side的作用到底是什么,它不是减少帧数,而是改变图像的短边的宽度,可以更改看一下它提取的帧数是否发生改变。

可以看到short_side在480的情况下帧数是72帧,我们改变一下短边的大小,变成240

可以看到更改后还是没有变化,依然是72帧,只不过短边变窄,那么为什么图像变的模糊了呢,我认为可能跟你输出的图像有关,输出的图像大小不变,而随着设定的短边变小,相应的就会放大为原来的尺寸,从而导致视频变得模糊。

3)跳回到main函数当中

num_frame = len(frame_paths)
h, w, _ = original_frames[0].shape

可以看到果然是把h,w设置成原始帧第一个帧的大小,而第一个帧并没有进行短边操作,所以变模糊的原因找到了,这里我们可以改成第二帧大小,那么就不会出现模糊的结果。结果却是没有变化依然模糊。

config = mmcv.Config.fromfile(args.config)

这行代码是在使用mmcv.Config类从指定的配置文件(通常是一个JSON文件)中加载配置信息。这里,args.config指定了配置文件的路径。

解释一下各个部分:

  • mmcv.Configmmcv是一个用于计算机视觉任务的库,其中Config类用于加载和解析配置文件。
  • fromfile(): 这是Config类的一个方法,用于从指定的文件中加载配置信息。
  • args.config: 这是一个变量,通常是通过命令行参数或某种方式传递进来的配置文件路径。

通过调用fromfile()方法,你可以将配置文件中的设置加载到一个Config对象中,然后可以使用这个对象来访问或修改这些设置。这在深度学习、计算机视觉和其他机器学习任务中非常常见,因为这些任务通常需要大量的配置参数来调整模型和训练过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值