The source is https://github.com/osoken/tiltshift_effector
A Python script that applies a fake tilt shift effect to video files such as .mov
.
I used Numpy
, Scipy
, ʻOpenCV,
Pillow`. For Python 2.7.
The principle is simple, just combine the original image and the blurred image while masking it. original
mask
Blurred image
After synthesis
A function that creates a mask.
def gen_mask(sz, t, tc, c, bc):
bounds = (0,limit_value(int(sz[1]*t),0,sz[1]),limit_value(int(sz[1]*(t+tc)),0,sz[1]),limit_value(int(sz[1]*(t+tc+c)),0,sz[1]),limit_value(int(sz[1]*(t+tc+c+bc)),0,sz[1]),sz[1]);
mask = np.array(Image.new('L', sz));
mask[bounds[0]:bounds[1],:] = 255;
for i in range(bounds[1],bounds[2]):
mask[i,:] = 255 - int(255.0/float( bounds[2] - bounds[1] ) * float(i - bounds[1]));
mask[bounds[3]:bounds[2],:] = 0;
for i in range(bounds[3],bounds[4]):
mask[i,:] = int(255.0/float( bounds[4] - bounds[3] ) * float(i - bounds[3]));
mask[bounds[4]:bounds[5],:] = 255;
mask = Image.fromarray(mask);
return mask;
sz
is a tuple of(width, height)
. t
, tc
, c
, bc
are numbers from 0.0
to 1.0
, t
is the upper white area, c
is the middle black area, and tc
is Between t
and c
, bc
expresses the width of the gradation between c
and the white area below, with the overall ratio being 1.0
.
I used the gaussian_filter
in scipy
as it is to generate the blurred image.
def gen_blurred_image(image, blur_factor):
if blur_factor == 0:
return image;
im = np.array(image);
return Image.fromarray(ndimage.gaussian_filter(im, sigma=[blur_factor, blur_factor, 0]));
It is useless to convert the variable ʻimage to the
numpy.arraytype and immediately return it to the
PIL ʻImage
type just for filtering, but in consideration of other operations It looks like this ... blur_factor
is the strength of the blur, given as a floating point number.
After generating the mask and the blurred image, combine them with the paste
function of PIL
.
def paste_image(base, layer, mask):
im = base;
im.paste(layer, mask = mask);
return im;
Once you're ready, all you have to do is open the video and apply the same processing every frame.
cap = cv2.VideoCapture('input.mov');
orig_size = (int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)));
out = cv2.VideoWriter('output.mov', cv2.cv.CV_FOURCC('m','p','4','v'), int(cap.get(cv2.cv.CV_CAP_PROP_FPS)), orig_size);
mask = gen_mask(orig_size, 0.4, 0.15, 0.05, 0.1);
while cap.isOpened():
ret,im_orig = cap.read();
if ret == True:
im = Image.fromarray(im_orig);
im_blur = gen_blurred_image(im, 2.0);
im = np.array(paste_image(im, im_blur, mask));
cv2.imshow('view', im);
out.write(im);
key = cv2.waitKey(1);
if key == 27:
break;
else:
break;
out.release();
cap.release();
cv2.destroyAllWindows();
The version in the repository handles input options, etc., so the number of lines is large, but in essence it is like this. I also adjust the image quality and saturation. The last key == 27
in the loop ends prematurely with ʻesc`.
Recommended Posts