使用OpenCV实现抖音“蓝线挑战”特效以及本地测试

效果展示

本项目通过Python-OpenCV实现抖音的“蓝线挑战”功能,即跟随视频中滑动的指示线实现多帧延迟,在视觉上出现上半部分图像停留的效果。视频结果

功能复现

  1. 采集视频,包括从本地读取视频格式和启动摄像头两种方式;
  2. 提取帧,对每一帧单独处理;
  3. 根据视频分辨率,绘制区域:上半部分绘制图片,下半部分绘制视频;
  4. 根据需求添加辅助;
  5. 测试并完成创意视频录制。

获取视频帧

通过OpenCV内建函数cv2.VideoCapture实现视频帧截取。使用命令行参数解析包argparse设置程序的调用指令:无输入时打开摄像头,有输入的情况下打开路径下的视频文件。

import cv2
import os
import numpy as np

path = '/Users/PycharmProjects/blue-line-challenge/output/grab_frames/'
cap = cv2.VideoCapture('/Users/panyining/PycharmProjects/blue-line-challenge/video/3.gif')
i = 1
height = 0

if not os.path.exists(path):
    os.makedirs(path)
while (cap.isOpened()):
    ret, frame = cap.read() 
    print(frame.shape)
    if ret == False:  #
        break
    cv2.imencode('.jpg', frame)[1].tofile(path + 'frame_' + str(i) + '.jpg')  
    cv2.imshow('frame', frame)
    i += 1

    if cv2.waitKey(1) & 0xFF == ord('q'):  
        break
cv2.waitKey(0)
cap.release()
cv2.destroyAllWindows()

frame

帧处理

主体思路是将每一帧的上半部分绘制图片、下半部分绘制视频,通过一个全局的参数height定位每次图像和视频的分界线。在循环中不断叠加高度,由 h e i g h t = 0 height=0 height=0 h e i g h t = l e n ( f r a m e . s h a p e [ 0 ] ) height=len(frame.shape[0]) height=len(frame.shape[0])即从图像帧的顶部到底部,实现蓝线的扫描的效果。
old_frame

由于分界线的存在,我们可以方便地实现对图像的处理。由于需要实现多帧延迟的效果,因此需要在每一次迭代时调用上一帧的图像old_frame用于处理。

以3通道的RGB的图像为例,每次取height位置的、长度为1、宽度为图像帧的宽W的长方形区域作为ROI,其值为上一帧old_frame对应位置的色彩值,如B通道的数字替换可以表示为: f r a m e [ h e i g h t : h e i g h t + 1 , : , 0 ] = 255 frame[height:height + 1, :, 0] = 255 frame[height:height+1,:,0]=255。至此,完成本项目核心算法的解析和实现。

import cv2
import os
import numpy as np
import time

height = 0
old_frame = np.ones((372, 500, 3), dtype=np.uint8)
old_frame[:, :, 0] = 0
old_frame[:, :, 1] = 0
old_frame[:, :, 1] = 0
cap = cv2.VideoCapture('/Users/panyining/PycharmProjects/blue-line-challenge/video/3.gif')

while cap.isOpened():
    frame = vs.read()
    frame = frame[1] if args.get("input", False) else frame
    
    frame = imutils.resize(frame, width=500)
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    frame[:height, :, :] = old_frame[:height, :, :]
    line = old_frame[height:height + 1, :, :]

    # frame[height:height + 1, :, 0] = 240  # B
    # frame[height:height + 1, :, 1] = 127  # G
    # frame[height:height + 1, :, 2] = 0  # R
    cv2.imshow('frame', frame)

    i += 1
    height += 2
    old_frame = frame

    if cv2.waitKey(1) & 0xFF == ord('q'):  
        break

cv2.waitKey(0)
cap.release()
cv2.destroyAllWindows()

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值