图像插值缩放

简单实现, 仅限单通道图像

双线性插值

双向性差值中,缩放图像(以下称目标图像)的像素的点 P 的强度值取决于相邻4个像素点的加权和。

假设缩放因子为 s, 那么目标图像的像素点可以通过 r, c 来映射源图像,如下所示

r = floor\left ( \frac{x}{s} \right ) \ and \ c = floor\left ( \frac{y}{s} \right )

那么从感兴趣像素点到原图像像素的距离可如下表示

x_d, y_d = \begin{Bmatrix}
rem\left ( \frac{x}{s}, 1 \right ) & ,rem\left ( \frac{y}{s}, 1 \right ) 
\end{Bmatrix}

因此相邻4个像素点可表示为

P_{topLft},P_{topRht},P_{botLft},P_{botRht} = \begin{Bmatrix}
f\left ( r,c \right ), & f\left ( r+1,c \right ), & f\left ( r,c+1 \right ), & f\left ( r+1,c+1 \right )
\end{Bmatrix}

然后利用上述信息,可以计算出感兴趣像素点值的加权和

v\left ( x,y \right ) = \left ( 1-y_d \right )\left ( x_d\cdot P_{topRht} + \left ( 1-x_d \right )\cdot P_{topLft}) \right ) + y_d\left ( x_d\cdot P_{botRht} + \left ( 1-x_d \right ) \cdot P_{botLft} \right )

代码如下所示:

 1 void resize_zoom(unsigned char *pSrc, unsigned char *pDst, int src_stride, int src_height, float zoom_x, float zoom_y)
 2 {
 3     #define CHECK_BOUNDARY(a, v)  ((a) > (v) ? (v):( (a) <0 ? (0):(a) ))
 4     if (!(zoom_x > 0 && zoom_y > 0 && src_stride > 0 && src_height > 0 && pSrc != NULL && pDst != NULL)) {
 5         printf("input param error..\n");
 6         pDst = NULL;
 7         return;
 8     }
 9     int dst_w = floor(zoom_x * src_stride);
10     int dst_h = floor(zoom_y * src_height);
11     
12     for (int h = 0; h < dst_h; h++) {
13         int y1 = CHECK_BOUNDARY(floor(h / zoom_y), src_height);
14         int y2 = CHECK_BOUNDARY(ceil(h / zoom_y), src_height);
15         float y = fmod((h/zoom_y), 1);
16         for (int w = 0; w < dst_w; w++) {
17             int x1 = CHECK_BOUNDARY(floor(w / zoom_x), src_stride);
18             int x2 = CHECK_BOUNDARY(ceil(w / zoom_x), src_stride);
19             float x = fmod((w / zoom_x), 1);
20             unsigned char topLeft = pSrc[y1 * src_stride + x1];
21             unsigned char botLeft = pSrc[y1 * src_stride + x2];
22             unsigned char topRight = pSrc[y2 * src_stride + x1];
23             unsigned char botRight = pSrc[y2 * src_stride + x2];
24             unsigned int tr = (topRight * y) + (topLeft * (1 - y));
25             unsigned int br = (botRight * y) + (botLeft * (1 - y));
26             unsigned int c = (br * x) + (tr * (1 - x));
27             pDst[h * dst_w + w] = CHECK_BOUNDARY(c, 255);
28         }
29     }
30     #undef CHECK_BOUNDARY
31 }
View Code

 

最近邻插值

最近邻插值算法中,像素点 v(x, y) 的强度取决于该点映射到源图像素点 f(x, y) 相邻像素的强度值。

具体实现逻辑如下

 1 void nnbr(unsigned char *pSrc, unsigned char *pDst, int src_stride, int src_height, float zoom_x, float zoom_y)
 2 {
 3     #define CHECK_BOUNDARY(a, v)  ((a) > (v) ? (v):( (a) <0 ? (0):(a) ))
 4     if (!(zoom_x > 0 && zoom_y > 0 && src_stride > 0 && src_height > 0 && pSrc != NULL && pDst != NULL)) {
 5         printf("input param error..\n");
 6         pDst = NULL;
 7         return;
 8     }
 9     int dst_w = floor(zoom_x * src_stride);
10     int dst_h = floor(zoom_y * src_height);
11     
12     for (int h = 0; h < dst_h; h++) {
13         int near_h = CHECK_BOUNDARY(floor(h / zoom_y), src_height);
14         for (int w = 0; w < dst_w; w++) {
15             int near_w = CHECK_BOUNDARY(floor(w / zoom_x), src_stride);
16             unsigned int c = pSrc[near_h * src_stride + near_w];
17             pDst[h * dst_w + w] = CHECK_BOUNDARY(c, 255);
18         }
19     }
20     #undef CHECK_BOUNDARY
21 }
View Code

 

posted @ 2017-04-04 11:46  呆呆的独行者  阅读(301)  评论(0编辑  收藏  举报