Я бы не стал использовать циклы в этом случае, cv2.resize()
выполнит работу.
Вот сравнение времени между тремя подходами:
import PIL.Image as Img
import numpy as np
from time import perf_counter
import cv2
def timer(method):
def timed(*args, **kwargs):
t1 = perf_counter()
result = method(*args, **kwargs)
t2 = perf_counter()
print(f'{method.__name__} time: {t2 - t1} seconds')
return result
return timed
@timer
def resize_1(image_path, shrink):
img = Img.open(image_path, 'r')
r, g, b = img.split()
channels = np.array([np.array(r), np.array(g), np.array(b)])
small_channels = []
for channel in channels:
x_len = len(channel)//shrink
y_len = len(channel[0])//shrink
for chunk_x in range(x_len):
for chunk_y in range(y_len):
pix_sum = 0
for x_in_chunk in range(shrink):
for y_in_chunk in range(shrink):
pix_sum += channel[chunk_x*shrink+x_in_chunk,chunk_y*shrink+y_in_chunk]
channel[chunk_x,chunk_y] = pix_sum // 100
small_channels.append(channel[:x_len,:y_len])
channels = np.array(small_channels)
grayscale = np.round((channels[0]*0.3+ channels[1]*0.6+ channels[2]*0.1)).astype('uint8')
pixels = np.stack([grayscale, grayscale, grayscale], axis = 2)
return Img.fromarray(pixels)
@timer
def resize_2(image_path, shrink):
img = Img.open(image_path, 'r')
r, g, b = img.split()
channels = np.array([np.array(r), np.array(g), np.array(b)])
small_channels = []
for channel in channels:
x_len = len(channel)//shrink
y_len = len(channel[0])//shrink
for chunk_x in range(x_len):
for chunk_y in range(y_len):
# slice all pixels within 10*10 box and sum them
pix_sum = channel[chunk_x*shrink:shrink*(chunk_x+1),
chunk_y*shrink:shrink*(chunk_y+1)].sum()
channel[chunk_x, chunk_y] = pix_sum // 100
small_channels.append(channel[:x_len,:y_len])
channels = np.array(small_channels)
grayscale = np.round((channels[0]*0.3+ channels[1]*0.6+ channels[2]*0.1)).astype('uint8')
pixels = np.stack([grayscale, grayscale, grayscale], axis = 2)
return Img.fromarray(pixels)
@timer
def resize_3(image_path, shrink):
image = cv2.imread(image_path)
size = image.shape[:-1]
new_size = tuple(int(item / shrink) for item in size)[::-1]
resized = cv2.resize(image, tuple(new_size))
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
return gray
if __name__ == '__main__':
img = 'sample_image.png'
shrink_by = 10
image1, image2, image3 = [item(img, shrink_by) for item in [resize_1, resize_2, resize_3]]
image1.show()
image2.show()
cv2.imshow('resize_3', image3)
cv2.waitKey(0)
cv2.destroyAllWindows()
Out:
resize_1 time: 1.980221013 seconds
resize_2 time: 0.3170622839999999 seconds
resize_3 time: 0.01659756599999973 seconds