缩放+锐化:做多一步,得到效果更好的缩略图

缩放+锐化:做多一步,得到效果更好的缩略图

先容我啰嗦一下做这个实验的“历史”:

这事儿大概可以追溯到13年10月,当时老陈拉我入伙做一个旅行游记的项目(很可惜我们没有坚持下去),不知道他怎么突发其想(fā shén jīng)打算用python来做后台,我说卧槽哥我不会python啊,他说没事,我也不会。行呗,那就学呗(这就是为什么本文代码会用python来实现)。

然后有一天,老陈突然发了一个“广告帖”给我看,大体内容是关于花瓣网的,其中鼓吹了花瓣网的图片处理技术多么多么牛逼。老陈说他还真试了一下,发现几大游记网站(马蜂窝、蝉游记等)的照片上传后的缩略图质量确实不如上传到花瓣网的,要不咱研究研究?研究成了咱也能吹吹咱网站的图片处理技术。(这就是本文的主题:得到效果更好的缩略图)


1. 几个网站的效果对比

通常,相机(手机)的照片大小都是几个mb的。对于图片类网站(包括旅行游记类网站),不可能在展示时候直接就给你展示原图,那刷图得慢死你。一般的操作是在用户上传照片时就将照片压缩为两个等级的大小,我们暂且称为大缩略图跟小缩略图(服务器空间大的离谱的话你还可以保存原图)。本文主要比较的是大缩略图。

 照片原图
面包旅行
40kb
640x424
DSC_6083_BreadTrip_thumbnail
蝉游记
35kb
600x300
DSC_6083_chanyouji_thumbnail
(呐别问我为啥图被裁了,我怎么知道)
花瓣网
133kb
580x384
DSC_6083_huaban_displayS
ACDSee
130kb
580x384
DSC_6083_ACDSee

从上面几张我们可以看到,缩略图效果最好是花瓣网,其次是ACDSee软件缩放处理后的(使用默认参数),然后是蝉游记,面包旅行。缩放到相同尺寸的照片,花瓣跟ACDSee的画面会更清晰,颜色更鲜艳,锯齿也少,当然这也导致他们需要更多的字节来存储。但对于一张用来做展示的照片,100多kb,我觉得是可以接受的。

2. 算法研究

Resize
单纯的只对图像进行缩放,我试验过了python的PIL库跟OPENCV库的几种缩放算法。得出的结果分两种:
第一种,如NEAREST、BILINEAR、BICUBIC算法。缩放后颜色保持的好,但线条处会有锯齿状。
第二中,如PIL的ANTIALIAS算法和OPENCV的AREA算法。缩放后图像有些模糊,但不会出现锯齿状。

Sharpen
为了让缩放后图像又无锯齿,又能保持清晰。我们可以对经过反锯齿缩放(模糊缩放)后得到的图像,再进行一次锐化操作,使图像更加清晰。

经过试验,发现使用 模糊缩放 + 锐化增强 完全可以达到等同于花瓣网和ACDSee的处理效果。

3. 算法实现

现在就是比较python的PIL和OPENCV库中哪个算法实现的效率更快。
读取图像:PIL快,OPENCV慢
缩放:PIL慢,OPENCV快
锐化:PIL快,OPENCV没找到
存图:PIL快,OPENCV快

经过多次试验比较,发现最快效率的步骤是:
使用OPENCV读取图像,
CV2_ImgOriginal = cv2.imread(strSourceFilePathName)
使用OPENCV的模糊缩放,
CV2_ImgResized = cv2.resize(CV2_ImgOriginal, (nWidth, nHeight), None, 0, 0, cv2.INTER_AREA)
将OPENCV图像转换为PIL图像,
CV2_ImgResized = cv2.cvtColor(CV2_ImgResized, cv2.COLOR_BGR2RGB)
PIL_ImgResized = Image.fromarray(CV2_ImgResized)
使用PIL的锐化增强,
PIL_ImgEnhanced = ImageEnhance.Sharpness(PIL_ImgResized).enhance(2.0)
使用PIL的存图函数。
PIL_ImgEnhanced.save(‘_resized.jpg’, 'JPEG', quality = 95)

最后的缩放效果与三个参数有关:缩放参数、锐化参数、jpeg存图质量参数。你可以通过调整这几个参数达到最优的效果。

4. 实验效果

花瓣网
133kb
580x384
DSC_6083_huaban_displayS
缩放+锐化
104kb
580x384
DSC_6083_original_ANTIALIAS+Sharpen

 

 照片原图
蝉游记
45kb
530x800
DSC_6603_chanyouji_display
花瓣网
182kb
580x876
DSC_6603_huaban_displayS
缩放+锐化
149kb
580x876
DSC_6603_original_ANTIALIAS+Sharpen

5. pyton实现代码

import cv2, Image, ImageEnhance, time, os

strSourceFolder = raw_input("Input Source Images Folder:")
strOutputFolder = raw_input("Input Output Images Folder:")
nWidth = int(raw_input("Input Resized Width:"))

print "resizing..."
StartTime = time.clock()
nCounter = 0
for file in os.listdir(strSourceFolder):
    strSourceFilePathName = os.path.join(strSourceFolder, file)
    CV2_ImgOriginal = cv2.imread(strSourceFilePathName)
    fRatio = float(CV2_ImgOriginal.shape[1]) / nWidth
    nHeight = int(CV2_ImgOriginal.shape[0] / fRatio)
    CV2_ImgResized = cv2.resize(CV2_ImgOriginal, (nWidth, nHeight), None, 0, 0, cv2.INTER_AREA)
    CV2_ImgResized = cv2.cvtColor(CV2_ImgResized, cv2.COLOR_BGR2RGB)
    PIL_ImgResized = Image.fromarray(CV2_ImgResized)
    PIL_ImgEnhanced = ImageEnhance.Sharpness(PIL_ImgResized).enhance(2.0)
    strFilename = os.path.splitext(file)[0]
    PIL_ImgEnhanced.save(os.path.join(strOutputFolder, strFilename) + "_resized.jpg", 'JPEG', quality = 95)
    nCounter = nCounter + 1
    print file, "processed"
EndTime = time.clock()
print "Processed", nCounter, "images"
print "Total elapsed time:", EndTime - StartTime, "Seconds"

如果使用php的话,可以使用image magick图像处理库来进行缩放+锐化操作。(为php安装imagick拓展与image magick图像库)
app中的话,我想应该可以在app中先做好缩放处理再上传到后台,这样可以减轻服务器的压力。

Leave a Reply

Your email address will not be published. Required fields are marked *