脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - OpenCV中resize函数插值算法的实现过程(五种)

OpenCV中resize函数插值算法的实现过程(五种)

2021-11-23 11:37fengbingchun Python

最新版OpenCV2.4.7中,cv::resize函数有五种插值算法:最近邻、双线性、双三次、基于像素区域关系、兰索斯插值。感兴趣的可以了解一下

最新版OpenCV2.4.7中,cv::resize函数有五种插值算法:最近邻、双线性、双三次、基于像素区域关系、兰索斯插值。下面用for循环代替cv::resize函数来说明其详细的插值实现过程,其中部分代码摘自于cv::resize函数中的源代码。

每种插值算法的前部分代码是相同的,如下:

?
1
2
3
4
5
6
7
8
cv::Mat matSrc, matDst1, matDst2;
 
matSrc = cv::imread("lena.jpg", 2 | 4);
matDst1 = cv::Mat(cv::Size(800, 1000), matSrc.type(), cv::Scalar::all(0));
matDst2 = cv::Mat(matDst1.size(), matSrc.type(), cv::Scalar::all(0));
 
double scale_x = (double)matSrc.cols / matDst1.cols;
double scale_y = (double)matSrc.rows / matDst1.rows;

1、最近邻:公式,

OpenCV中resize函数插值算法的实现过程(五种)OpenCV中resize函数插值算法的实现过程(五种)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for (int i = 0; i < matDst1.cols; ++i)
{
    int sx = cvFloor(i * scale_x);
    sx = std::min(sx, matSrc.cols - 1);
    for (int j = 0; j < matDst1.rows; ++j)
    {
        int sy = cvFloor(j * scale_y);
        sy = std::min(sy, matSrc.rows - 1);
        matDst1.at<cv::Vec3b>(j, i) = matSrc.at<cv::Vec3b>(sy, sx);
    }
}
cv::imwrite("nearest_1.jpg", matDst1);
 
cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 0);
cv::imwrite("nearest_2.jpg", matDst2);

2、双线性:由相邻的四像素(2*2)计算得出,公式,

OpenCV中resize函数插值算法的实现过程(五种)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
uchar* dataDst = matDst1.data;
int stepDst = matDst1.step;
uchar* dataSrc = matSrc.data;
int stepSrc = matSrc.step;
int iWidthSrc = matSrc.cols;
int iHiehgtSrc = matSrc.rows;
 
