教你用Python壓縮圖片
阿新 • • 發佈:2018-12-15
質量、速度、廉價,選擇其中兩個
如果需要做圖片識別那麼必定需要大量的訓練素材,我們通常使用爬蟲來獲取,python爬取bing圖片,python爬取百度圖片,但是怕取下來的圖片大小不一,再進行訓練之前必須進行裁剪和壓縮,今天就來講一講圖片壓縮,下面這個例子是我做一個專案時用到的
import PIL.Image as Image import os #圖片壓縮批處理 def compressImage(srcPath,dstPath): for filename in os.listdir(srcPath): #如果不存在目的目錄則建立一個,保持層級結構 if not os.path.exists(dstPath): os.makedirs(dstPath) #拼接完整的檔案或資料夾路徑 srcFile=os.path.join(srcPath,filename) dstFile=os.path.join(dstPath,filename) # 如果是檔案就處理 if os.path.isfile(srcFile): try: #開啟原圖片縮小後儲存,可以用if srcFile.endswith(".jpg")或者split,splitext等函式等針對特定檔案壓縮 sImg=Image.open(srcFile) w,h=sImg.size dImg=sImg.resize((int(w/2),int(h/2)),Image.ANTIALIAS) #設定壓縮尺寸和選項,注意尺寸要用括號 dImg.save(dstFile) #也可以用srcFile原路徑儲存,或者更改字尾儲存,save這個函式後面可以加壓縮編碼選項JPEG之類的 print (dstFile+" 成功!") except Exception: print(dstFile+"失敗!!!!!!!!!!!!!!!!!!!!!!!!!!!!") # 如果是資料夾就遞迴 if os.path.isdir(srcFile): compressImage(srcFile, dstFile) if __name__=='__main__': compressImage("G:/兔屎圖片_未處理","G:/兔屎圖片_已處理")
可能這個方法不是很通用,因為我當時處理的圖片都是很大的,一個圖片大概在3M-5M這樣,而我並不需要這麼高解析度,因為太高解析度會影響我機器學習的效率,我就採用最粗暴的方法,使用PIL庫中的Image類,呼叫resize方法把圖片的寬高直接砍一半,但是這裡我還是採用了Image.ANTIALIAS濾鏡雖然這樣會使我圖片壓縮的效率降低一大截,但也盡最大可能的保留了圖片的資訊。
但我後來又遇到一種更好的壓縮圖片的方法,使用tinify API進行壓縮,通過它壓縮的圖片資訊基本上沒有損失,是個壓縮圖片利它的官方網站:https://tinypng.com/
在它官網上也可以直接進行壓縮,不過只能小批量的操作,一次最多20張,下面是使用它進行圖片壓縮的指令碼,你需要自己申請Key填寫到程式中
import os import os.path import click import tinify tinify.key = "你申請的Key,放在這裡." targetFileDirName = "/compress" #輸出目錄 targetIsDir = False totalPicCount = 1 #壓縮圖片總數 compressSuccessPicCount = 0 #圖片壓縮成功的數量 #這裡就是通過tingPng壓縮圖片的核心程式碼 def compress_core(file, outputFile): source = tinify.from_file(file) #壓縮指定檔案 source.to_file(outputFile) #將壓縮後的檔案輸出當指定位置 def compress_file(file): if not os.path.isfile(file): print("你指定的不是檔案,不給你壓縮這個檔案!") return srcFiledirName = os.path.dirname(file) basename = os.path.basename(file) #獲得檔案全稱 例如 migo.png filename, fileSuffix = os.path.splitext(basename) #獲得檔名稱和字尾名 例如 migo 和 png if picIsCorrect(fileSuffix): targetFileDir = srcFiledirName + targetFileDirName if not os.path.isdir(targetFileDir): os.mkdir(targetFileDir) print("正在壓縮的圖片: %s"%(srcFiledirName + "/" +basename)) compress_core(file, targetFileDir + "/" + basename) global compressSuccessPicCount compressSuccessPicCount += 1 global targetIsDir if targetIsDir is not True: print("------------壓縮的圖片在: %s 目錄下"%(targetFileDir)) else: print("暫不支援壓縮 {} 格式的檔案, 檔名: {}".format(fileSuffix, basename)) def picIsCorrect(fileSuffix): if fileSuffix == ".png" or fileSuffix == ".jpg" or fileSuffix == ".jpeg": return True else: return False def compress_dir(dir): if not os.path.isdir(dir): print("你輸入的不是一個目錄") return else: global targetIsDir targetIsDir = True srcFilePath = dir #源路徑 for root, dirs, files in os.walk(srcFilePath): global totalPicCount totalPicCount = len(files) for name in files: compress_file(srcFilePath + "/" + name) break #僅遍歷當前目錄 print("------------所有壓縮的圖片都在: %s 目錄下" %(srcFilePath + targetFileDirName)) @click.command() @click.option('-f', "--file", type=str, default=None, help="單個檔案壓縮") @click.option('-d', "--dir", type=str, default=None, help="被壓縮的資料夾") def run(file, dir): if not file is None: compress_file(file) #壓縮指定的檔案 pass elif not dir is None: compress_dir(dir) #壓縮指定的目錄 pass else: compress_dir(os.getcwd()) #壓縮當前資料夾 print("當前目錄: %s"%(os.getcwd())) print("------壓縮結束!------圖片總數 ({}), 壓縮的圖片數量 ({})".format(totalPicCount, compressSuccessPicCount)) if __name__ == "__main__": run()