题目
#从网上下载或自己手机录制一段视频(>30秒),第0-5秒显示一句话的字幕,第6-15秒显示另一句话的字幕。
#第20秒开始从屏幕中心出现一个光点,发出眩光,逐渐扩大覆盖的整个屏幕(类似太阳),最后光点缩小复原,整个过程10秒。
先给出框架
data文件夹(文末有链接)
.mp4文件可以选取自己的视频,图片是你要生成的眩光效果,相应的要改utils。
gen_glareRGB.py
##gen_glareRGB.py##
#获取眩光图片的像素分布,是调用的函数,下次放在modules模块里面会更好
import cv2
def GlaredgeRgb():
#这里是我们需要获取的眩光半径343个像素,是取了视频高度的一半
radius_rgb = [0]*343
glare_data = cv2.imread('../data/glare.jpg')
glare_data = cv2.cvtColor(glare_data,cv2.COLOR_BGR2RGB)
row,col,cha = glare_data.shape
#选择中心的那一行
chose_row=int(row/2)
#从第300列开始,获取像素值
chose_col = 300
for i in range(len(radius_rgb)):
radius_rgb[i] = tuple(glare_data[chose_row,i+chose_col])
return radius_rgb[266:343] #343-77=266,是由于在这之内的像素全是白色,只取非白色点
if __name__ == '__main__':
a = GlaredgeRgb()
print(a)
count = 0
for i in range(len(a)):
#找非白色点有多少个
if a[i][0] != 255:
print(i)
count +=1
print(count) #77
print(count/len(a)) #0.2244,计算非白色点的比率
SubtitlesVideo1.py
加上字幕,生成第一种眩光,时间花费较短,20s左右,效果中下。
##SubtitlesVideo1.py##
#从网上下载或自己手机录制一段视频(>30秒),第0-5秒显示一句话的字幕,第6-15秒显示另一句话的字幕。
#第20秒开始从屏幕中心出现一个光点,发出眩光,逐渐扩大覆盖的整个屏幕(类似太阳),最后光点缩小复原,整个过程10秒。
#这个光照实现的不够好,是比较生硬的感觉
import datetime
import time
# 方法一:datetime.datetime.now() 时间和日期的结合 eg: 2021-10-15 14:19:27.875779
#——————————————————————————————————————————————————————————————————————#
start_dt = datetime.datetime.now()
print("start_datetime:", start_dt)
time.sleep(2)
for i in range(10000):
i += 1
#——————————————————————————————————————————————————————————————————————#
import cv2
from utils.gen_glareRGB import GlaredgeRgb
def glare_circle(img = '../data/glare.jpg',center = (30,30),radius=3):
edge_i = 0
glare_edge = GlaredgeRgb()
cent_rate = 0.78
cv2.circle(img,center,int(radius*cent_rate),(255,255,255),-1)
for i in range(int(radius*cent_rate)+1,radius+1):
if edge_i >= len(glare_edge):
edge_i = len(glare_edge) - edge_i%len(glare_edge) -1
cv2.circle(img,center,i,tuple([int(x) for x in glare_edge[edge_i]]),0)
edge_i += 1
return 0
#original_video
org_video = "../data/LawerCrush.mp4"
#video_subtitled
sub_video = "../data/LawerCrush_subtitles1.mp4"
#read video
Video = cv2.VideoCapture(org_video)
#Gets the video frame rate
Fps_video = Video.get(cv2.CAP_PROP_FPS)
#Sets the encoding format for writing video
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
#Get video width
frame_width = int(Video.get(cv2.CAP_PROP_FRAME_WIDTH))
#Get video Height
frame_height = int(Video.get(cv2.CAP_PROP_FRAME_HEIGHT))
#Save the video after the subtitles
videoWriter = cv2.VideoWriter(sub_video, fourcc, Fps_video, (frame_width, frame_height))
##Add subtitles
glare_time = int(Fps_video*5)-1 #vanish overflow
glare_count = 0
frame_id = 0
w_index = 0
putword = ['He is a down-and-out lawyer','God gave him another surprise',' ']
cc_x = int(frame_width/2)
cc_y = int(frame_height/2)
while (Video.isOpened()):
ret, frame = Video.read()
if ret == True:
frame_id += 1
time_s = int(frame_id/Fps_video)
if(time_s<6):
w_index = 0
elif(time_s<16):
w_index = 1
else:
w_index =2
if 20<time_s <= 25 :
glare_count += 1
elif 25< time_s <=30:
glare_count -= 1
#full
glare_circle(frame,(cc_x,cc_y),int((cc_x/glare_time)*glare_count))
#Text coordinates
word_x = 450
word_y = int(frame_height)-18
cv2.putText(frame, '%s' %putword[w_index], (word_x, word_y), cv2.FONT_HERSHEY_SIMPLEX, 2, (255,255,255), 2)
#****写入视频
videoWriter.write(frame)
else:
videoWriter.release()
break
#——————————————————————————————————————————————————————————————————————#
end_dt = datetime.datetime.now()
print("end_datetime:", end_dt)
print("time cost:", (end_dt - start_dt).seconds, "s")
#——————————————————————————————————————————————————————————————————————#
SubtitlesVideo2.py
加上字幕,生成第二种眩光,时间花费较长,30min左右,效果很好。
##SubtitlesVideo2.py##
#从网上下载或自己手机录制一段视频(>30秒),第0-5秒显示一句话的字幕,第6-15秒显示另一句话的字幕。
#第20秒开始从屏幕中心出现一个光点,发出眩光,逐渐扩大覆盖的整个屏幕(类似太阳),最后光点缩小复原,整个过程10秒。
#这个光照实现比较自然
import cv2
import math
import numpy as np
import datetime
import time
# 方法一:datetime.datetime.now() 时间和日期的结合 eg: 2021-10-15 14:19:27.875779
#——————————————————————————————————————————————————————————————————————#
start_dt = datetime.datetime.now()
print("start_datetime:", start_dt)
time.sleep(2)
for i in range(10000):
i += 1
#——————————————————————————————————————————————————————————————————————#
#original_video
org_video = "../data/LawerCrush.mp4"
#video_subtitled
sub_video = "../data/LawerCrush_subtitles2.mp4"
#read video
Video = cv2.VideoCapture(org_video)
#Gets the video frame rate
Fps_video = Video.get(cv2.CAP_PROP_FPS)
#Sets the encoding format for writing video
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
#Get video width
frame_width = int(Video.get(cv2.CAP_PROP_FRAME_WIDTH))
#Get video Height
frame_height = int(Video.get(cv2.CAP_PROP_FRAME_HEIGHT))
#Save the video after the subtitles
videoWriter = cv2.VideoWriter(sub_video, fourcc, Fps_video, (frame_width, frame_height))
##Add glare
strength = 222
centerx = frame_width/2
centery = frame_height/2
#full
radius = max(centerx,centery)
glare_time = int(Fps_video*5)-1 #5s一个阶段
glare_count = 0
def glaring(frame,r):
if r == 0:
return 0
for i in range(frame_height):
for j in range(frame_width):
distance = math.pow((centery-i),2) + math.pow((centerx-j),2)
#获取原始图像
B = frame[i, j][0]
G = frame[i, j][1]
R = frame[i, j][2]
if (distance<r*r):
#按照距离大小计算增强的光照值
result = (int)(strength * (1.0 -math. sqrt(distance) / radius))
B = frame[i, j][0] + result
G = frame[i, j][1] + result
R = frame[i, j][2] + result
#判断边界防止越界
B = min(255, max(0, B))
G = min(255, max(0, G))
R = min(255, max(0, R))
frame[i, j] = np.uint8((B, G, R))
else:
frame[i, j] = np.uint8((B, G, R))
#______________________________________________#
##Add subtitles
frame_id = 0
w_index = 0
putword = ['He is a down-and-out lawyer','God gave him another surprise',' ']
#______________________________________________#
while (Video.isOpened()):
ret, frame = Video.read()
if ret == True:
frame_id += 1
print(frame_id)
time_s = int(frame_id/Fps_video)
if(time_s<6):
w_index = 0
elif(time_s<16):
w_index = 1
else:
w_index =2
if time_s<=20:
glare_count = 0
elif 20<time_s <= 25 :
print('therebig{}'.format(frame_id))
glare_count +=1
elif 25< time_s <=30:
glare_count -=1
print('theresmalll{}'.format(frame_id))
if frame_id%1 == 0:
glaring(frame,(radius/glare_time )*glare_count)
#Text coordinates
word_x = 450
word_y = int(frame_height)-18
cv2.putText(frame, '%s' %putword[w_index], (word_x, word_y), cv2.FONT_HERSHEY_SIMPLEX, 2, (255,255,255), 2)
#****写入视频
videoWriter.write(frame)
else:
videoWriter.release()
break
#——————————————————————————————————————————————————————————————————————#
end_dt = datetime.datetime.now()
print("end_datetime:", end_dt)
print("time cost:", (end_dt - start_dt).seconds, "s")
#——————————————————————————————————————————————————————————————————————#
运行结果
运行SubtitlesVideo1.py之后,在data文件夹会多出来一个视频
查看视频完成要求情况:
运行SubtitlesVideo2.py之后,在data文件夹又会多出来一个视频
查看视频完成要求情况(主要是眩光有变化):
第三种美丽的眩光,并且耗时短,是由W同学的好想法(见代码)做到的
e2_main_acc.py
import cv2
import os
from tqdm import tqdm
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import multiprocessing
# 切割图像帧
def get_each_frame(video_path):
# 读取视频文件
video = cv2.VideoCapture(video_path)
_, frame = video.read()
fps = video.get(cv2.CAP_PROP_FPS)
frames = video.get(cv2.CAP_PROP_FRAME_COUNT)
frames = int(frames)
print('开始切割图像帧....')
print('*' + 50 * '-' + '*')
for i in tqdm(range(1, frames + 1)):
address = './per_picture/' + str(i) + '.jpg'
cv2.imwrite(address, frame)
_, frame = video.read()
return frames, int(fps)
# 合成图像帧为视频
def merge_image_to_video(folder_name, per_h, per_w, fps, n):
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
img_size = (per_w, per_h)
video = cv2.VideoWriter("output.mp4", fourcc, fps, img_size)
print('开始合成图像帧....')
print('*' + 50 * '-' + '*')
for f1 in tqdm(range(1, n + 1)):
f1 = str(f1) + '.jpg'
filename = os.path.join(folder_name, f1)
frame = cv2.imread(filename)
frame = cv2.resize(frame, img_size, interpolation=cv2.INTER_CUBIC)
video.write(frame)
video.release()
# 添加字幕
def add_text(s, e, t, h, w):
# 字幕参数设置
pos = (w // 3, h - 100)
t_color = (0, 255, 255)
t_size = 60
print('开始添加字幕....')
print('*' + 50 * '-' + '*')
for i in tqdm(range(s, e + 1)):
path = './per_picture/' + str(i) + '.jpg'
img = cv2.imread(path)
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# 创建一个可以在给定图像上绘图的对象
draw = ImageDraw.Draw(img)
# 字体的格式
font = ImageFont.truetype("simsun.ttc", t_size, encoding="utf-8")
# 绘制文本
draw.text(pos, t, t_color, font=font)
# 转换回OpenCV格式
img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
cv2.imwrite(path, img)
# 添加曝光点
def add_exposure(s, e, h, w, mode):
if mode == 'up':
r = 0.01
v = (h ** 2 + w ** 2) ** (1 / 2) * 2 / (e - s + 1)
print('增加逐渐增大的曝光点......')
elif mode == 'down':
r = (h ** 2 + w ** 2) ** (1 / 2) * 2
v = -(h ** 2 + w ** 2) ** (1 / 2) * 2 / (e - s + 1)
print('增加逐渐减小的曝光点......')
print('*' + 50 * '-' + '*')
for i in tqdm(range(s, e + 1)):
r += v
path = './per_picture/' + str(i) + '.jpg'
img = cv2.imread(path)
# 曝光点部分
m1 = np.zeros((h, w, 3))
I = np.arange(h)[:, None]
J = np.arange(w)
i_r = ((I - h // 2) ** 2 + (J - w // 2) ** 2) ** (1 / 2)
p1 = i_r < r
# 逻辑矩阵扣出曝光点区域
q = 255 * (1 - i_r / r)
# 渐变光强
q = np.repeat(q, 3, axis=1)
# 复制光强到B、G、R三个通道
q = q.reshape((h, w, 3))
m1[p1] = q[p1]
img = img + m1
# 曝光点区域加上渐变的光强
cv2.imwrite(path, img)
if __name__ == '__main__':
# 切割图像帧
n, fps = get_each_frame('./test.mp4')
# 获取每张图像长和宽
image = cv2.imread('./per_picture/1.jpg')
h, w, _ = image.shape
# 第0-5秒 显示字幕:"你为什么离开?"
text1 = multiprocessing.Process(target=add_text, args=(fps * 0 + 1, fps * 5, "你为什么离开?", h, w))
# 第6-15秒显示另一句话的字幕 '我不会停留在—个地方看风景,我的目标是星辰大海'
text2 = multiprocessing.Process(target=add_text, args=(fps * 6 + 1, fps * 15, '我不会停留在—个地方看风景,我的目标是星辰大海', h, w))
# 增加逐渐变大的曝光点 20-25秒
exposure1 = multiprocessing.Process(target=add_exposure, args=(fps * 20 + 1, fps * 25, h, w, 'up'))
# 增加逐渐减小的曝光点 25-30秒
exposure2 = multiprocessing.Process(target=add_exposure, args=(fps * 25 + 1, fps * 30, h, w, 'down'))
text1.start()
text2.start()
exposure1.start()
exposure2.start()
text1.join()
text2.join()
exposure1.join()
exposure2.join()
# 合成图像帧为视频流
merge_image_to_video('per_picture', h, w, fps=fps, n=n)
e2_main.py
import cv2
import os
from tqdm import tqdm
import numpy as np
from PIL import Image, ImageDraw, ImageFont
# 切割图像帧
def get_each_frame(video_path):
# 创建视频流对象
video = cv2.VideoCapture(video_path)
# 获取视频帧率
fps = video.get(cv2.CAP_PROP_FPS)
# 获取总帧数
frames = video.get(cv2.CAP_PROP_FRAME_COUNT)
frames = int(frames)
print('开始切割图像帧....')
print('*' + 50 * '-' + '*')
for i in tqdm(range(1, frames + 1)):
# 存储图片帧的位置
address = './per_picture/' + str(i) + '.jpg'
_, frame = video.read()
cv2.imwrite(address, frame)
return frames, int(fps)
# 合成图像帧为视频
def merge_image_to_video(folder_name, per_h, per_w, fps, n):
# 设置视频流的格式
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# 封装图像帧格式为元组
img_size = (per_w, per_h)
# 传入 视频 的帧率 和图像帧大小
video = cv2.VideoWriter("output.mp4", fourcc, fps, img_size)
print('开始合成图像帧....')
print('*' + 50 * '-' + '*')
for f1 in tqdm(range(1, n + 1)):
f1 = str(f1) + '.jpg'
# 图像帧路径
filename = os.path.join(folder_name, f1)
# 获取图像
frame = cv2.imread(filename)
frame = cv2.resize(frame, img_size, interpolation=cv2.INTER_CUBIC)
# 写入图像帧
video.write(frame)
video.release()
# 添加字幕
def add_text(s, e, t, h, w):
# 字幕参数设置
pos = (w // 3, h - 100)
t_color = (0, 255, 255)
t_size = 60
print('开始添加字幕....')
print('*' + 50 * '-' + '*')
for i in tqdm(range(s, e + 1)):
path = './per_picture/' + str(i) + '.jpg'
img = cv2.imread(path)
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# 创建一个可以在给定图像上绘图的对象
draw = ImageDraw.Draw(img)
# 字体的格式
font = ImageFont.truetype("simsun.ttc", t_size, encoding="utf-8")
# 绘制文本
draw.text(pos, t, t_color, font=font)
# 转换回OpenCV格式
img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
cv2.imwrite(path, img)
# 添加曝光点
def add_exposure(s, e, h, w, mode):
if mode == 'up':
r = 0.01
v = (h ** 2 + w ** 2) ** (1 / 2) * 2 / (e - s + 1)
elif mode == 'down':
r = (h ** 2 + w ** 2) ** (1 / 2) * 2
v = -(h ** 2 + w ** 2) ** (1 / 2) * 2 / (e - s + 1)
print('*' + 50 * '-' + '*')
for i in tqdm(range(s, e + 1)):
r += v
path = './per_picture/' + str(i) + '.jpg'
img = cv2.imread(path)
# 曝光点部分
m1 = np.zeros((h, w, 3))
I = np.arange(h)[:, None]
J = np.arange(w)
i_r = ((I - h // 2) ** 2 + (J - w // 2) ** 2) ** (1 / 2)
p1 = i_r < r
q = 255 * (1 - i_r / r)
q = np.repeat(q, 3, axis=1)
q = q.reshape((h, w, 3))
m1[p1] = q[p1]
img = img + m1
cv2.imwrite(path, img)
if __name__ == '__main__':
# 切割图像帧
n, fps = get_each_frame('./test.mp4')
# 获取每张图像长和宽
image = cv2.imread('./per_picture/1.jpg')
h, w, _ = image.shape
# 第0-5秒 显示字幕:"你为什么离开?"
add_text(fps * 0 + 1, fps * 5, "你为什么离开?", h, w)
# 第6-15秒显示另一句话的字幕 '我不会停留在—个地方看风景,我的目标是星辰大海'
add_text(fps * 6 + 1, fps * 15, '我不会停留在—个地方看风景,我的目标是星辰大海', h, w)
# 增加逐渐变大的曝光点 20-25秒
print('增加逐渐增大的曝光点......')
add_exposure(fps * 20 + 1, fps * 25, h, w, mode='up')
print('增加逐渐减小的曝光点......')
# 增加逐渐减小的曝光点 25-30秒
add_exposure(fps * 25 + 1, fps * 30, h, w, mode='down')
# 合成图像帧为视频流
merge_image_to_video('per_picture', h, w, fps=fps, n=n)