OpenCV函数:resize() 实现 (最近邻,双线性)

来源:互联网 发布:嘉兴菜鸟网络招聘岗位 编辑:程序博客网 时间:2024/06/06 03:09

前言

在 OpenCV 中,resize()用来改变图像的大小,包含了 5 种插值方式。在这里,我用代码实现了其中两种最具代表性的插值方式:最近邻与双线性插值。

最近邻

最近邻插值方式如下:

xd=xsfxyd=ysfyfx=wd/wsfy=hd/hs

其中,xd,yd为目标图像坐标,xs,ys为源图像坐标。
实现最近邻的 resize() 代码:

Mat ReSizeForNearest(Mat src, Size dsize,double fx = 0, double fy = 0){    if (src.empty())        throw exception("Image is empty!");    int c = src.channels();    if (dsize.width!=0 && dsize.height!=0)    {        fx = (double)dsize.width / (double)src.cols;        fy = (double)dsize.height / (double)src.rows;    }    else if (fx != 0 && fy != 0)    {        dsize.width = int(src.cols*fx);        dsize.height = int(src.rows*fy);    }    else    {        throw exception("Invalid parameter!");    }    Mat dst(dsize, src.type(), Scalar::all(0));    for (int i = 0; i < dst.rows; i++)    {        uchar* dstData = dst.ptr<uchar>(i);        int srcy = cvFloor(i / fy);        srcy = min(srcy, src.rows - 1);        uchar* srcData = src.ptr<uchar>(srcy);        for (int j = 0; j < dst.cols*c; j+=c)        {            int srcx = cvFloor((j/c) / fx);            srcx = min(srcx, src.cols - 1);            for (int k = 0; k < c; k++)            {                dstData[j + k] = srcData[srcx*c + k];            }        }    }    return dst;}

实验结果:
原始图片:

这里写图片描述

调用 ReSizeForNearest(image, Size(600, 1000));的结果:

这里写图片描述

可以发现放大后的图片非常粗糙。

双线性插值

先给出双线性插值的公式:

Dst(xd,yd)=(1u)(1v)Src(xs,ys)+(1u)vSrc(xs,ys+1)+u(v1)Src(xs+1,ys)+uvSrc(xs+1,ys+1)

其矩阵表示为:
Dst(xd,yd)=[1uu][Src(xs,ys)Src(xs+1,ys)Src(xs,ys+1)Src(xs+1,ys+1)][1vv]

其中,xd,yd 的计算方式与最近邻相同,向下取整,u,v 为计算得到坐标值的小数部分。

实现双线性插值的 resize() 代码:

Mat ReSizeForLinear(Mat src, Size dsize, double fx = 0, double fy = 0){    if (src.empty())        throw exception("Image is empty!");    int c = src.channels();    if (dsize.width != 0 && dsize.height != 0)    {        fx = (double)dsize.width / (double)src.cols;        fy = (double)dsize.height / (double)src.rows;    }    else if (fx != 0 && fy != 0)    {        dsize.width = int(src.cols*fx);        dsize.height = int(src.rows*fy);    }    else    {        throw exception("Invalid parameter!");    }    Mat dst(dsize, src.type(), Scalar::all(0));    for (int i = 0; i < dst.rows; i++)    {        uchar* dstData = dst.ptr<uchar>(i);        double srcy = i / fy;        int y = cvFloor(srcy);        double v = srcy - y;        if (v < 0)        {            y = 0;            v = 0;        }        if (y >= src.rows - 1)        {            y = src.rows - 2;            v = 1;        }        uchar* srcData1 = src.ptr<uchar>(y);        uchar* srcData2 = src.ptr<uchar>(y+1);        for (int j = 0; j < dst.cols*c; j += c)        {            double srcx = (j/c) / fx;            int x = cvFloor(srcx);            double u = srcx - x;            if (x < 0)            {                x = 0;                u = 0;            }            if (x >= src.cols - 1)            {                x = src.cols - 2;                u = 1;            }            for (int k = 0; k < c; k++)            {                dstData[j + k] = (1 - u)*(1 - v)*srcData1[x*c + k] +                    (1 - u)*v*srcData2[x*c + k] +                    u*(1 - v)*srcData1[(x + 1)*c + k] +                    u*v*srcData2[(x + 1)*c + k];            }        }    }    return dst;}

实验结果:
原图与上面一致,ReSizeForLinear(image, Size(600, 1000));的结果为:
这里写图片描述

其结果比上面的图片效果好了很多。

阅读全文
0 0
原创粉丝点击