OpenCV函式:resize() 實現 (最近鄰,雙線性)
阿新 • • 發佈:2019-02-09
前言
在 OpenCV 中,resize()
用來改變影象的大小,包含了 5 種插值方式。在這裡,我用程式碼實現了其中兩種最具代表性的插值方式:最近鄰與雙線性插值。
最近鄰
最近鄰插值方式如下:
其中,
實現最近鄰的 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));
的結果:
可以發現放大後的圖片非常粗糙。
雙線性插值
先給出雙線性插值的公式:
其矩陣表示為:
其中,
實現雙線性插值的 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));
的結果為:
其結果比上面的圖片效果好了很多。