纸上得来终觉浅:测试Pillow与OpenCV调整(缩减)图片尺寸的效率

《每天进步一点点:使用Python批量修改图片尺寸》一文中,我曾提到之所以选择使用OpenCV库而不是Pillow,是因为OpenCV库使用C++实现,而Pillow是纯Python实现,所以使用OpenCV会比Pillow高效一点点。

image.png
(图源 :pixabay)

当我用Python+OpenCV成功实现想要的功能后,出于学习的目的,我又使用Pillow把相应功能重新实现一遍。但是在测试过程中,直观的感受是Python+Pillow反而比Python+OpenCV要快一点点。

那么在缩减图片这个操作上,两者到底谁更高效一些呢?我突然生出了将它们比较一番的心思。说干就干,与其道听途说或者盲目猜测,何不用程序拿数据说话呢?

为了更好的进行比较,我将两者缩减图片的函数调整为差不多的样子,分别如下:

def resize_image_by_opencv(file_path, scale_percent):
    print("Process by OpenCV")
    img = cv2.imread(file_path)
    width = int(img.shape[1] * scale_percent / 100)
    height = int(img.shape[0] * scale_percent / 100)
    resized_img = cv2.resize(img, (width, height))
    cv2.imwrite(file_path, resized_img)

以上代码为使用OpenCV调整图片。

def resize_image_by_pillow(file_path, scale_percent):
    print("Process by Pillow")
    img = Image.open(file_path)
    width = int(img.size[0] * scale_percent / 100)
    height = int(img.size[1] * scale_percent / 100)
    resized_img = img.resize((width, height))
    resized_img.save(file_path)

以上代码为使用Pillow调整图片。

然后在程序中加上测量耗时的代码:

import time
def main(argv=None):
    start = time.time()
    #cpu_start = time.clock()
    process_start = time.process_time()
    perf_start = time.perf_counter()

    for file_name in os.listdir(folder_path):
        if file_name.endswith('.jpg') or file_name.endswith('.png'):
            print(file_name)
            file_path = os.path.join(folder_path, file_name)
            resize_image_by_opencv(file_path, scale_percent)
            #resize_image_by_pillow(file_path, scale_percent)

    end = time.time()
    #cpu_end = time.clock()
    process_end = time.process_time()
    perf_end = time.perf_counter()
    #print("CPU Time:", cpu_end - cpu_start)
    print("Proc Time:", process_end - process_start)
    print("Exec Time:", end - start)
    print("Perf Time:", perf_end - perf_start)

接下来就是进行测试啦,从去大洋山爬山的相册中选择出38张照片,第一次运行程序,亦即使用OpenCV进行图片缩减。

这里额外说一下,在批处理文件中,我在文件第一行添加了如下语句:

color 17

上述代码的意思是将前景色设置为白色,将背景色设置为蓝色,这样看起来比较舒服(以前TC2.0以及Basic啥的界面全是这个颜色)

执行部分输出如下:
image.png

然后进行第二次测试,删除目录中的图片,重新从去大洋山爬山的相册中选择出38张照片,将main函数中调整图片尺寸的代码修改为使用Pillow,亦即:

             #resize_image_by_opencv(file_path, scale_percent)
             resize_image_by_pillow(file_path, scale_percent)

然后重新执行批处理脚本:

image.png

将两次操作中时间部分截取出来。

使用OpenCV:

Proc Time: 8.484375
Exec Time: 5.6140031814575195
Perf Time: 5.613874399998167

使用Pillow:

Proc Time: 4.65625
Exec Time: 4.69614839553833
Perf Time: 4.696085299998231

可见在调整图片尺寸这个简单的应用中,Python+Pillow要优于Python+OpenCV的。处理38张图片,实际耗时快了大约1秒左右。

这里我们还注意到一个问题,就是使用OpenCV,CPU时间的耗费要远高于Python+Pillow,大概因为不是原生Python代码,需要反复调用的缘故。

所以,至少在调整图片这个应用情形下,使用Python+Pillow无疑是最佳选择。

那么你可能会问,之前不是说:

OpenCV库使用C++实现,而Pillow是纯Python实现,所以使用OpenCV会比Pillow高效一点点。

我觉得一方面“纸上得来终觉浅,绝知此事要躬行”,不能人云亦云,道听途说,要自己实际测试一下;而另一方面,实在是调整图片尺寸只是所有图片操作中最最最简单的一个,杀鸡用牛刀,OpenCV的优势完全没有体现出来,如果要做一些极为复杂的图片操作,我相信结果会完全不一样的。

至于我做这个测试,纯属无聊,毕竟不为无益之事,何以遣有涯之生!


补充说一下代码中time.clock()的问题,在Python3.8之前可以使用如下代码来测试CPU时间:

import time
start = time.clock()
......
end =  time.clock()
print("CPU Time: ", end - start)

但是它在Linux与Windows下行为不太一致,所以Python3.8开始,就把这个移除啦,使用time.process_time()time.perf_counter()作为替代。

看来各种程序、代码库再不断更新,我们也必须随时跟进呢,否则就落伍了呢。


好了,经过O哥一顿猛如虎的操作,每次发图片贴,又可以节省一秒的时间,好开心呀,毕竟时间就是生命,时间就是金钱呀。😊

相关链接

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now