搞笑全景影片合成效果
这篇教学会透过 OpenCV 操作图像的数组,在即时截取摄影机画面时,将部分的内容固定成静态图像,最后组合成搞笑的全景影片效果。
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
制作一条会动的直线
参考“line() 画直线”文章范例,在读取摄影机镜头画面,在画面中绘制一条上到下的红色直线,透过 while 循环改变直线的 x 座标,就能让红色直线从画面的左边移动到右边,搭配判断 x 座标的逻辑,就能让红色直线不断在画面中移动。
import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
w, h = 640, 360 # 定義長寬
x = 0 # 定義 x 從 0 開始
while True:
ret, img = cap.read()
if not ret:
print("Cannot receive frame")
break
img = cv2.resize(img,(w,h)) # 縮小尺寸加快速度
img = cv2.flip(img, 1) # 翻轉影像,使其如同鏡子
img = img[:, int((w-h)/2):int((h+(w-h)/2))] # 將影像變成正方形
cv2.line(img,(x,0),(x,h),(0,0,255),5) # 畫線
cv2.imshow('oxxostudio',img) # 正常狀況下,一直顯示即時影像
x = x + 2
if x > h:
x = 0
keyCode = cv2.waitKey(10) # 等待鍵盤事件
if keyCode == ord('q'):
break # 按下 q 就全部結束
cap.release()
cv2.destroyAllWindows()
左到右的全景图像合成
延伸红色线条移动的程序码,新增一个 output 黑色画布,当线条移动的同时,截取图像中某个范围 ( 例如不断从左到右截取 2x360 的范围 ),将这些范围组合成静态图像,最后就会输出一张全景的合成图像,如果在过程中改变姿势,就会出现莫名其妙的有趣结果,详细程序码解说在注解中,下方列出一些重点:
- 定义变数 a 和 run 作为存档的档名编号,以及判断是否开始。
- output 为全黑的画布。
- 判断键盘事件,按下 a 才开始。
- 当截取结束,按下 s 可以存档。
- 截取的当下,将静态图像合成到 output 画布,再将静态区域提供给输出的 img 使用。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
w, h = 640, 360 # 定義長寬
a = 1 # 存檔的檔名編號從 1 開始
run = 0 # 是否開始,0 表示尚未開始,1 表示開始
output = np.zeros((h,h,3), dtype='uint8') # 設定合成的影像為一張全黑的畫布 ( 長寬使用正方形 )
while True:
ret, img = cap.read()
if not ret:
print("Cannot receive frame")
break
img = cv2.resize(img,(w,h)) # 縮小尺寸加快速度
img = cv2.flip(img, 1) # 翻轉影像,使其如同鏡子
img = img[:, int((w-h)/2):int((h+(w-h)/2))] # 將影像變成正方形
keyCode = cv2.waitKey(10) # 等待鍵盤事件
if keyCode == ord('a') and run == 0:
x = 0 # 如果按下 a,設定 x 為 0
run = 1 # 開始合成
elif keyCode == ord('q'):
break # 按下 q 就全部結束
if run == 1:
output[0:h, x:x+2] = img[0:h, x:x+2] # 設定 output 的某個區域為即時影像 img 的某區域
cv2.line(img,(x+5,0),(x+5,h),(0,0,255),5) # 畫線 ( 因為線條寬度 5,所以位移 5 )
x = x + 2 # 改變 x 位置
img[0:h,0:x] = output[0:h,0:x] # 設定即時影像 img 的某區域為 output
cv2.imshow('oxxostudio',img) # 顯示即時影像
if x > h:
keyCode = cv2.waitKey() == ord('s') # 如果寬度抵達正方形邊緣,等待鍵盤事件按下 s
cv2.imwrite(f'oxxo-{a}.jpg',img) # 存檔
a = a + 1 # 檔名編號增加 1
run = 0 # 停止合成
else:
cv2.imshow('oxxostudio',img) # 正常狀況下,一直顯示即時影像
cap.release()
cv2.destroyAllWindows()
上到下的全景图像合成
运用同样的原理,修改参数,就可将图像改成从上到下的全景图像合成。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
w, h = 640, 360 # 定義長寬
a = 1 # 存檔的檔名編號從 1 開始
run = 0 # 是否開始,0 表示尚未開始,1 表示開始
output = np.zeros((h,h,3), dtype='uint8') # 設定合成的影像為一張全黑的畫布
while True:
ret, img = cap.read()
if not ret:
print("Cannot receive frame")
break
img = cv2.resize(img,(w,h)) # 縮小尺寸加快速度
img = cv2.flip(img, 1) # 翻轉影像,使其如同鏡子
img = img[:, int((w-h)/2):int((h+(w-h)/2))] # 將影像變成正方形
keyCode = cv2.waitKey(10) # 等待鍵盤事件
if keyCode == ord('a') and run == 0:
y = 0 # 如果按下 a,設定 y 為 0
run = 1 # 開始合成
elif keyCode == ord('q'):
break # 按下 q 就全部結束
if run == 1:
output[y:y+2, 0:h] = img[y:y+2, 0:h] # 設定 output 的某個區域為即時影像 img 的某區域
cv2.line(img,(0,y+5),(h,y+5),(0,0,255),5) # 畫線
y = y + 2 # 改變 x 位置
img[0:y,0:h] = output[0:y,0:h] # 設定即時影像 img 的某區域為 output
cv2.imshow('oxxostudio',img) # 顯示即時影像
if y > h:
keyCode = cv2.waitKey() == ord('s') # 如果寬度抵達正方形邊緣,等待鍵盤事件按下 s
cv2.imwrite(f'oxxo-{a}.jpg',img) # 存檔
a = a + 1 # 檔名編號增加 1
run = 0 # 停止合成
else:
cv2.imshow('oxxostudio',img) # 正常狀況下,一直顯示即時影像
cap.release()
cv2.destroyAllWindows()
微信扫码关注
抖音扫码关注