使用 opencv 將圖片壓縮到指定文件尺寸

前言

圖片壓縮應用很普遍,如生成縮略圖等。前期我在進行圖片處理的過程當中碰到了一個問題,就是如何將圖片壓縮到指定尺寸,此處尺寸指的是生成圖片文件的大小。python

我使用 opencv 進行圖片處理,因而想着直接使用 opencv 進行圖片壓縮處理, opencv 自己包含了壓縮到指定像素大小的方法,奈何尋找了不少方法均不能壓縮到指定文件尺寸,因而本身在思考後寫出了此方法。本文使用python語言。算法

1、 opencv 常規使用

opencv 無需多言,作過圖片處理的人應該都知道此類庫,下面我介紹一些經常使用方法。shell

1.1 安裝 opencv

首先安裝 python ,建議 python3 ,而後執行
數組

pip install opencv-python

1.2 讀取圖片

首先引入 opencv 包:函數

import cv2 as cv

然後讀取圖片:測試

image = cv.imread(path)

其中 path 爲圖片路徑, image 爲圖片數據,是一個 numpy.ndarray 對象,其實就是一個多維數組。目前 opencv 支持幾乎全部格式的圖片(參考 http://blog.csdn.net/mars_xiaolei/article/details/78890971)。優化

1.3 保存圖片

代碼:.net

cv.imwrite(path, image)

其中 path 爲保存的文件路徑, image 爲讀取或者處理過的圖片數據, opencv 根據保存文件的後綴名來寫不一樣格式的圖片數據,因此後綴名必定要寫正確。code

2、圖片壓縮

2.1 常規壓縮

opencv 支持常規壓縮,能夠將圖片壓縮到指定的像素尺寸或者按比例縮放。對象

  • 壓縮到指定的像素尺寸:
new_image = cv.resize(image, size)

其中 size 是一個二維元組,表示壓縮後圖片的寬高。

  • 按比例縮放:
new_image = cv.resize(image, None, fx, fy)

其中 fx , fy 表示圖片在寬和高方向的壓縮了比例。

2.2 壓縮到指定文檔大小

有了上面的基礎咱們來分析一下如何實現壓縮到指定文檔大小。

首先咱們要讀取原始文檔的大小,算出原始文檔大小和壓縮目標值的比例,因爲咱們要實現的是寬高等比例壓縮,因而將其開根號即表示在單邊的壓縮比例,調用 2.1 節中的按比例壓縮。理論上一次就能達到效果,可是因爲圖片自己存在壓縮,因此可能一次沒法達到預期,只要對壓縮後的圖片重複此步驟,直到達到預期便可。

2.2.1 讀取文檔尺寸

def get_doc_size(path):
    try:
        size = os.path.getsize(path)
        return get_mb_size(size)
    except Exception as err:
        print(err)

def get_mb_size(bytes):
    bytes = float(bytes)
    mb = bytes / 1024 / 1024
    return mb

get_doc_size 函數返回圖片的文檔大小,單位爲 MB 。

2.2.2 刪除文件

def delete_file(path):
    if file_exist(path):
        os.remove(path)
    else:
        print('no such file:%s' % path)
        
def file_exist(path):
    return os.path.exists(path)

因爲咱們須要刪除壓縮過程當中產生的中間文件,因此須要調用 delete_file 方法刪除之。

2.2.3 壓縮

size = get_doc_size(path)
delete_file(resize_path)

while size > filesize:
    rate = math.ceil((size / filesize) * 10) / 10 + 0.1
    rate = math.sqrt(rate)

    rate = 1.0 / rate
    if file_exist(resize_path):
        resize_rate(resize_path, resize_path, rate, rate)
    else:
        resize_rate(path, resize_path, rate, rate)
    size = get_doc_size(resize_path)

其中 filesize 表示壓縮目標值, path 表示原始文件路徑, resize_path 表示壓縮後存放路徑, resize_rate 表示上述按比例壓縮方法,定義以下:

def resize_rate(path, resize_path, fx, fy):
    image = read_image(path)
    im_resize = cv.resize(image, None, fx=fx, fy=fy)
    delete_file(resize_path)
    save_image(resize_path, im_resize)
    
def save_image(path, image):
    cv.imwrite(path, image)


def read_image(path):
    return cv.imread(path)

固然此處爲了效果更好,我作了一些優化。

首先在獲取壓縮比例的時候我作了下述操做:

rate = math.ceil((size / filesize) * 10) / 10 + 0.1

理論狀況應當是直接返回 size / filesize 便可,可是在實際測試過程當中爲了加速收斂,我採用上述方式,將一個小數先乘以 10 對其向上取整,這樣就表示精度保留到原始數值小數後 1 位,即若是是 3.14 將獲得 32 ,然後將此結果再除以 10 , 即獲得 3.2 ,因此最終結果就是對小數後第二位進行向上進位,最後結果又加了 0.1 以更快速的收斂,固然你也能夠去掉。

實際測試發現,通常重複執行兩次便可獲得理想的壓縮效果,而且結果值與理想壓縮尺寸相差無幾。

3、結論

本文簡單介紹瞭如何使用 opencv 將圖片壓縮到指定文件尺寸,固然你也能夠選擇其餘文件處理類庫而不是 opencv ,這個徹底能夠根據用戶本身的興趣而來,而且也能夠優化最終的循環算法,以達到更佳的效果,或者更快的收斂。

相關文章
相關標籤/搜索