for (int j = 0; j < matDst1.rows; ++j)
{
    float fy = (float)((j + 0.5) * scale_y - 0.5);
    int sy = cvFloor(fy);
    fy -= sy;
    sy = std::min(sy, iHiehgtSrc - 2);
    sy = std::max(0, sy);
 
    short cbufy[2];
    cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
    cbufy[1] = 2048 - cbufy[0];
 
    for (int i = 0; i < matDst1.cols; ++i)
    {
        float fx = (float)((i + 0.5) * scale_x - 0.5);
        int sx = cvFloor(fx);
        fx -= sx;
 
        if (sx < 0) {
            fx = 0, sx = 0;
        }
        if (sx >= iWidthSrc - 1) {
            fx = 0, sx = iWidthSrc - 2;
        }
 
        short cbufx[2];
        cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
        cbufx[1] = 2048 - cbufx[0];
 
        for (int k = 0; k < matSrc.channels(); ++k)
        {
            *(dataDst+ j*stepDst + 3*i + k) = (*(dataSrc + sy*stepSrc + 3*sx + k) * cbufx[0] * cbufy[0] +
                *(dataSrc + (sy+1)*stepSrc + 3*sx + k) * cbufx[0] * cbufy[1] +
                *(dataSrc + sy*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[0] +
                *(dataSrc + (sy+1)*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[1]) >> 22;
        }
    }
}
cv::imwrite("linear_1.jpg", matDst1);
 
cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 1);
cv::imwrite("linear_2.jpg", matDst2);

3、双三次:由相邻的4*4像素计算得出,公式类似于双线性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
int iscale_x = cv::saturate_cast<int>(scale_x);
int iscale_y = cv::saturate_cast<int>(scale_y);
 
for (int j = 0; j < matDst1.rows; ++j)
{
    float fy = (float)((j + 0.5) * scale_y - 0.5);
    int sy = cvFloor(fy);
    fy -= sy;
    sy = std::min(sy, matSrc.rows - 3);
    sy = std::max(1, sy);
 
    const float A = -0.75f;
 
    float coeffsY[4];
    coeffsY[0] = ((A*(fy + 1) - 5*A)*(fy + 1) + 8*A)*(fy + 1) - 4*A;
    coeffsY[1] = ((A + 2)*fy - (A + 3))*fy*fy + 1;
    coeffsY[2] = ((A + 2)*(1 - fy) - (A + 3))*(1 - fy)*(1 - fy) + 1;
    coeffsY[3] = 1.f - coeffsY[0] - coeffsY[1] - coeffsY[2];
 
    short cbufY[4];
    cbufY[0] = cv::saturate_cast<short>(coeffsY[0] * 2048);
    cbufY[1] = cv::saturate_cast<short>(coeffsY[1] * 2048);
    cbufY[2] = cv::saturate_cast<short>(coeffsY[2] * 2048);
    cbufY[3] = cv::saturate_cast<short>(coeffsY[3] * 2048);
 
    for (int i = 0; i < matDst1.cols; ++i)
    {
        float fx = (float)((i + 0.5) * scale_x - 0.5);
        int sx = cvFloor(fx);
        fx -= sx;
 
        if (sx < 1) {
            fx = 0, sx = 1;
        }
        if (sx >= matSrc.cols - 3) {
            fx = 0, sx = matSrc.cols - 3;
        }
 
        float coeffsX[4];
        coeffsX[0] = ((A*(fx + 1) - 5*A)*(fx + 1) + 8*A)*(fx + 1) - 4*A;
        coeffsX[1] = ((A + 2)*fx - (A + 3))*fx*fx + 1;
        coeffsX[2] = ((A + 2)*(1 - fx) - (A + 3))*(1 - fx)*(1 - fx) + 1;
        coeffsX[3] = 1.f - coeffsX[0] - coeffsX[1] - coeffsX[2];
 
        short cbufX[4];
        cbufX[0] = cv::saturate_cast<short>(coeffsX[0] * 2048);
        cbufX[1] = cv::saturate_cast<short>(coeffsX[1] * 2048);
        cbufX[2] = cv::saturate_cast<short>(coeffsX[2] * 2048);
        cbufX[3] = cv::saturate_cast<short>(coeffsX[3] * 2048);
 
        for (int k = 0; k < matSrc.channels(); ++k)
        {
            matDst1.at<cv::Vec3b>(j, i)[k] = abs((matSrc.at<cv::Vec3b>(sy-1, sx-1)[k] * cbufX[0] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx-1)[k] * cbufX[0] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy+1, sx-1)[k] * cbufX[0] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx-1)[k] * cbufX[0] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy-1, sx)[k] * cbufX[1] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufX[1] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy+1, sx)[k] * cbufX[1] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx)[k] * cbufX[1] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy-1, sx+1)[k] * cbufX[2] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx+1)[k] * cbufX[2] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy+1, sx+1)[k] * cbufX[2] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx+1)[k] * cbufX[2] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy-1, sx+2)[k] * cbufX[3] * cbufY[0] + matSrc.at<cv::Vec3b>(sy, sx+2)[k] * cbufX[3] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy+1, sx+2)[k] * cbufX[3] * cbufY[2] + matSrc.at<cv::Vec3b>(sy+2, sx+2)[k] * cbufX[3] * cbufY[3] ) >> 22);
        }
    }
}
cv::imwrite("cubic_1.jpg", matDst1);
 
cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 2);
cv::imwrite("cubic_2.jpg", matDst2);

4、基于像素区域关系:共分三种情况,图像放大时类似于双线性插值,图像缩小(x轴、y轴同时缩小)又分两种情况,此情况下可以避免波纹出现。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#ifdef _MSC_VER
    cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 3);
    cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_2.jpg", matDst2);
#else
    cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 3);
    cv::imwrite("area_2.jpg", matDst2);
