Opencv实现纵横比保持的图像缩放

之前实现过C实现纵横比保持的RGB图像缩放,其实计算效率是不高的。

opencv的好多实现都是自带mmx, sse加速的。所以就来研究一下如何用opencv来实现纵横比保持的图像缩放。

查看了一下opencv resize函数的详细定义:

resize函数

函数原型:

void cv::resize( 
InputArray _src, 
OutputArray _dst, 
Size dsize,
double inv_scale_x = 0,
double inv_scale_y = 0, 
int interpolation = INTER_LINEAR 
)

参数说明:

  • src,输入图像,Mat类型即可;

  • dst,输出图像,当其非零时,有着dsize(第三个参数)的尺寸或者有src.size()计算出来;

  • dsize,输出图像的大小。如果它等于0,由下式计算:

     dsize = Size( round(fx*src.cols, round(fy*src.rows)));
    其中fx,fy,dsize都能不为0
    
  • fx,沿水平轴的缩放系数,默认值为0,且等于0时,由下式计算:

     inv_scale_x = (double)dsize.width/ssize.width;
    
  • fy,沿垂直轴的缩放系数,默认值为0,且等于0时,由下式计算:

     inv_scale_y = (double)dsize.height/ssize.height;
    
  • interpolation,用于指定插值方式,默认值为INTER_LINEAR(线性插值),可选插值方式如下:

取值说明
INTER_NEAREST最近邻插值
INTER_LINEAR线性插值(默认值)
INTER_AREA区域插值(利用像素区域关系的重采样插值)
INTER_CUBIC三次样条插值(超过4×4像素领域内的双三次插值)
INTER_LANCZOS4Lanczos插值(超过8×8像素邻域的Lanczos插值)

注意:要缩小图像,一般情况下用INTER_AREA来插值;而若要放大图像,一般情况下用INTER_CUBIC(效率不高,不推荐)或INTER_LINEAR(效率高,推荐)

但是该函数实现不了任意尺寸的纵横比保持的图像缩放。

仔细想了一下,可以先做crop操作,然后再缩放,分两步,这样就可以达到纵横比保持的图像缩放。

代码如下:

#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 first
    double 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 y
        xmin = 0;
        xmax = srcSize.width;
        ymin = (srcSize.height - srcSize.width) >> 1;
        ymax = srcSize.height - ymin;
    } else {
        //crop x
        ymin = 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 second
    resize(crop_img, dst_img, dstSize);

	


    imwrite( "dst.bmp", dst_img);

    imwrite( "rgb24.bmp", mSrc_BGR);

    delete[] b_Buffer;
    delete[] rgb_Buffer;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值