video-modification/main.py

555 lines
20 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()