video-modification/main.py

555 lines
20 KiB
Python
Raw Permalink Normal View History

2023-11-29 19:52:28 +08:00
import cv2
import os
import numpy as np
def divide(video, folder_name):
# 获取视频的帧数
frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
# print(frame_count)
save_count = 0
# 创建保存帧的文件夹
if not os.path.exists(folder_name):
os.makedirs(folder_name)
# 循环读取视频中的每一帧
for i in range(frame_count):
_, frame = video.read()
# dst = cv2.resize(frame, (960, 540))
cv2.imwrite(folder_name+"/frame_{}.jpg".format(i), frame)
if i % 50 == 0:
print(i/frame_count)
def divide_into_n(video):
frame_number = 1 # 记录读取到的帧数初始值为1
frame_interval = 100 # 每隔100帧截取1帧
if not os.path.exists("frames3"):
os.makedirs("frames3")
while (video.isOpened()): # 视频文件被打开后
retval, frame = video.read() # 读取视频帧
if retval == True: # 读取到视频帧后
if (frame_number % frame_interval == 0): # 每隔100帧
cv2.imwrite("frames3/" + str(frame_number) + ".jpg", frame) # 截取并保存1帧
else: # 没有读取到视频帧
break # 终止循环
frame_number = frame_number + 1 # 读取到的视频帧执行自加操作
cv2.waitKey(1) # 1毫秒后播放视频文件的下一帧
print("视频帧已截取完成!") # 控制台输出提示信息
def merge(folder_name, frame_num):
l=[]
for i in range(frame_num):
l.append(str(i)+".jpg")
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# 这里的outpy.mp4v就是视频保存路径
image0 = cv2.imread(folder_name + "/00000.jpg")
iw, ih, ic = np.shape(image0)
out = cv2.VideoWriter('outpy.mp4v', cv2.VideoWriter_fourcc(*'DIVX'), 20, (iw, ih))
"""
注意这里的width和height一定要和图片的一致否则保存的视频是无法播放的
"""
# i是帧图片的名字(含有后缀名)
for i in l:
img12 = cv2.imread("./frame4/new/"+str(i)) # savepath为图片帧目录名
out.write(img12) # out为刚刚创建的保存视频的对象
out.release()
def generate_video(image_folder,frame_id):
video_name = image_folder+'result.mp4'
fps = 20
images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video = cv2.VideoWriter(video_name, fourcc, fps, (width, height))
for frame_index in range(1,frame_id+1):
image = ""+str(frame_index)+".jpg"
print(image)
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
def modify_image():
# base_path = "./frame4/000.jpg"
# target_path = "./frame4/frame_1913.jpg"
base_path = "./frame6/000.jpg"
target_path = "./frame6/frame_280.jpg"
base_picture = cv2.imread(base_path)
target_picture = cv2.imread(target_path)
# kernel = np.ones((5, 5), np.float32) / 25 # 5x5 的平均滤波器核:
# target_picture = cv2.filter2D(target_picture, -1, kernel)
# print(base_picture.shape)
up = 44
down = 139
left = 291
right = 349
for i in range(up, down): # 上下
for j in range(left, right): # 左右
# base_picture[i, j] = [128, 128, 128]
base_value = base_picture[i,j]
target_value = target_picture[i, j]
# if i-up<5 or down-i<5 or j-left<5 or right-j<5:
# lRGB = np.mean(base_value, target_value)
# base_picture[i, j][0] = lRGB[0]
# base_picture[i, j][1] = lRGB[1]
# base_picture[i, j][2] = lRGB[2]
base_picture[i, j] = target_value
# resize_base = target_picture[up:down, left:right]
#
# mask = 255 * np.ones(resize_base.shape, resize_base.dtype)
#
# center = (int((left + right) / 2), int((up + down) / 2))
#
# base_picture = cv2.seamlessClone(resize_base, base_picture, mask, center, cv2.MONOCHROME_TRANSFER) # NORMAL_CLONE 也可以
# kernel = np.ones((5, 5), np.float32) / 25 # 5x5 的平均滤波器核:
# base_picture = cv2.filter2D(base_picture, -1, kernel)
cv2.imshow("after", base_picture)
cv2.imwrite("./frame6/0000.jpg", base_picture) # 截取并保存1帧
# 等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
def get_video_size(video):
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
frame_num = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
return width, height, frame_num
def get_all_frame_rgb(folder_name,image_num):
image0 = cv2.imread(folder_name+"/frame_0.jpg")
iw, ih, ic = np.shape(image0)
# print(iw,ih)
rgb_list = []
# for i in range(iw*ih):
# rgb_list.append([])
# print("complete list initialization")
for i in range(image_num):
image_path = folder_name+"/frame_"+str(i)+".jpg"
image = cv2.imread(image_path)
for x in range(iw):
for y in range(ih):
print(image[x,y])
# rgb_list.append(rgb_value)
# rgb_list[x*ih+y].append(rgb_value)
print("analyzing frame",i)
# print(rgb_list)
rgb_list = []
def resize_img(folder_name,image_num,cut_top_size):
for i in range(image_num):
image_path = folder_name+"/frame_"+str(i)+".jpg"
image = cv2.imread(image_path)
new_image = image[cut_top_size:621,0:1103]
cv2.imwrite("frame4/new/" + str(i) + ".jpg", new_image) # 截取并保存1帧
def expand_position(p1,p2,img, frame_id, weight, expand_mode):
base_path = folder_name + "00000.jpg"
base_image = cv2.imread(base_path)
# print(1)
new_up = p1[1]
new_down = p2[1]
new_left = p1[0]
new_right = p2[0]
need_expand = False
prev_need = False
width = int(base_image.shape[1])
height = int(base_image.shape[0])
threshold_cha = 50
threshold_different_num = 5
lr_range = 5
t_range = 5
d_range = 15
if expand_mode == 1:
lr_range = 30 + int(frame_id / weight) # 20
t_range = 35 + int(frame_id / (weight)) # video444 -> weight*0.4 # 35
d_range = 25 + int(frame_id / weight) # 25
if expand_mode == 2:
lr_range = 50
d_range = 270 # 25
for x in range(max(0,p1[0]),max(0,p1[0]-lr_range),-1):
prev_need = need_expand
need_expand = False
need_num=0
for y in range(p1[1],p2[1]):
cha = 0
cha += abs(int(base_image[y, x][0]) - int(img[y, x][0]))
cha += abs(int(base_image[y, x][1]) - int(img[y, x][1]))
cha += abs(int(base_image[y, x][2]) - int(img[y, x][2]))
# cv2.rectangle(img, (x,y), (x,y), (255, 0, 0), 2, 1) # origin
# cv2.imshow("Tracking", img)
# cv2.waitKey(0)
# cv2.rectangle(base_image, (x, y), (x, y), (255, 0, 0), 2, 1) # origin
# cv2.imshow("Tracking", base_image)
# cv2.waitKey(0)
if cha>threshold_cha:
need_num += 1
# print(x,y,base_image[x, y],img[x, y])
need_expand = True
# break
if need_num>threshold_different_num:
# print(x,need_num)
new_left = x
for x in range(min(width,p2[0]),min(width,p2[0]+lr_range),1):
prev_need = need_expand
need_expand = False
need_num=0
for y in range(p1[1],p2[1]):
cha = 0
cha += abs(int(base_image[y, x][0]) - int(img[y, x][0]))
cha += abs(int(base_image[y, x][1]) - int(img[y, x][1]))
cha += abs(int(base_image[y, x][2]) - int(img[y, x][2]))
if cha>threshold_cha:
need_num += 1
# print(x,y,base_image[x, y],img[x, y])
need_expand = True
# break
if need_num>threshold_different_num:
new_right = x
for y in range(p1[1],max(1,p1[1]-t_range),-1):
prev_need = need_expand
need_expand = False
need_num=0
for x in range(p1[0],p2[0]):
cha = 0
cha += abs(int(base_image[y, x][0]) - int(img[y, x][0]))
cha += abs(int(base_image[y, x][1]) - int(img[y, x][1]))
cha += abs(int(base_image[y, x][2]) - int(img[y, x][2]))
if cha>threshold_cha:
need_num += 1
# print(x,y,base_image[x, y],img[x, y])
need_expand = True
# break
if need_num>threshold_different_num:
new_up = y
for y in range(p2[1],min(height,p2[1]+d_range),1):
prev_need = need_expand
need_expand = False
need_num=0
for x in range(p1[0],p2[0]):
cha = 0
cha += abs(int(base_image[y, x][0]) - int(img[y, x][0]))
cha += abs(int(base_image[y, x][1]) - int(img[y, x][1]))
cha += abs(int(base_image[y, x][2]) - int(img[y, x][2]))
if cha>threshold_cha:
need_num += 1
# print(x,y,base_image[x, y],img[x, y])
need_expand = True
# break
if need_num>threshold_different_num:
new_down = y
return (new_left,new_up),(new_right,new_down)
# return (max(0,p1[0]-lr_range),max(1,p1[1]-t_range)),(min(width,p2[0]+lr_range),min(height,p2[1]+d_range)) # 查看扩大的最大范围
def cover_base(img,p1,p2):
base_path = folder_name + "00000.jpg"
base_image = cv2.imread(base_path)
width = int(img.shape[1])
height = int(img.shape[0])
edge_adding = 10
w1=0.2
w2=0.5
w3=0.8
for x in range(max(0,p1[0]-edge_adding),min(p2[0]+edge_adding,width)):
for y in range(max(0,p1[1]-edge_adding),min(p2[1]+edge_adding,height)):
cha0 = abs(int(base_image[y, x][0]) - int(img[y, x][0]))
cha1 = abs(int(base_image[y, x][1]) - int(img[y, x][1]))
cha2 = abs(int(base_image[y, x][2]) - int(img[y, x][2]))
if x==max(0,p1[0]-edge_adding):
img[y, x][0] = int(base_image[y, x ][0])*w1 + int(img[y, x-1][0])*(1-w1)
img[y, x][1] = int(base_image[y, x ][1])*w1 + int(img[y, x-1][1])*(1-w1)
img[y, x][2] = int(base_image[y, x][2])*w1 + int(img[y, x-1][2])*(1-w1)
# print(1)
elif x==min(p2[0]+edge_adding,width):
img[y, x][0] = int(base_image[y, x ][0])*w1 + int(img[y, x+1][0])*(1-w1)
img[y, x][1] = int(base_image[y, x][1])*w1 + int(img[y, x+1][1])*(1-w1)
img[y, x][2] = int(base_image[y, x ][2])*w1 + int(img[y, x+1][2])*(1-w1)
elif y==max(0,p1[1]-edge_adding):
img[y, x][0] = int(base_image[y, x][0])*w1 + int(img[y-1, x][0])*(1-w1)
img[y, x][1] = int(base_image[y, x][1])*w1 + int(img[y-1, x][1])*(1-w1)
img[y, x][2] = int(base_image[y, x][2])*w1 + int(img[y-1, x][2])*(1-w1)
elif y==p2[1]+edge_adding:
img[y, x][0] = int(base_image[y, x][0])*w1 + int(img[y+1, x][0])*(1-w1)
img[y, x][1] = int(base_image[y, x][1])*w1 + int(img[y+1, x][1])*(1-w1)
img[y, x][2] = int(base_image[y, x][2])*w1 + int(img[y+1, x][2])*(1-w1)
elif x==max(0,p1[0]-edge_adding)+1:
img[y, x][0] = int(base_image[y, x ][0])*w2 + int(img[y, x-2][0])*(1-w2)
img[y, x][1] = int(base_image[y, x ][1])*w2 + int(img[y, x-2][1])*(1-w2)
img[y, x][2] = int(base_image[y, x][2])*w2 + int(img[y, x-2][2])*(1-w2)
# print(1)
elif x==min(p2[0]+edge_adding,width)-1:
img[y, x][0] = int(base_image[y, x ][0])*w2 + int(img[y, x+2][0])*(1-w2)
img[y, x][1] = int(base_image[y, x][1])*w2 + int(img[y, x+2][1])*(1-w2)
img[y, x][2] = int(base_image[y, x ][2])*w2 + int(img[y, x+2][2])*(1-w2)
elif y==max(0,p1[1]-edge_adding)+1:
img[y, x][0] = int(base_image[y, x][0])*w2 + int(img[y-2, x][0])*(1-w2)
img[y, x][1] = int(base_image[y, x][1])*w2 + int(img[y-2, x][1])*(1-w2)
img[y, x][2] = int(base_image[y, x][2])*w2 + int(img[y-2, x][2])*(1-w2)
elif y==p2[1]+edge_adding-1 and y<height-2:
img[y, x][0] = int(base_image[y, x][0])*w2 + int(img[y+2, x][0])*(1-w2)
img[y, x][1] = int(base_image[y, x][1])*w2 + int(img[y+2, x][1])*(1-w2)
img[y, x][2] = int(base_image[y, x][2])*w2 + int(img[y+2, x][2])*(1-w2)
elif x==max(0,p1[0]-edge_adding)+2:
img[y, x][0] = int(base_image[y, x ][0])*w3 + int(img[y, x-3][0])*(1-w3)
img[y, x][1] = int(base_image[y, x ][1])*w3 + int(img[y, x-3][1])*(1-w3)
img[y, x][2] = int(base_image[y, x][2])*w3 + int(img[y, x-3][2])*(1-w3)
# print(1)
elif x==min(p2[0]+edge_adding,width)-2:
img[y, x][0] = int(base_image[y, x ][0])*w3 + int(img[y, x+3][0])*(1-w3)
img[y, x][1] = int(base_image[y, x][1])*w3 + int(img[y, x+3][1])*(1-w3)
img[y, x][2] = int(base_image[y, x ][2])*w3 + int(img[y, x+3][2])*(1-w3)
elif y==max(0,p1[1]-edge_adding)+2:
img[y, x][0] = int(base_image[y, x][0])*w3 + int(img[y-3, x][0])*(1-w3)
img[y, x][1] = int(base_image[y, x][1])*w3 + int(img[y-3, x][1])*(1-w3)
img[y, x][2] = int(base_image[y, x][2])*w3 + int(img[y-3, x][2])*(1-w3)
elif y==p2[1]+edge_adding-2 and y<height-3:
img[y, x][0] = int(base_image[y, x][0])*w3 + int(img[y+3, x][0])*(1-w3)
img[y, x][1] = int(base_image[y, x][1])*w3 + int(img[y+3, x][1])*(1-w3)
img[y, x][2] = int(base_image[y, x][2])*w3 + int(img[y+3, x][2])*(1-w3)
else:
img[y,x]=base_image[y,x]
# 模糊部分
# roi = img[max(0,p1[1]-edge_adding):min(p2[1]+edge_adding,575),max(0,p1[0]-edge_adding):min(p2[0]+edge_adding,1103)]
# blur = cv2.GaussianBlur(roi, (5, 5), 0)
# img[max(0, p1[1] - edge_adding):min(p2[1] + edge_adding, 575), max(0, p1[0] - edge_adding):min(p2[0] + edge_adding, 1103)] = blur
return img
def seamless_cover_base(img, p1, p2):
base_path = folder_name + "00000.jpg"
base_image = cv2.imread(base_path)
edge_adding = 10
width = int(img.shape[1])
height = int(img.shape[0])
pure_cover = cover_base(img, p1, p2)
has_touched_bottom = False
if min(p2[1]+edge_adding, height) == height:
has_touched_bottom = True
resize_base = pure_cover[max(0, p1[1]-edge_adding):min(p2[1]+edge_adding, height), max(0, p1[0]-edge_adding):min(p2[0]+edge_adding, width)]
mask = 255 * np.ones(resize_base.shape, resize_base.dtype)
center = (int((min(p2[0]+edge_adding, width)+max(0, p1[0]-edge_adding)) / 2), int((min(p2[1]+edge_adding, height)+max(0, p1[1]-edge_adding)) / 2))
# print(p1,p2,center)
normal_clone = cv2.seamlessClone(resize_base, img, mask, center, cv2.NORMAL_CLONE) # NORMAL_CLONE 也可以
return normal_clone
# if has_touched_bottom:
# return cover_base(img, p1, p2)
# else:
# normal_clone = cv2.seamlessClone(resize_base, img, mask, center, cv2.MONOCHROME_TRANSFER) # NORMAL_CLONE 也可以
# return normal_clone
def prevent_big_change(p1, p2, prev1, prev2):
v10 = p1[0]
v11 = p1[1]
v20 = p2[0]
v21 = p2[1]
max_cha = 20
if prev1[0]-p1[0]>max_cha:
v10=prev1[0]-max_cha
elif p1[0]-prev1[0]>max_cha:
v10=prev1[0]+max_cha
if prev1[1]-p1[1]>max_cha:
v11=prev1[1]-max_cha
elif p1[1]-prev1[1]>max_cha:
v11=prev1[1]+max_cha
if prev2[0] - p2[0] > max_cha:
v20 = prev2[0] - max_cha
elif p2[0] - prev2[0] > max_cha:
v20 = prev2[0] + max_cha
if prev2[1] - p2[1] > max_cha:
v21 = prev2[1] - max_cha
elif p2[1] - prev2[1] > max_cha:
v21 = prev2[1] + max_cha
return (v10,v11),(v20,v21)
def find_object(cut_top_size,trace_file,img_prefix,expand_mode,img_out_folder):
file = open(trace_file, encoding="utf-8")
content = file.readlines()
new_p1 = (0, 0)
new_p2 = (0, 0)
prev_new_p1 = (0, 0)
prev_new_p2 = (0, 0)
img_out_folder = "output/" # 合成视频的源文件夹
frame_id = 0
content_size = len(content)
for item in content:
item = item.strip("\n")
item = item.replace(",","")
item = item.replace("(","")
item = item.replace(")","")
up = int(item.split(" ")[1]) - cut_top_size
down = int(item.split(" ")[3]) - cut_top_size
left = int(item.split(" ")[0])
right = int(item.split(" ")[2])
p1 = (left,up)
p2 = (right,down)
image_path = folder_name + img_prefix + str(frame_id) + ".jpg"
# print(image_path)
image = cv2.imread(image_path)
width = int(image.shape[1])
height = int(image.shape[0])
prev_new_p1 = new_p1
prev_new_p2 = new_p2
weight = 1
if frame_id<content_size/3:
weight = 3
elif frame_id<content_size/2:
weight = 2
elif frame_id < content_size / 1.5:
weight = 1.7
elif frame_id < content_size / 1.2:
weight = 1.3
else:
weight = 1
if expand_mode == 0:
weight = 10
if p2[1]>height:
p2 = (p2[0],height)
new_p1, new_p2 = expand_position(p1, p2, image, frame_id, weight,expand_mode) # 扩大框框
# 防止目标跟踪框的突变
if frame_id>1:
new_p1, new_p2 = prevent_big_change(new_p1, new_p2, prev_new_p1, prev_new_p2)
# cv2.rectangle(image, p1, p2, (255, 0, 0), 2, 1) # origin
# cv2.rectangle(image, new_p1, new_p2, (255, 0, 0), 2, 1) # draw adaptive rectangle
# image = cover_base(image, new_p1, new_p2) # cover one entity 覆盖原图
image = seamless_cover_base(image, new_p1, new_p2) # cover one entity 覆盖原图
# blurred = cv2.GaussianBlur(image, (1, 5), 0) # 模糊整个图像
frame_id += 1
cv2.imshow("Tracking", image)
print(frame_id/content_size)
# cv2.imwrite(img_out_folder + str(frame_id) + ".jpg", image) # 截取并保存1帧
cv2.waitKey(0)
# generate_video(img_out_folder,frame_id)
if __name__ == '__main__':
# 读取视频
video_name = "333.avi"
my_video = cv2.VideoCapture(video_name)
w, h, n = get_video_size(my_video)
print("width:", w)
print("height:", h)
print("frame_num:", n)
cut_top_size = 0
trace_txt = "position.txt"
image_prefix = "frame_"
expand_mode = 0 # 1-bigger, 0-no-change
folder_name = "frame7/"
if video_name=="003.avi":
folder_name = "frame6/"
elif video_name=="444.avi":
folder_name = "frame5/"
elif video_name=="333.avi":
cut_top_size = 46
expand_mode = 1
image_prefix = ""
folder_name = "frame4/new/"
elif video_name == "lab.mp4":
folder_name = "frame7/"
expand_mode = 2
else:
print("no this video")
# divide(my_video,folder_name)
# divide_into_n(my_video)
# merge(folder_name,n)
img_folder = "output/" # 合成视频的源文件夹
# generate_video(img_folder,500)
# modify_image()
# get_all_frame_rgb(folder_name,n)
# resize_img(folder_name,n,cut_top_size)
# cut_top_size = 46
# cut_top_size = 0
# trace_txt = "position.txt"
# image_prefix = "frame_"
# expand_mode = 0 # 1-bigger, 0-no-change
find_object(cut_top_size,trace_txt,image_prefix,expand_mode,img_folder)
# 关闭视频文件
my_video.release()