这里有个证件照换底的需求:将图像的透明底色换为红色背景。其逻辑是用一个嵌套的 for 循环分别遍历图像的行和列,判断每一个位置的像素点是否是透明的,如果是,换成红色背景;如果不是,则不做任何修改。但目前的问题是速度有点慢,需要做并行加速。我们用 Python 自带的多线程池进行优化,优化程序的代码如下:
"""安装依赖模块
pip install numpy opencv-python tqdm
"""
import time
import numpy as np
from cv2 import cv2
from tqdm import tqdm
import concurrent.futures as cf
class ChangeBackgroundColor():
"""修改图片背景的类(默认将透明背景修改为红色背景)
Args:
root (str): 输入图片的路径
"""
def __init__(self, root: str):
"""类的初始化函数
Args:
root (str): 输入图片的路径
"""
self.image_original = cv2.imread(root, cv2.IMREAD_UNCHANGED)
self.rows, self.cols, _ = self.image_original.shape
self.serial()
self.parallel()
def serial(self):
"""串行程序
"""
t1 = time.time()
for i in tqdm(range(self.rows), desc='Serial-Time'):
for j in range(self.cols):
if (self.image_original[i][j] == np.zeros(4)).all():
self.image_original[i][j] = np.array([0, 0, 255, 255])
else:
pass
t2 = time.time()
cv2.imwrite('./red.png', self.image_original)
def __temp__(self, i, pbar):
"""并行程序依赖的临时函数
Args:
i (int): 图片矩阵的行索引
pbar (tqdm()): tqdm的进度条实例
"""
for j in range(self.cols):
if (self.image_original[i][j] == np.zeros(4)).all():
self.image_original[i][j] = np.array([0, 0, 255, 255]) # 图片背景修改为红色 | 注意OPENCV的通道是BGR
else:
pass
pbar.update()
def parallel(self):
"""并行程序
"""
t1 = time.time()
with tqdm(total=self.rows, desc='Parallel-Time') as pbar:
with cf.ThreadPoolExecutor() as tp:
for i in range(self.rows):
tp.submit(self.__temp__, i, pbar)
t2 = time.time()
cv2.imwrite('./red.png', self.image_original)
if __name__ == '__main__':
ChangeBackgroundColor('./original.png')
代码命名已经做了多线程并行优化,但速度不但没有提升,反而下降了??
串行在我自己电脑上测试的是8s,并行测试的是23s。
会不会是 Python 全局解释锁(GIL)的问题?
(待解决……)