? ? 圖像縮放是圖像處理中的基礎操作之一。無論是圖像預處理、數據增強還是圖像金字塔構建,cv::resize
都是我們最常用的函數之一。但你是否注意到,在 OpenCV 中同時還存在一個名為 cv::Mat::resize
的方法?這兩個函數雖然名字類似,但用途完全不同。
? ? 本篇博客將系統介紹 cv::resize
的功能與使用方法,并重點提示開發者不要將其與 cv::Mat::resize
混淆。
cv::resize
:圖像尺寸縮放
void cv::resize(InputArray src,OutputArray dst,Size dsize,double fx = 0,double fy = 0,int interpolation = INTER_LINEAR
);
- src: 輸入圖像
- dst: 輸出圖像
- dsize,fx,fy: 輸出圖像尺寸,可以使用dsize明確指出輸出圖像尺寸(如cv::Size(100,100)),或者使用fx,fy分別控制水平與垂直方向上縮放系數,如fx=0.5表示水平方向上縮小到原尺寸的0.5
- interpolation: 插值方式,包括:
INTER_NEAREST
最近鄰,INTER_LINEAR
雙線性(默認),INTER_CUBIC
雙三次,INTER_AREA
像素區域重采樣(適合縮小)
cv::Mat img = cv::imread("lena.jpg");
cv::Mat small, large, dst;// 縮小為原來一半
cv::resize(img, small, cv::Size(), 0.5, 0.5, cv::INTER_AREA);// 放大到原圖2倍
cv::resize(img, large, cv::Size(), 2.0, 2.0, cv::INTER_CUBIC);// 變換到指定尺寸
// 注意:目標尺寸的指定方法只能二選一,如選擇指定尺寸則縮放系數為0,反之指定尺寸為0
cv::resize(img, dst, cv::Size(100, 100), 0, 0, cv::INTER_CUBIC);
不同插值方式的比較?
插值方法 | 縮小時效果 | 放大時效果 | 說明 |
---|---|---|---|
INTER_NEAREST | 鋸齒明顯 | 像素塊狀 | 最快但最差 |
INTER_LINEAR | 較平滑 | 較清晰 | 適合放大,縮小時推薦平滑圖像后調用 |
INTER_CUBIC | 非常平滑 | 較銳利 | 適合放大,縮小時推薦平滑圖像后調用 |
INTER_AREA | 保細節 | 效果一般 | 專門為縮小圖像設計,等價于平滑圖像+INTER_LINEAR |
常見誤區:不要把 cv::resize
和 cv::Mat::resize
混淆?
? ? OpenCV 中還有另一個方法 cv::Mat::resize(size_t)
,這個函數并不是用于圖像縮放,而是改變矩陣中的元素數量。舉例說明:
// 創建一個1行10列的矩陣(或向量)
cv::Mat vec = (cv::Mat_<int>(1, 10) << 1,2,3,4,5,6,7,8,9,10);// 僅保留前5個元素
// 這里通過改變Mat對象頭文件實現數據尺寸改變,
// 如果改變后尺寸大于原來尺寸可能進行內存分布,否則不會進行內存分配!
vec.resize(5); // 注意:這不是圖像縮小!
? ? 一句話總結:圖像縮放用 cv::resize
,向量裁剪才 Mat::resize。
?
實用技巧
-
圖像縮小建議使用
INTER_AREA
當你對圖像進行縮小時,INTER_AREA
的區域重采樣方法可以保留更多細節,避免馬賽克感。
cv::resize(img, small, cv::Size(), 0.25, 0.25, cv::INTER_AREA);
- 你也可以使用固定目標尺寸進行縮放,不依賴縮放因子。
cv::resize(img, resized, cv::Size(256, 256)); // 直接縮放到 256×256
- 在一些應用中存在批量圖像縮放到統一尺寸的需求,常見用法如下:
std::vector<cv::Mat> images = ...;
for (auto& img : images) {cv::resize(img, img, cv::Size(224, 224));
}
深入理解圖像縮放?
? ? 在深入理解圖像插值:從原理到應用中,我們對與resize相關的圖像插值進行了詳細的講解,您可以參考該博文以深入理解圖像縮放相關內容。