#endif
 
    fprintf(stdout, "==== start area ====\n");
    double inv_scale_x = 1. / scale_x;
    double inv_scale_y = 1. / scale_y;
    int iscale_x = cv::saturate_cast<int>(scale_x);
    int iscale_y = cv::saturate_cast<int>(scale_y);
    bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON && std::abs(scale_y - iscale_y) < DBL_EPSILON;
 
    if (scale_x >= 1 && scale_y >= 1)  { // zoom out
        if (is_area_fast)  { // integer multiples
            for (int j = 0; j < matDst1.rows; ++j) {
                int sy = std::min(cvFloor(j * scale_y), matSrc.rows - 1);
 
                for (int i = 0; i < matDst1.cols; ++i) {
                    int sx = std::min(cvFloor(i * scale_x), matSrc.cols -1);
 
                    matDst1.at<cv::Vec3b>(j, i) = matSrc.at<cv::Vec3b>(sy, sx);
                }
            }
#ifdef _MSC_VER
            cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_1.jpg", matDst1);
#else
            cv::imwrite("area_1.jpg", matDst1);
#endif
            return 0;
        }
 
        for (int j = 0; j < matDst1.rows; ++j) {
            double fsy1 = j * scale_y;
            double fsy2 = fsy1 + scale_y;
            double cellHeight = cv::min(scale_y, matSrc.rows - fsy1);
 
            int sy1 = cvCeil(fsy1), sy2 = cvFloor(fsy2);
 
            sy2 = std::min(sy2, matSrc.rows - 2);
            sy1 = std::min(sy1, sy2);
 
            float cbufy[2];
            cbufy[0] = (float)((sy1 - fsy1) / cellHeight);
            cbufy[1] = (float)(std::min(std::min(fsy2 - sy2, 1.), cellHeight) / cellHeight);
 
            for (int i = 0; i < matDst1.cols; ++i) {
                double fsx1 = i * scale_x;
                double fsx2 = fsx1 + scale_x;
                double cellWidth = std::min(scale_x, matSrc.cols - fsx1);
 
                int sx1 = cvCeil(fsx1), sx2 = cvFloor(fsx2);
 
                sx2 = std::min(sx2, matSrc.cols - 2);
                sx1 = std::min(sx1, sx2);
 
                float cbufx[2];
                cbufx[0] = (float)((sx1 - fsx1) / cellWidth);
                cbufx[1] = (float)(std::min(std::min(fsx2 - sx2, 1.), cellWidth) / cellWidth);
 
                for (int k = 0; k < matSrc.channels(); ++k) {
                    matDst1.at<cv::Vec3b>(j, i)[k] = (uchar)(matSrc.at<cv::Vec3b>(sy1, sx1)[k] * cbufx[0] * cbufy[0] +
                        matSrc.at<cv::Vec3b>(sy1 + 1, sx1)[k] * cbufx[0] * cbufy[1] +
                        matSrc.at<cv::Vec3b>(sy1, sx1 + 1)[k] * cbufx[1] * cbufy[0] +
                        matSrc.at<cv::Vec3b>(sy1 + 1, sx1 + 1)[k] * cbufx[1] * cbufy[1]);
                }
            }
        }
#ifdef _MSC_VER
        cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_1.jpg", matDst1);
#else
        cv::imwrite("area_1.jpg", matDst1);
#endif
 
        return 0;
    }
 
    //zoom in,it is emulated using some variant of bilinear interpolation
    for (int j = 0; j < matDst1.rows; ++j) {
        int  sy = cvFloor(j * scale_y);
        float fy = (float)((j + 1) - (sy + 1) * inv_scale_y);
        fy = fy <= 0 ? 0.f : fy - cvFloor(fy);
        sy = std::min(sy, matSrc.rows - 2);
 
        short cbufy[2];
        cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);
        cbufy[1] = 2048 - cbufy[0];
 
        for (int i = 0; i < matDst1.cols; ++i) {
            int sx = cvFloor(i * scale_x);
            float fx = (float)((i + 1) - (sx + 1) * inv_scale_x);
            fx = fx < 0 ? 0.f : fx - cvFloor(fx);
 
            if (sx < 0) {
                fx = 0, sx = 0;
            }
 
            if (sx >= matSrc.cols - 1) {
                fx = 0, sx = matSrc.cols - 2;
            }
 
            short cbufx[2];
            cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);
            cbufx[1] = 2048 - cbufx[0];
 
            for (int k = 0; k < matSrc.channels(); ++k) {
                matDst1.at<cv::Vec3b>(j, i)[k] = (matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufx[0] * cbufy[0] +
                    matSrc.at<cv::Vec3b>(sy + 1, sx)[k] * cbufx[0] * cbufy[1] +
                    matSrc.at<cv::Vec3b>(sy, sx + 1)[k] * cbufx[1] * cbufy[0] +
                    matSrc.at<cv::Vec3b>(sy + 1, sx + 1)[k] * cbufx[1] * cbufy[1]) >> 22;
            }
        }
    }
    fprintf(stdout, "==== end area ====\n");
 
#ifdef _MSC_VER
    cv::imwrite("E:/GitCode/OpenCV_Test/test_images/area_1.jpg", matDst1);
#else
    cv::imwrite("area_1.jpg", matDst1);
#endif

注:以上基于area进行图像缩小的代码有问题,具体实现代码可以参考https://github.com/fengbingchun/OpenCV_Test/blob/master/src/fbc_cv/include/resize.hpp,用法如下:

