1.7 模拟光艺术/长曝光
长曝光(或光艺术)指的是捕捉到时间流逝效果的照片的拍摄过程。长曝光照片的一些流行应用实例包括如绸缎般光滑的水、高速公路上汽车前灯形成的单一的连续运动照明带。在本实例中,我们将通过平均化视频中的图像帧来模拟长曝光。
1.7.1 准备工作
在本实例中,我们将从视频中提取图像帧,然后平均化图像帧来模拟光艺术。让我们先导入所需要的Python库:
from glob import glob import cv2 import numpy as np import matplotlib.pylab as plt
1.7.2 执行步骤
要模拟光艺术/长曝光,我们需要执行以下步骤。
1.实现extract_frames()函数,通过该函数从输入参数(传递给函数的视频中)提取前200(最多)帧图像:
def extract_frames(vid_file): vidcap = cv2.VideoCapture(vid_file) success,image = vidcap.read() i = 1 success = True while success and i <= 200: cv2.imwrite('images/exposure/vid_{}.jpg'.format(i), image) success,image = vidcap.read() i += 1
2.调用上述函数,把从Godafost(冰岛)瀑布视频中所提取的所有帧图像(扩展名为.jpg的文件)保存到exposure文件夹中:
extract_frames('images/godafost.mp4') #cloud.mp4
3.从exposure文件夹中读取所有扩展名为.jpg的文件,以float类型来读取每个文件的内容,将每个图像分成B、G和R这3个颜色通道;计算颜色通道的当前和;最后,计算颜色通道的平均值:
imfiles = glob('images/exposure/*.jpg') nfiles = len(imfiles) R1, G1, B1 = 0, 0, 0 for i in range(nfiles): image = cv2.imread(imfiles[i]).astype(float) (B, G, R) = cv2.split(image) R1 += R B1 += B G1 += G R1, G1, B1 = R1 / nfiles, G1 / nfiles, B1 / nfiles
4.合并所得到的颜色通道的平均值,并保存最终输出图像:
final = cv2.merge([B1, G1, R1]) cv2.imwrite('images/godafost.png', final)
图1-14显示了从视频中所提取的一个输入帧。
图1-14
运行上述代码,将得到图1-15所示的一幅长曝光图像。
请注意观察云和瀑布中的连续效果。
图1-15
1.7.3 工作原理
调用OpenCV-Python库中的VideoCapture()函数,通过该函数,我们可以创建一个以视频文件作为输入的VideoCapture对象。然后,使用该对象的read()方法来从视频中捕获图像帧。
通过OpenCV-Python库的imread()和imwrite()函数分别从/向磁盘读取/写入图像。
调用cv2.split()函数,通过该函数将RGB图像拆分为单独的颜色通道;调用cv2.merge()函数,通过该函数将单独的颜色通道组合回RGB图像。
1.7.4 更多实践
焦点叠加(也称为扩展景深)是(在图像处理/计算摄影中的)一种技术/技巧,该技术采用多张图像(对同一对象在不同焦距处进行拍摄)作为输入,然后通过组合输入图像来创建一个比任何单个源图像都具有更高景深(DOF)的输出图像。读者可以在Python中模拟焦点叠加技术。以下是一个使用mahotas库对从视频中提取的灰度图像帧实现焦点叠加的例子。
使用Mahotas库来扩展景深
使用mahotas库函数,通过执行以下步骤来实现焦点叠加。
1.通过从夜间高速公路交通视频中提取灰度图像帧来创建图像堆栈:
import mahotas as mh def create_image_stack(vid_file, n = 200): vidcap = cv2.VideoCapture(vid_file) success,image = vidcap.read() i = 0 success = True h, w = image.shape[:2] imstack = np.zeros((n, h, w)) while success and i < n: imstack[i,...] = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) success,image = vidcap.read() i += 1 return imstack image = create_image_stack('images/highway.mp4') #cloud.mp4 stack,h,w = image.shape
2.使用mahotas库的sobel()函数,将其计算结果作为聚焦的像素级度量:
focus = np.array([mh.sobel(t, just_filter=True) for t in image])
3.在每个像素位置,选择最佳切片(最大聚焦)并创建最终图像:
best = np.argmax(focus, 0) image = image.reshape((stack,-1)) # image is now (stack, nr_pixels) image = image.transpose() # image is now (nr_pixels, stack) final = image[np.arange(len(image)), best.ravel()] # Select the right pixel at each location final = final.reshape((h,w)) # reshape to get final result
图1-16所示的是在图像堆栈中所用到的其中一幅输入图像。
图1-16
由算法实现所生成的最终输出图像如图1-17所示。
图1-17