倒数计时自动拍照效果
不论是数码相机还是手机的相机,都会具备“倒数计时自动拍照”的功能,这篇教学会介绍使用 OpenCV,实作倒数计时自动拍照的效果 ( 按下键盘后倒数秒数,时间到就会出现快门闪烁的效果进行拍照 )。
快速导览:
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
拍照时的快门闪烁效果
使用手机倒数计时拍照时,在拍照的当下会出现快门闪烁效果 ( 整个画面全白,然后白色逐渐消失再出现原本的画面 ),为了实现这个效果,必须要建立一个“全白”的图片 ( 使用负片效果将 numpy 产生的全黑图片反转 ),透过“权重叠加”的方式将白色图片与原本图像重叠,接着让白色慢慢消失,就能制作出类似闪烁一下的效果。
import cv2
import numpy as np
img = cv2.imread('mona.jpg') # 開啟圖片
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) # 轉換成 BGRA ( 因為需要 alpha 色版 )
w = img.shape[1] # 取得寬度
h = img.shape[0] # 取得高度
white = 255 - np.zeros((h,w,4), dtype='uint8') # 建立白色圖
a = 1 # 一開始 a 為 1
while True:
a = a - 0.01 # a 不斷減少 0.01
if a<0: a = 0 # 如果 a 小於 0 就讓 a 等於 0
output = cv2.addWeighted(white, a, img, 1-a, 0) # 根據 a 套用權重
cv2.imshow('oxxostudio', output) # 顯示圖片
if cv2.waitKey(1) == ord('q'):
break
cap.release() # 所有作業都完成後,釋放資源
cv2.destroyAllWindows() # 結束所有視窗
由于 imshow 如果指定同一个视窗,则在程序中只能出现一次,根据这个规则改写程序,加入侦测“空白键”的功能,当按下空白键时,才会出现闪烁效果。
参考:侦测键盘行为
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
img = cv2.imread('mona.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
w = img.shape[1]
h = img.shape[0]
white = 255 - np.zeros((h,w,4), dtype='uint8')
a = 0 # 開始時 a 等於 0
while True:
key = cv2.waitKey(1) # 偵測按鍵
if key == 32:
a = 1 # 如果按下空白鍵,讓 a 等於 1
elif key == ord('q'):
break
if a == 0:
output = img.copy() # 如果 a 等於 0,複製來源圖片為 output
else:
output = cv2.addWeighted(white, a, img, 1-a, 0) # 如果 a 等於 1,根據 a 套用權重
a = a - 0.01 # a 不斷減少 0.01
if a<0: a = 0 # 如果 a 小於 0 就讓 a 等於 0
cv2.imshow('oxxostudio', output)
cap.release()
cv2.destroyAllWindows()
按下空白键就拍照
参考“读取并播放影片”以及“写入并储存图片”文章,将程序修改成读取摄影镜头的影片,并在按下空白键时,将当下的图片存档,就能实现按下空白键拍照 ( 包含快门闪烁 ) 的效果。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
a = 0 # 白色圖片透明度
n = 0 # 檔名編號
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, img = cap.read() # 讀取影片的每一幀
if not ret:
print("Cannot receive frame") # 如果讀取錯誤,印出訊息
break
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) # 轉換顏色為 BGRA
w = int(img.shape[1]*0.5) # 縮小寬度為一半
h = int(img.shape[0]*0.5) # 縮小高度為一半
img = cv2.resize(img,(w,h)) # 縮放尺寸
white = 255 - np.zeros((h,w,4), dtype='uint8') # 產生全白圖片
key = cv2.waitKey(1)
if key == 32: # 按下空白將 a 等於 1
a = 1
elif key == ord('q'): # 按下 q 結束
break
if a == 0:
output = img.copy() # 如果 a 為 0,設定 output 變數為來源圖片的拷貝
else:
photo = img.copy() # 如果 a 不為 0,設定 photo 變數為來源圖片的拷貝
output = cv2.addWeighted(white, a, photo, 1-a, 0) # 計算權重,產生白色慢慢消失效果
a = a - 0.1
if a<0:
a = 0
n = n + 1
cv2.imwrite(f'photo-{n}.jpg', photo) # 存檔
cv2.imshow('oxxostudio', output) # 顯示圖片
cap.release() # 所有作業都完成後,釋放資源
cv2.destroyAllWindows() # 結束所有視窗
按下空白键,倒数计时自动拍照
参考“图像加入文字”文章,修改程序,在程序中新增一个 sec 秒数的变数以及对应的判断,当按下空白键时,在画面中出现出现倒数的秒数,当秒数为 0 时就进行拍照。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
# 定義加入文字的函式
def putText(source, x, y, text, scale=2.5, color=(255,255,255)):
org = (x,y)
fontFace = cv2.FONT_HERSHEY_SIMPLEX
fontScale = scale
thickness = 5
lineType = cv2.LINE_AA
cv2.putText(source, text, org, fontFace, fontScale, color, thickness, lineType)
a = 0
n = 0
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, img = cap.read()
if not ret:
print("Cannot receive frame")
break
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
w = int(img.shape[1]*0.5)
h = int(img.shape[0]*0.5)
img = cv2.resize(img,(w,h))
white = 255 - np.zeros((h,w,4), dtype='uint8')
key = cv2.waitKey(1)
if key == 32:
a = 1
sec = 4 # 加入倒數秒數
elif key == ord('q'):
break
if a == 0:
output = img.copy()
else:
output = img.copy() # 設定 output 和 photo 變數
photo = img.copy()
sec = sec - 0.05 # sec 不斷減少 0.05 ( 根據個人電腦效能設定,使其搭配 while 迴圈看起來像倒數一秒 )
putText(output, 10, 70, str(int(sec))) # 加入文字
# 如果秒數小於 1
if sec < 1:
output = cv2.addWeighted(white, a, photo, 1-a, 0)
a = a - 0.1
if a<0:
a = 0
n = n + 1
cv2.imwrite(f'photo-{n}.jpg', photo)
cv2.imshow('oxxostudio', output)
cap.release()
cv2.destroyAllWindows()
微信扫码关注
抖音扫码关注