一、实验要求
1、手动点击关键点进行替换
2、利用光流对相邻的视频帧进行关键点的追踪
二、实验结果
三、实验代码
1、手动进行图像关键点的点击
import cv2
import numpy as np
导入图片
img1 = cv2.imread('path1')
img2 = cv2.imread('path2')
a =[]
b = []
def on_EVENT_LBUTTONDOWN1(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(img1, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(img1, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image1", img1)
def on_EVENT_LBUTTONDOWN2(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(img2, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(img2, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image2", img2)
cv2.namedWindow("image1")
cv2.namedWindow("image2")
cv2.setMouseCallback("image1", on_EVENT_LBUTTONDOWN1)
cv2.setMouseCallback("image2", on_EVENT_LBUTTONDOWN2)
cv2.imshow("image1", img1)
cv2.imshow("image2", img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
#for i in range(8):
print([a[i],b[i]])
调用cv2库和numpy库,利用cv2.setMouseCallback函数得到鼠标的点击信息,并在on_EVENT_LBUTTONDOWN函数中对点击的点进行标记,将点击点的坐标存储在数组a,b里面。
2、利用光流对相邻的视频帧进行关键点的追踪
(1)首先需要提取视频的第一帧,手动进行关键点的标注,调用cap.read函数,此时frame为视频第一帧的二进制流数据
import cv2
cap = cv2.VideoCapture('2.mp4')
ret, frame = cap.read() #frame是每一帧的图像
scaling_factor = 0.5
frame = cv2.resize(frame, None, fx=scaling_factor,
fy=scaling_factor, interpolation=cv2.INTER_AREA)
(2)手动点击关键点
a =[]
b = []
def on_EVENT_LBUTTONDOWN1(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(frame, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(frame, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image1", frame)
def on_EVENT_LBUTTONDOWN2(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(img1, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(img1, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image2", img1)
cv2.namedWindow("image1")
cv2.setMouseCallback("image1", on_EVENT_LBUTTONDOWN1)
cv2.imshow("image1", frame)
cv2.namedWindow("image2")
cv2.setMouseCallback("image2", on_EVENT_LBUTTONDOWN2)
cv2.imshow("image2", img1)
cv2.waitKey(0)
p0=np.float32([[[a[0],b[0]]],[[a[1],b[1]]],[[a[2],b[2]]],[[a[3],b[3]]]])
print(p0)
cv2.destroyAllWindows()
(3)对视频光流进行追踪,p0为当前关键点,p1为视频流中关键点的下一个位置信息
调用cv2.calcOpticalFlowPyrLK()函数进行我们想要的追踪操作
(ps.关注cv2.calcOpticalFlowPyrLK()函数中p0的格式)
import cv2
import numpy as np
feature_params = dict(maxCorners=100, qualityLevel=0.3,
minDistance=7, blockSize=7)
lk_params = dict(winSize=(15,15), maxLevel=2,
criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
cap = cv2.VideoCapture('path')
ret, frame = cap.read() #frame是每一帧的图像
scaling_factor = 0.5
frame = cv2.resize(frame, None, fx=scaling_factor,
fy=scaling_factor, interpolation=cv2.INTER_AREA)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
p0 = np.float32([[[174,170]],[[180,190]],[[200,200]],[[210,210]]])
p0 = cv2.goodFeaturesToTrack(gray, mask=None, **feature_params) #角点检测
print(p0)
mask = np.zeros_like(frame)
while True:
ret, frame = cap.read()
frame = cv2.resize(frame, None, fx=scaling_factor,
fy=scaling_factor, interpolation=cv2.INTER_AREA)
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
p1, st, err = cv2.calcOpticalFlowPyrLK(gray, frame_gray, p0, None, **lk_params)
print(p1[0][0])
print(p0)
good_new = p1[st == 1]
good_old = p0[st == 1]
for i,(new,old) in enumerate(zip(good_new,good_old)):
a,b = new.ravel()
a=int(a)
b=int(b)
c,d = old.ravel()
c=int(c)
d=int(d)
cv2.line(mask, (a, b),(c, d),(0, 150, 0), 1)
cv2.circle(frame, (a, b), 3, (0, 255, 0), -1)
gray = frame_gray.copy()
p0 = good_new.reshape(-1, 1, 2)
img = cv2.add(frame, mask)
cv2.imshow("Output", img)
k = cv2.waitKey(30)
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
3、人脸的替换(以为图片的替换为例)
(1)鼠标定点(不再赘述)
(2)矩阵变换
调用cv2.getPerspectiveTransform(), cv2.warpPerspective()函数进行两张图片上的关键点的对比(注:此函数规定对应点为4个点)
(3)内容替换
直接用变换好的图像相应矩阵位置处的值替换原图像位置的值
import numpy as np
import cv2
%matplotlib inline
img1 = cv2.imread('path1')
img2 = cv2.imread('path2')
a =[]
b = []
一、鼠标定点
def on_EVENT_LBUTTONDOWN1(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(img1, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(img1, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image1", img1)
def on_EVENT_LBUTTONDOWN2(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(img2, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(img2, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image2", img2)
cv2.namedWindow("image1")
cv2.namedWindow("image2")
cv2.setMouseCallback("image1", on_EVENT_LBUTTONDOWN1)
cv2.setMouseCallback("image2", on_EVENT_LBUTTONDOWN2)
cv2.imshow("image1", img1)
cv2.imshow("image2", img2)
cv2.waitKey(0)
print(a[3],b[3])
print(a[6],b[6])
cv2.destroyAllWindows()
二、矩阵变换
points1 = np.float32([[[a[4],b[4]]],[[a[5],b[5]]],[[a[6],b[6]]],[[a[7],b[7]]]])
points2 = np.float32([[[a[0],b[0]]],[[a[1],b[1]]],[[a[2],b[2]]],[[a[3],b[3]]]])
M = cv2.getPerspectiveTransform(points1, points2)
Affine_img = cv2.warpPerspective(img2, M, (img1.shape[1], img1.shape[0]))
三、内容替换
m=a[2]-a[0]
n=b[2]-b[0]
for j in range(m):
for i in range(m):
img1[74+i][125+j] = Affine_img[74+i][125+j]
cv2.namedWindow("image3")
cv2.imshow("image3",Affine_img) # 显示图片
cv2.imshow("image2",np.array(img_cov, dtype = np.uint8 ))
cv2.waitKey(0)
cv2.destroyAllWindows()
四、完整代码
import numpy as np
import cv2
%matplotlib inline
#视频第一帧和图像第一帧锁定
cap = cv2.VideoCapture('2.mp4')
ret, frame = cap.read() #frame是每一帧的图像
scaling_factor = 0.5
frame = cv2.resize(frame, None, fx=scaling_factor,
fy=scaling_factor, interpolation=cv2.INTER_AREA)
img1 = cv2.imread('face.jpg')
a =[]
b = []
def on_EVENT_LBUTTONDOWN1(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(frame, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(frame, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image1", frame)
def on_EVENT_LBUTTONDOWN2(event, x, y, flags, param):
# 点击鼠标左键
if event == cv2.EVENT_LBUTTONDOWN:
xy = "%d,%d" % (x, y)
a.append(x)
b.append(y)
cv2.circle(img1, (x, y), 1, (255, 0, 0), thickness=-1)
cv2.putText(img1, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
1.0, (0, 0, 0), thickness=1)
cv2.imshow("image2", img1)
cv2.namedWindow("image1")
cv2.setMouseCallback("image1", on_EVENT_LBUTTONDOWN1)
cv2.imshow("image1", frame)
cv2.namedWindow("image2")
cv2.setMouseCallback("image2", on_EVENT_LBUTTONDOWN2)
cv2.imshow("image2", img1)
cv2.waitKey(0)
p0=np.float32([[[a[0],b[0]]],[[a[1],b[1]]],[[a[2],b[2]]],[[a[3],b[3]]]])
print(p0)
cv2.destroyAllWindows()
#光流追踪关键点
lk_params = dict(winSize=(15,15), maxLevel=2,
criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
mask = np.zeros_like(frame)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
while True:
ret, frame = cap.read()
frame = cv2.resize(frame, None, fx=scaling_factor,
fy=scaling_factor, interpolation=cv2.INTER_AREA)
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
p1, st, err = cv2.calcOpticalFlowPyrLK(gray, frame_gray, p0, None, **lk_params)
good_new = p1[st == 1]
good_old = p0[st == 1]
for i,(new,old) in enumerate(zip(good_new,good_old)):
e,f = new.ravel()
e=int(e)
f=int(f)
g,h = old.ravel()
g=int(g)
h=int(h)
cv2.line(mask, (e, f),(g, h),(0, 150, 0), 1)
cv2.circle(frame, (e, f), 3, (0, 255, 0), -1)
# 二、矩阵变换
points1 = np.float32([[[a[4],b[4]]],[[a[5],b[5]]],[[a[6],b[6]]],[[a[7],b[7]]]])
points2 = np.float32(p1)
M = cv2.getPerspectiveTransform(points1, points2)
Affine_img = cv2.warpPerspective(img1, M, (frame.shape[1], frame.shape[0]))
# 三、内容替换
m = p1[2][0][0]-p1[0][0][0] #m=a[2]-a[0]
m=int(m)
n = p1[2][0][1]-p1[0][0][1] #n=b[2]-b[0]
n=int(n)
a1 = int(p1[0][0][1])
a2 = int(p1[0][0][0])
a3 = int(p1[0][0][1])
a4 = int(p1[0][0][0])
for i in range(n):
for j in range(m):
frame[a1+i][a2+j] = Affine_img[a3+i][a4+j]
cv2.namedWindow("image3")
cv2.imshow("image3",Affine_img) # 显示图片
# cv2.imshow("image2",np.array(img_cov, dtype = np.uint8 ))
cv2.waitKey(0)
cv2.destroyAllWindows()
gray = frame_gray.copy()
p0 = good_new.reshape(-1, 1, 2)
img = cv2.add(frame, mask)
cv2.imshow("Output", img)
k = cv2.waitKey(30)
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
完结撒花!
Original: https://blog.csdn.net/Josepyth/article/details/125288514
Author: Josepyth
Title: Python:计算机视觉实现视频的AI换脸(最基础)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/532461/
转载文章受原作者版权保护。转载请注明原作者出处!