Python的图像缩放(resize)方法
双线性差值方法的详细过程,
推荐博客:三十分钟理解:线性插值,双线性插值Bilinear Interpolation算法。
接下来,展示的是基于Python、cv2和skimage实现双线性差值的图像缩放。
#! python
#
import os
import sys
import time
# Matplotlib.
import matplotlib.pyplot as plt
# PIL.
from PIL import Image
# Numpy.
import numpy as np
# OpenCV.
import cv2
# Skimage.
import skimage
from skimage import transform
# TODO: Resize.
dst_width, dst_height = 192, 108
# py_Resize.
def py_Resize(src, shape):
# Shape.
height, width, channels = src.shape
dst_width, dst_height = shape
if ((dst_height == height) and (dst_width == width)):
return src
# Object.
dst_Image = np.zeros((dst_height, dst_width, channels), np.uint8)
# Resize.
# Scale for resize.
scale_x = float(width)/dst_width
scale_y = float(height)/dst_height
# tmp
for k in range(channels):
for dst_y in range(dst_height):
for dst_x in range(dst_width):
# Original coords.
src_x = (dst_x + 0.5) * scale_x - 0.5
src_y = (dst_y + 0.5) * scale_y - 0.5
# INTER_LINEAR:
# 2*2 neighbors.
src_x_0 = int(np.floor(src_x))
src_y_0 = int(np.floor(src_y))
src_x_1 = min(src_x_0 + 1, width - 1)
src_y_1 = min(src_y_0 + 1, height - 1)
#
value0 = (src_x_1 - src_x) * src[src_y_0, src_x_0, k] + (src_x - src_x_0) * src[src_y_0, src_x_1, k]
value1 = (src_x_1 - src_x) * src[src_y_1, src_x_0, k] + (src_x - src_x_0) * src[src_y_1, src_x_1, k]
#
dst_Image[dst_y, dst_x, k] = int((src_y_1 - src_y) * value0 + (src_y - src_y_0) * value1)
return dst_Image
# Read the image.
# PIL.
im = Image.open('show.jpg')
print (im.size)
#(width, height): (1920, 1080)
# Numpy.
im_org = np.array(im)
print (im_org.shape)
#(height, width, channel): (1080, 1920, 3)
# 1. python.
_start = time.time()
imResize_py = py_Resize(im_org, (dst_width, dst_height)) # in 1
time1 = time.time() - _start
# 2. opencv.
_start = time.time()
imResize_cv = cv2.resize(im_org, (dst_width, dst_height))
time2 = time.time() - _start
# 3. skimage.
_start = time.time()
imResize_ski = transform.resize(im_org, (dst_height, dst_width))
time3 = time.time() - _start
# Show ALL.
plt.subplot(2,2,1); plt.title('ORG'); plt.imshow(im_org)
plt.subplot(2,2,2); plt.title('PY_resize: %fs' %(time1)); plt.imshow(imResize_py)
plt.subplot(2,2,3); plt.title('CV_resize: %fs' %(time2)); plt.imshow(imResize_cv)
plt.subplot(2,2,4); plt.title('SKI_resize: %fs' %(time3)); plt.imshow(imResize_ski)
plt.show()
结果展示:
详细的源码如下:
1. Python代码实现
# 1. python.
imResize_py = py_Resize(im_org, (dst_width, dst_height))
# Numpy.
import numpy as np
# py_Resize.
def py_Resize(src, shape):
# Shape.
height, width, channels = src.shape
dst_width, dst_height = shape
if ((dst_height == height) and (dst_width == width)):
return src
# Object.
dst_Image = np.zeros((dst_height, dst_width, channels), np.uint8)
# Resize.
# Scale for resize.
scale_x = float(width)/dst_width
scale_y = float(height)/dst_height
# tmp
for k in range(channels):
for dst_y in range(dst_height):
for dst_x in range(dst_width):
# Original coords.
src_x = (dst_x + 0.5) * scale_x - 0.5
src_y = (dst_y + 0.5) * scale_y - 0.5
# INTER_LINEAR:
# 2*2 neighbors.
src_x_0 = int(np.floor(src_x))
src_y_0 = int(np.floor(src_y))
src_x_1 = min(src_x_0 + 1, width - 1)
src_y_1 = min(src_y_0 + 1, height - 1)
#
value0 = (src_x_1 - src_x) * src[src_y_0, src_x_0, k] + (src_x - src_x_0) * src[src_y_0, src_x_1, k]
value1 = (src_x_1 - src_x) * src[src_y_1, src_x_0, k] + (src_x - src_x_0) * src[src_y_1, src_x_1, k]
#
dst_Image[dst_y, dst_x, k] = int((src_y_1 - src_y) * value0 + (src_y - src_y_0) * value1)
return dst_Image
2.OpenCV实现
# 2. opencv.
import cv2
#
imResize_cv = cv2.resize(im_org, (dst_width, dst_height))
3. Skimage实现
# 3. skimage.
import skimage
from skimage import transform
#
imResize_ski = transform.resize(im_org, (dst_height, dst_width))
总结:
OpenCV处理速度最快,Skimage次之,自写Python函数速率太渣。
实际应用中,OpenCV安装太复杂,自写效率太低,建议采用Skimage。