?
1
2
3
fbc::Mat3BGR src(matSrc.rows, matSrc.cols, matSrc.data);
fbc::Mat3BGR dst(matDst1.rows, matDst1.cols, matDst1.data);
fbc::resize(src, dst, 3);

5、兰索斯插值:由相邻的8*8像素计算得出,公式类似于双线性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
int iscale_x = cv::saturate_cast<int>(scale_x);
int iscale_y = cv::saturate_cast<int>(scale_y);
 
for (int j = 0; j < matDst1.rows; ++j)
{
    float fy = (float)((j + 0.5) * scale_y - 0.5);
    int sy = cvFloor(fy);
    fy -= sy;
    sy = std::min(sy, matSrc.rows - 5);
    sy = std::max(3, sy);
 
    const double s45 = 0.70710678118654752440084436210485;
    const double cs[][2] = {{1, 0}, {-s45, -s45}, {0, 1}, {s45, -s45}, {-1, 0}, {s45, s45}, {0, -1}, {-s45, s45}};
    float coeffsY[8];
 
    if (fy < FLT_EPSILON) {
        for (int t = 0; t < 8; t++)
            coeffsY[t] = 0;
        coeffsY[3] = 1;
    } else {
        float sum = 0;
        double y0 = -(fy + 3) * CV_PI * 0.25, s0 = sin(y0), c0 = cos(y0);
 
        for (int t = 0; t < 8; ++t)
        {
            double dy = -(fy + 3 -t) * CV_PI * 0.25;
            coeffsY[t] = (float)((cs[t][0] * s0 + cs[t][1] * c0) / (dy * dy));
            sum += coeffsY[t];
        }
 
        sum = 1.f / sum;
        for (int t = 0; t < 8; ++t)
            coeffsY[t] *= sum;
    }
 
    short cbufY[8];
    cbufY[0] = cv::saturate_cast<short>(coeffsY[0] * 2048);
    cbufY[1] = cv::saturate_cast<short>(coeffsY[1] * 2048);
    cbufY[2] = cv::saturate_cast<short>(coeffsY[2] * 2048);
    cbufY[3] = cv::saturate_cast<short>(coeffsY[3] * 2048);
    cbufY[4] = cv::saturate_cast<short>(coeffsY[4] * 2048);
    cbufY[5] = cv::saturate_cast<short>(coeffsY[5] * 2048);
    cbufY[6] = cv::saturate_cast<short>(coeffsY[6] * 2048);
    cbufY[7] = cv::saturate_cast<short>(coeffsY[7] * 2048);
 
    for (int i = 0; i < matDst1.cols; ++i)
    {
        float fx = (float)((i + 0.5) * scale_x - 0.5);
        int sx = cvFloor(fx);
        fx -= sx;
 
        if (sx < 3) {
            fx = 0, sx = 3;
        }
        if (sx >= matSrc.cols - 5) {
            fx = 0, sx = matSrc.cols - 5;
        }
 
        float coeffsX[8];
 
        if (fx < FLT_EPSILON) {
            for ( int t = 0; t < 8; t++ )
                coeffsX[t] = 0;
            coeffsX[3] = 1;
        } else {
            float sum = 0;
            double x0 = -(fx + 3) * CV_PI * 0.25, s0 = sin(x0), c0 = cos(x0);
 
            for (int t = 0; t < 8; ++t)
            {
                double dx = -(fx + 3 -t) * CV_PI * 0.25;
                coeffsX[t] = (float)((cs[t][0] * s0 + cs[t][1] * c0) / (dx * dx));
                sum += coeffsX[t];
            }
 
            sum = 1.f / sum;
            for (int t = 0; t < 8; ++t)
                coeffsX[t] *= sum;
        }
 
        short cbufX[8];
        cbufX[0] = cv::saturate_cast<short>(coeffsX[0] * 2048);
        cbufX[1] = cv::saturate_cast<short>(coeffsX[1] * 2048);
        cbufX[2] = cv::saturate_cast<short>(coeffsX[2] * 2048);
        cbufX[3] = cv::saturate_cast<short>(coeffsX[3] * 2048);
        cbufX[4] = cv::saturate_cast<short>(coeffsX[4] * 2048);
        cbufX[5] = cv::saturate_cast<short>(coeffsX[5] * 2048);
        cbufX[6] = cv::saturate_cast<short>(coeffsX[6] * 2048);
        cbufX[7] = cv::saturate_cast<short>(coeffsX[7] * 2048);
 
        for (int k = 0; k < matSrc.channels(); ++k)
        {
            matDst1.at<cv::Vec3b>(j, i)[k] = abs((matSrc.at<cv::Vec3b>(sy-3, sx-3)[k] * cbufX[0] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx-3)[k] * cbufX[0] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx-3)[k] * cbufX[0] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx-3)[k] * cbufX[0] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx-3)[k] * cbufX[0] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx-3)[k] * cbufX[0] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx-3)[k] * cbufX[0] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx-3)[k] * cbufX[0] * cbufY[7] +
 
                matSrc.at<cv::Vec3b>(sy-3, sx-2)[k] * cbufX[1] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx-2)[k] * cbufX[1] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx-2)[k] * cbufX[1] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx-2)[k] * cbufX[1] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx-2)[k] * cbufX[1] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx-2)[k] * cbufX[1] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx-2)[k] * cbufX[1] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx-2)[k] * cbufX[1] * cbufY[7] +
 
                matSrc.at<cv::Vec3b>(sy-3, sx-1)[k] * cbufX[2] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx-1)[k] * cbufX[2] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx-1)[k] * cbufX[2] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx-1)[k] * cbufX[2] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx-1)[k] * cbufX[2] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx-1)[k] * cbufX[2] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx-1)[k] * cbufX[2] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx-1)[k] * cbufX[2] * cbufY[7] +
 
                matSrc.at<cv::Vec3b>(sy-3, sx)[k] * cbufX[3] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx)[k] * cbufX[3] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx)[k] * cbufX[3] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx)[k] * cbufX[3] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx)[k] * cbufX[3] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx)[k] * cbufX[3] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx)[k] * cbufX[3] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx)[k] * cbufX[3] * cbufY[7] +
 
                matSrc.at<cv::Vec3b>(sy-3, sx+1)[k] * cbufX[4] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+1)[k] * cbufX[4] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx+1)[k] * cbufX[4] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+1)[k] * cbufX[4] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx+1)[k] * cbufX[4] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+1)[k] * cbufX[4] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx+1)[k] * cbufX[4] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+1)[k] * cbufX[4] * cbufY[7] +
 
                matSrc.at<cv::Vec3b>(sy-3, sx+2)[k] * cbufX[5] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+2)[k] * cbufX[5] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx+2)[k] * cbufX[5] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+2)[k] * cbufX[5] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx+2)[k] * cbufX[5] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+2)[k] * cbufX[5] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx+2)[k] * cbufX[5] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+2)[k] * cbufX[5] * cbufY[7] +
 
                matSrc.at<cv::Vec3b>(sy-3, sx+3)[k] * cbufX[6] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+3)[k] * cbufX[6] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx+3)[k] * cbufX[6] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+3)[k] * cbufX[6] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx+3)[k] * cbufX[6] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+3)[k] * cbufX[6] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx+3)[k] * cbufX[6] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+3)[k] * cbufX[6] * cbufY[7] +
 
                matSrc.at<cv::Vec3b>(sy-3, sx+4)[k] * cbufX[7] * cbufY[0] + matSrc.at<cv::Vec3b>(sy-2, sx+4)[k] * cbufX[7] * cbufY[1] +
                matSrc.at<cv::Vec3b>(sy-1, sx+4)[k] * cbufX[7] * cbufY[2] + matSrc.at<cv::Vec3b>(sy, sx+4)[k] * cbufX[7] * cbufY[3] +
                matSrc.at<cv::Vec3b>(sy+1, sx+4)[k] * cbufX[7] * cbufY[4] + matSrc.at<cv::Vec3b>(sy+2, sx+4)[k] * cbufX[7] * cbufY[5] +
                matSrc.at<cv::Vec3b>(sy+3, sx+4)[k] * cbufX[7] * cbufY[6] + matSrc.at<cv::Vec3b>(sy+4, sx+4)[k] * cbufX[7] * cbufY[7] ) >> 22);// 4194304
        }
    }
}
cv::imwrite("Lanczos_1.jpg", matDst1);
 
cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 4);
cv::imwrite("Lanczos_2.jpg", matDst2);

以上代码的实现结果与cv::resize函数相同,但是执行效率非常低,只是为了详细说明插值过程。OpenCV中默认采用C++ Concurrency进行优化加速,你也可以采用TBB、OpenMP等进行优化加速。

GitHub:https://github.com/fengbingchun/OpenCV_Test/blob/master/demo/OpenCV_Test/test_opencv_funset.cpp

到此这篇关于OpenCV中resize函数插值算法的实现过程(五种)的文章就介绍到这了,更多相关OpenCV resize插值内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/fengbingchun/article/details/17335477

延伸 · 阅读

精彩推荐