Opencv实现纵横比保持的图像缩放
之前實(shí)現(xiàn)過(guò)C實(shí)現(xiàn)縱橫比保持的RGB圖像縮放,其實(shí)計(jì)算效率是不高的。
opencv的好多實(shí)現(xiàn)都是自帶mmx, sse加速的。所以就來(lái)研究一下如何用opencv來(lái)實(shí)現(xiàn)縱橫比保持的圖像縮放。
查看了一下opencv resize函數(shù)的詳細(xì)定義:
resize函數(shù)
函數(shù)原型:
void cv::resize( InputArray _src, OutputArray _dst, Size dsize, double inv_scale_x = 0, double inv_scale_y = 0, int interpolation = INTER_LINEAR )參數(shù)說(shuō)明:
-
src,輸入圖像,Mat類型即可;
-
dst,輸出圖像,當(dāng)其非零時(shí),有著dsize(第三個(gè)參數(shù))的尺寸或者有src.size()計(jì)算出來(lái);
-
dsize,輸出圖像的大小。如果它等于0,由下式計(jì)算:
dsize = Size( round(fx*src.cols, round(fy*src.rows))); 其中fx,fy,dsize都能不為0 -
fx,沿水平軸的縮放系數(shù),默認(rèn)值為0,且等于0時(shí),由下式計(jì)算:
inv_scale_x = (double)dsize.width/ssize.width; -
fy,沿垂直軸的縮放系數(shù),默認(rèn)值為0,且等于0時(shí),由下式計(jì)算:
inv_scale_y = (double)dsize.height/ssize.height; -
interpolation,用于指定插值方式,默認(rèn)值為INTER_LINEAR(線性插值),可選插值方式如下:
| INTER_NEAREST | 最近鄰插值 |
| INTER_LINEAR | 線性插值(默認(rèn)值) |
| INTER_AREA | 區(qū)域插值(利用像素區(qū)域關(guān)系的重采樣插值) |
| INTER_CUBIC | 三次樣條插值(超過(guò)4×4像素領(lǐng)域內(nèi)的雙三次插值) |
| INTER_LANCZOS4 | Lanczos插值(超過(guò)8×8像素鄰域的Lanczos插值) |
注意:要縮小圖像,一般情況下用INTER_AREA來(lái)插值;而若要放大圖像,一般情況下用INTER_CUBIC(效率不高,不推薦)或INTER_LINEAR(效率高,推薦)
但是該函數(shù)實(shí)現(xiàn)不了任意尺寸的縱橫比保持的圖像縮放。
仔細(xì)想了一下,可以先做crop操作,然后再縮放,分兩步,這樣就可以達(dá)到縱橫比保持的圖像縮放。
代碼如下:
#include "opencv2/opencv.hpp" #include "opencv2/opencv.hpp" #include<fstream> #include <chrono>using namespace std; using namespace cv;int main(int, char**) {cv::Size szSize(3840 , 2160);uchar *b_Buffer = new uchar[szSize.width * szSize.height * 2];uchar *rgb_Buffer = new uchar[szSize.width * szSize.height * 3];string binFile("input.yuv");ifstream File_VideoFile;File_VideoFile.open(binFile, ios::in | ios::binary);if (!File_VideoFile.is_open()){std::cerr << "[ERROR] cannot open the YUV Input File " << binFile << endl;std::cerr << std::endl;assert(0);}File_VideoFile.read((char*)b_Buffer, sizeof(uchar)*szSize.width*szSize.height*2);File_VideoFile.close();cv::Mat mSrc(szSize,CV_8UC2, b_Buffer);cv::Mat mSrc_BGR(szSize, CV_8UC3);auto time1 = std::chrono::steady_clock::now();cvtColor(mSrc, mSrc_BGR, COLOR_YUV2BGR_YUYV);auto time2 = std::chrono::steady_clock::now();auto duration = std::chrono::duration_cast<std::chrono::microseconds>(time2-time1).count();printf("cv time: %.2f ms.\n", (float)duration / 1000);Size dstSize(1600, 1600);Size srcSize(3840, 2160);Mat dst_img(dstSize, CV_8UC3);//crop firstdouble fx = dstSize.width / srcSize.width;double fy = dstSize.height / srcSize.height;int xmin = 0, xmax = 0;int ymin = 0, ymax = 0;if (fx > fy) {//crop yxmin = 0;xmax = srcSize.width;ymin = (srcSize.height - srcSize.width) >> 1;ymax = srcSize.height - ymin;} else {//crop xymin = 0;ymax = srcSize.height;xmin = (srcSize.width - srcSize.height) >> 1;xmax = srcSize.width - xmin;}Mat crop_img = mSrc_BGR(Range(ymin, ymax), Range(xmin, xmax));//scale secondresize(crop_img, dst_img, dstSize);imwrite( "dst.bmp", dst_img);imwrite( "rgb24.bmp", mSrc_BGR);delete[] b_Buffer;delete[] rgb_Buffer;return 0; }總結(jié)
以上是生活随笔為你收集整理的Opencv实现纵横比保持的图像缩放的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: marquee 和JS 滚动效果
- 下一篇: 什么是用户故事及用户故事在敏捷开发中如何