{"id":371,"date":"2009-12-29T16:43:20","date_gmt":"2009-12-29T23:43:20","guid":{"rendered":"http:\/\/www.giassa.net\/?page_id=371"},"modified":"2025-08-24T08:03:52","modified_gmt":"2025-08-24T15:03:52","slug":"iv-generalized-bicubic-interpolation","status":"publish","type":"page","link":"https:\/\/www.giassa.net\/?page_id=371","title":{"rendered":"IV &#8211; Generalized Bicubic Interpolation"},"content":{"rendered":"<p>If you haven&#8217;t read the previous section on bicubic spline interpolation, now would be a good time!<\/p>\n<p>As mentioned in the previous section, when we are performing bicubic interpolation, we are generating a smooth surface that interpolates data points on a 2D grid. Also, as previously mentioned&#8230;<\/p>\n<h1>Quote:<\/h1>\n<p><em>So, we can see that we have taken the original data set, and interpolated values in both the x and y dimensions to create a smooth surface. <strong>An important note<\/strong>: Notice how the interpolated dataset is smooth in the x-direction, y-direction, and the xy-direction (ie: along the diagonals). This means that for any point in our interpolated data set, we should be able to compute not only the intensity (ie: height\/grayscale) value, but also it&#8217;s derivative in ANY direction along x, y, or xy. This is equivalent to us having the following data available to us (assume <img src='https:\/\/s0.wp.com\/latex.php?latex=f%28a%2Cb%29%3D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(a,b)=' title='f(a,b)=' class='latex' \/>the grayscale intensity value from the source image, <img src='https:\/\/s0.wp.com\/latex.php?latex=X&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='X' title='X' class='latex' \/>, at <img src='https:\/\/s0.wp.com\/latex.php?latex=X%28a%2Cb%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='X(a,b)' title='X(a,b)' class='latex' \/>, and that we are trying to calculate the interpolated grayscale value in the target\/output image, <img src='https:\/\/s0.wp.com\/latex.php?latex=Y&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='Y' title='Y' class='latex' \/>, at <img src='https:\/\/s0.wp.com\/latex.php?latex=Y%28J%2CK%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='Y(J,K)' title='Y(J,K)' class='latex' \/>) (Equations based on those provided in [1]):<\/em><\/p>\n<ul>\n<li><em>The original intensity values of the surrounding pixels (4 values) <\/em>\n<ul>\n<li><em><img src='https:\/\/s0.wp.com\/latex.php?latex=f%28A%2CB%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(A,B)' title='f(A,B)' class='latex' \/><\/em><\/li>\n<li><em><img src='https:\/\/s0.wp.com\/latex.php?latex=f%28A%2B1%2CB%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(A+1,B)' title='f(A+1,B)' class='latex' \/><\/em><\/li>\n<li><em><img src='https:\/\/s0.wp.com\/latex.php?latex=f%28A%2CB%2B1%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(A,B+1)' title='f(A,B+1)' class='latex' \/><\/em><\/li>\n<li><em><img src='https:\/\/s0.wp.com\/latex.php?latex=f%28A%2B1%2CB%2B1%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(A+1,B+1)' title='f(A+1,B+1)' class='latex' \/><\/em><\/li>\n<\/ul>\n<\/li>\n<li><em>The partial derivatives along the x-axis for each of these points (4 values) <\/em>\n<ul>\n<li><em><img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cdfrac%7B%5Cdelta+f%7D%7B%5Cdelta+x%7D%3Df_x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\dfrac{\\delta f}{\\delta x}=f_x' title='\\dfrac{\\delta f}{\\delta x}=f_x' class='latex' \/><\/em><\/li>\n<\/ul>\n<\/li>\n<li><em>The partial derivatives along the y-axis for each of these points (4 values) <\/em>\n<ul>\n<li><em><img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cdfrac%7B%5Cdelta+f%7D%7B%5Cdelta+y%7D%3Df_y&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\dfrac{\\delta f}{\\delta y}=f_y' title='\\dfrac{\\delta f}{\\delta y}=f_y' class='latex' \/><\/em><\/li>\n<\/ul>\n<\/li>\n<li><em>The cross-derivatives at each of these points (4 values) <\/em>\n<ul>\n<li><em><img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cdfrac%7B%5Cdelta%5E2+f%7D%7B%5Cdelta+y%5Cdelta+x%7D%3Df_%7Bxy%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\dfrac{\\delta^2 f}{\\delta y\\delta x}=f_{xy}' title='\\dfrac{\\delta^2 f}{\\delta y\\delta x}=f_{xy}' class='latex' \/><\/em><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><em> This leaves us with a total of 16 values to solve for in the case of generalized bicubic interpolation, as opposed to the 4 needed with 1D cubic spline interpolation (<img src='https:\/\/s0.wp.com\/latex.php?latex=a_i%2Cb_i%2Cc_i%2C&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='a_i,b_i,c_i,' title='a_i,b_i,c_i,' class='latex' \/> and <img src='https:\/\/s0.wp.com\/latex.php?latex=d_i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='d_i' title='d_i' class='latex' \/>).<\/em><\/p>\n<h1>End Quote<\/h1>\n<p>I also mentioned in the previous section that bicubic spline interpolation is a special case of generalized bicubic interpolation. For the former of the two, we simply carried out 1D cubic spline interpolation along each axis and we were done. We aren&#8217;t making use of all the data available to us though, such as the cross-derivatives.<\/p>\n<p>For each of the neighbouring 4 data points, we need to know its intensity value (<img src='https:\/\/s0.wp.com\/latex.php?latex=X%28A%2CB%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='X(A,B)' title='X(A,B)' class='latex' \/>), its partial derivatives along both axes (<img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cdfrac%7B%5Cdelta+f%7D%7B%5Cdelta+x%7D%3Df_x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\dfrac{\\delta f}{\\delta x}=f_x' title='\\dfrac{\\delta f}{\\delta x}=f_x' class='latex' \/> and <img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cdfrac%7B%5Cdelta+f%7D%7B%5Cdelta+y%7D%3Df_y&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\dfrac{\\delta f}{\\delta y}=f_y' title='\\dfrac{\\delta f}{\\delta y}=f_y' class='latex' \/>), and finally, its cross-derivatives (<img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cdfrac%7B%5Cdelta%5E2+f%7D%7B%5Cdelta+y%5Cdelta+x%7D%3Df_%7Bxy%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\dfrac{\\delta^2 f}{\\delta y\\delta x}=f_{xy}' title='\\dfrac{\\delta^2 f}{\\delta y\\delta x}=f_{xy}' class='latex' \/>) before we can proceed any further. Before we proceed these, we need a coordinate system, as always. Notice how we now need to know the values of (1-h),(1-w), etc, whereas when we carried out bicubic spline interpolation we didn&#8217;t!<\/p>\n<div id=\"attachment_423\" style=\"width: 317px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/grid-others1.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-423\" class=\"size-full wp-image-423\" title=\"grid-others\" src=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/grid-others1.png\" alt=\"\" width=\"307\" height=\"259\" srcset=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/grid-others1.png 307w, https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/grid-others1-300x253.png 300w\" sizes=\"auto, (max-width: 307px) 100vw, 307px\" \/><\/a><p id=\"caption-attachment-423\" class=\"wp-caption-text\">Grid Coordinates<\/p><\/div>\n<p>We can calculate the partial derivatives easily enough using centered differences, which are basically slope calculations using the intensity values, <img src='https:\/\/s0.wp.com\/latex.php?latex=f%28a%2Cb%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(a,b)' title='f(a,b)' class='latex' \/> from adjacent pixels. For the partial derivative along the horizontal axis<em>, <\/em><img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cdfrac%7B%5Cdelta+f%7D%7B%5Cdelta+x%7D%3Df_x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\dfrac{\\delta f}{\\delta x}=f_x' title='\\dfrac{\\delta f}{\\delta x}=f_x' class='latex' \/>, we can calculate it to be (assuming equal spacing between pixels in the source image):<\/p>\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_x%28A%2CB%29%3D%5Cdfrac%7Bf%28A%2B1%2CB%29-f%28A-1%2CB%29%7D%7B%28A%2B1%29-%28A-1%29%7D%3D%5Cdfrac%7Bf%28A%2B1%2CB%29-f%28A-1%2CB%29%7D%7B2%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_x(A,B)=\\dfrac{f(A+1,B)-f(A-1,B)}{(A+1)-(A-1)}=\\dfrac{f(A+1,B)-f(A-1,B)}{2}' title='f_x(A,B)=\\dfrac{f(A+1,B)-f(A-1,B)}{(A+1)-(A-1)}=\\dfrac{f(A+1,B)-f(A-1,B)}{2}' class='latex' \/><\/li>\n<\/ul>\n<p>Similarly, we calculate the partial derivative for the vertical axis at each neighbouring pixel by:<\/p>\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_y%28A%2CB%29%3D%5Cdfrac%7Bf%28A%2CB%2B1%29-f%28A%2CB-1%29%7D%7B%28B%2B1%29-%28B-1%29%7D%3D%5Cdfrac%7Bf%28A%2CB%2B1%29-f%28A%2CB-1%29%7D%7B2%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_y(A,B)=\\dfrac{f(A,B+1)-f(A,B-1)}{(B+1)-(B-1)}=\\dfrac{f(A,B+1)-f(A,B-1)}{2}' title='f_y(A,B)=\\dfrac{f(A,B+1)-f(A,B-1)}{(B+1)-(B-1)}=\\dfrac{f(A,B+1)-f(A,B-1)}{2}' class='latex' \/><\/li>\n<\/ul>\n<p>Finally, for the cross derivatives, we can calculate them by:<\/p>\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_%7Bxy%7D%28A%2CB%29%3D%5Cdfrac%7B%5Bf%28A-1%2CB-1%29%2Bf%28A%2B1%2CB%2B1%29%5D-%5Bf%28A%2B1%2CB-1%29%2Bf%28A-1%2CB%2B1%29%5D%7D%7B%5B%28A%2B1%29-%28A-1%29%5D%2A%5B%28B%2B1%29-%28B-1%29%5D%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{xy}(A,B)=\\dfrac{[f(A-1,B-1)+f(A+1,B+1)]-[f(A+1,B-1)+f(A-1,B+1)]}{[(A+1)-(A-1)]*[(B+1)-(B-1)]}' title='f_{xy}(A,B)=\\dfrac{[f(A-1,B-1)+f(A+1,B+1)]-[f(A+1,B-1)+f(A-1,B+1)]}{[(A+1)-(A-1)]*[(B+1)-(B-1)]}' class='latex' \/><\/li>\n<li>Therefore, <img src='https:\/\/s0.wp.com\/latex.php?latex=f_%7Bxy%7D%28A%2CB%29%3D%5Cdfrac%7B%5Bf%28A-1%2CB-1%29%2Bf%28A%2B1%2CB%2B1%29%5D-%5Bf%28A%2B1%2CB-1%29%2Bf%28A-1%2CB%2B1%29%5D%7D%7B4%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{xy}(A,B)=\\dfrac{[f(A-1,B-1)+f(A+1,B+1)]-[f(A+1,B-1)+f(A-1,B+1)]}{4}' title='f_{xy}(A,B)=\\dfrac{[f(A-1,B-1)+f(A+1,B+1)]-[f(A+1,B-1)+f(A-1,B+1)]}{4}' class='latex' \/><\/li>\n<\/ul>\n<p><strong>If the spacing between pixels is not equal (ie: you are only carrying out interpolation on part of an image rather than the whole thing), you will need to adjust the denominator values in the above equations. Note that even if you get these values wrong, <\/strong><strong>the final result will still be smooth, just not as accurate!<\/strong><\/p>\n<p>With these values available, we can defined any interpolated value in our output\/target image, <img src='https:\/\/s0.wp.com\/latex.php?latex=p%28x%2Cy%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p(x,y)' title='p(x,y)' class='latex' \/>, as a function of the pixels from our input image according to (refer to the grid coordinates in the figure above for visual definitions of A,B,J,K,h, and w):<\/p>\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=p%28J%2CK%29%3D%5Csum_%7Bm%3D0%7D%5E%7B3%7D%5Csum_%7Bn%3D0%7D%5E%7B3%7Da_%7Bmn%7D%281-w%29%5Em%281-h%29%5En&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^m(1-h)^n' title='p(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^m(1-h)^n' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=p_x%28J%2CK%29%3D%5Csum_%7Bm%3D0%7D%5E%7B3%7D%5Csum_%7Bn%3D0%7D%5E%7B3%7Da_%7Bmn%7D%281-w%29%5E%7Bm-1%7D%281-h%29%5En&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p_x(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^{m-1}(1-h)^n' title='p_x(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^{m-1}(1-h)^n' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=p_y%28J%2CK%29%3D%5Csum_%7Bm%3D0%7D%5E%7B3%7D%5Csum_%7Bn%3D0%7D%5E%7B3%7Da_%7Bmn%7D%281-w%29%5Em%281-h%29%5E%7Bn-1%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p_y(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^m(1-h)^{n-1}' title='p_y(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^m(1-h)^{n-1}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=p_%7Bxy%7D%28J%2CK%29%3D%5Csum_%7Bm%3D0%7D%5E%7B3%7D%5Csum_%7Bn%3D0%7D%5E%7B3%7Da_%7Bmn%7D%281-w%29%5E%7Bm-1%7D%281-h%29%5E%7Bn-1%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p_{xy}(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^{m-1}(1-h)^{n-1}' title='p_{xy}(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^{m-1}(1-h)^{n-1}' class='latex' \/><\/li>\n<\/ul>\n<p>However, before we can carry on, we need to solve for the coefficients, <img src='https:\/\/s0.wp.com\/latex.php?latex=a_%7Bij%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='a_{ij}' title='a_{ij}' class='latex' \/>. Assuming that <img src='https:\/\/s0.wp.com\/latex.php?latex=w&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='w' title='w' class='latex' \/> and <img src='https:\/\/s0.wp.com\/latex.php?latex=h&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='h' title='h' class='latex' \/> are continuous over the interval <img src='https:\/\/s0.wp.com\/latex.php?latex=%5B0%2C1%5D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='[0,1]' title='[0,1]' class='latex' \/>, and that we redefine the values at the gridpoints of the source image, <img src='https:\/\/s0.wp.com\/latex.php?latex=f%28A%2CB%29%2Cf%28A%2B1%2CB%29%2Cf%28A%2CB%2B1%29%2Cf%28A%2B1%2CB%2B1%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(A,B),f(A+1,B),f(A,B+1),f(A+1,B+1)' title='f(A,B),f(A+1,B),f(A,B+1),f(A+1,B+1)' class='latex' \/> as <img src='https:\/\/s0.wp.com\/latex.php?latex=f%280%2C0%29%2Cf%281%2C0%29%2Cf%280%2C1%29%2Cf%281%2C1%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(0,0),f(1,0),f(0,1),f(1,1)' title='f(0,0),f(1,0),f(0,1),f(1,1)' class='latex' \/>, we can express all 16 coefficients of <img src='https:\/\/s0.wp.com\/latex.php?latex=a_%7Bmn%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='a_{mn}' title='a_{mn}' class='latex' \/> as follows (equations provided by [1]):<\/p>\n<ul>\n<li>Function values:\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f%280%2C0%29%3Da_%7B00%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(0,0)=a_{00}' title='f(0,0)=a_{00}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f%281%2C0%29%3Da_%7B00%7D%2Ba_%7B10%7D%2Ba_%7B20%7D%2Ba_%7B30%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(1,0)=a_{00}+a_{10}+a_{20}+a_{30}' title='f(1,0)=a_{00}+a_{10}+a_{20}+a_{30}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f%280%2C1%29%3Da_%7B00%7D%2Ba_%7B01%7D%2Ba_%7B02%7D%2Ba_%7B03%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(0,1)=a_{00}+a_{01}+a_{02}+a_{03}' title='f(0,1)=a_{00}+a_{01}+a_{02}+a_{03}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f%281%2C1%29%3D%5Csum_%7Bm%3D0%7D%5E%7B3%7D%5Csum_%7Bn%3D0%7D%5E%7B3%7Da_%7Bmn%7D%3Da_%7B00%7D%2Ba_%7B01%7D%2Ba_%7B02%7D%2Ba_%7B03%7D%2Ba_%7B10%7D%2Ba_%7B11%7D%2Ba_%7B12%7D%2Ba_%7B13%7D%2Ba_%7B20%7D%2Ba_%7B21%7D%2Ba_%7B22%7D%2Ba_%7B23%7D%2Ba_%7B30%7D%2Ba_%7B31%7D%2Ba_%7B32%7D%2Ba_%7B33%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f(1,1)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}=a_{00}+a_{01}+a_{02}+a_{03}+a_{10}+a_{11}+a_{12}+a_{13}+a_{20}+a_{21}+a_{22}+a_{23}+a_{30}+a_{31}+a_{32}+a_{33}' title='f(1,1)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}=a_{00}+a_{01}+a_{02}+a_{03}+a_{10}+a_{11}+a_{12}+a_{13}+a_{20}+a_{21}+a_{22}+a_{23}+a_{30}+a_{31}+a_{32}+a_{33}' class='latex' \/><\/li>\n<\/ul>\n<\/li>\n<li>X-Derivatives:\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_x%280%2C0%29%3Da_%7B10%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_x(0,0)=a_{10}' title='f_x(0,0)=a_{10}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_x%281%2C0%29%3Da_%7B10%7D%2B2a_%7B20%7D%2B3a_%7B30%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_x(1,0)=a_{10}+2a_{20}+3a_{30}' title='f_x(1,0)=a_{10}+2a_{20}+3a_{30}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_x%280%2C1%29%3Da_%7B10%7D%2Ba_%7B11%7D%2Ba_%7B12%7D%2Ba_%7B13%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_x(0,1)=a_{10}+a_{11}+a_{12}+a_{13}' title='f_x(0,1)=a_{10}+a_{11}+a_{12}+a_{13}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_x%281%2C1%29%3D%5Csum_%7Bm%3D1%7D%5E%7B3%7D%5Csum_%7Bn%3D0%7D%5E%7B3%7Da_%7Bmn%7Dm&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_x(1,1)=\\sum_{m=1}^{3}\\sum_{n=0}^{3}a_{mn}m' title='f_x(1,1)=\\sum_{m=1}^{3}\\sum_{n=0}^{3}a_{mn}m' class='latex' \/><\/li>\n<\/ul>\n<\/li>\n<li>Y-Derivatives:\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_y%280%2C0%29%3Da_%7B01%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_y(0,0)=a_{01}' title='f_y(0,0)=a_{01}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_y%281%2C0%29%3Da_%7B01%7D%2Ba_%7B11%7D%2Ba_%7B21%7D%2Ba_%7B31%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_y(1,0)=a_{01}+a_{11}+a_{21}+a_{31}' title='f_y(1,0)=a_{01}+a_{11}+a_{21}+a_{31}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_y%280%2C1%29%3Da_%7B01%7D%2B2a_%7B02%7D%2B3a_%7B03%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_y(0,1)=a_{01}+2a_{02}+3a_{03}' title='f_y(0,1)=a_{01}+2a_{02}+3a_{03}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_y%281%2C1%29%3D%5Csum_%7Bm%3D0%7D%5E%7B3%7D%5Csum_%7Bn%3D1%7D%5E%7B3%7Da_%7Bmn%7Dn&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_y(1,1)=\\sum_{m=0}^{3}\\sum_{n=1}^{3}a_{mn}n' title='f_y(1,1)=\\sum_{m=0}^{3}\\sum_{n=1}^{3}a_{mn}n' class='latex' \/><\/li>\n<\/ul>\n<\/li>\n<li>Cross-Derivatives (XY):\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_%7Bxy%7D%280%2C0%29%3Da_%7B11%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{xy}(0,0)=a_{11}' title='f_{xy}(0,0)=a_{11}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_%7Bxy%7D%281%2C0%29%3Da_%7B11%7D%2B2a_%7B21%7D%2B3a_%7B31%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{xy}(1,0)=a_{11}+2a_{21}+3a_{31}' title='f_{xy}(1,0)=a_{11}+2a_{21}+3a_{31}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_%7Bxy%7D%280%2C0%29%3Da_%7B11%7D%2B2a_%7B12%7D%2B3a_%7B13%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{xy}(0,0)=a_{11}+2a_{12}+3a_{13}' title='f_{xy}(0,0)=a_{11}+2a_{12}+3a_{13}' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=f_%7Bxy%7D%280%2C0%29%3D%5Csum_%7Bm%3D1%7D%5E%7B3%7D%5Csum_%7Bn%3D1%7D%5E%7B3%7Da_%7Bmn%7Dmn&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{xy}(0,0)=\\sum_{m=1}^{3}\\sum_{n=1}^{3}a_{mn}mn' title='f_{xy}(0,0)=\\sum_{m=1}^{3}\\sum_{n=1}^{3}a_{mn}mn' class='latex' \/><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>These coefficient values, combined with the previously calculated partial and cross-derivative values, form a set of linear equations which form a matrix equation of the general form <img src='https:\/\/s0.wp.com\/latex.php?latex=Ax%3Db&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='Ax=b' title='Ax=b' class='latex' \/>. We will rewrite it in the form <img src='https:\/\/s0.wp.com\/latex.php?latex=M%5Calpha%3D%5Cbeta&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M\\alpha=\\beta' title='M\\alpha=\\beta' class='latex' \/> so that we don&#8217;t confuse the values for our matrices with those used in the equations above. Let:<\/p>\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=%5Calpha+%3D+%5Cleft%28%5Cbegin%7Barray%7D%7Bcccccccccccccccc%7Da_%7B00%7D%26a_%7B10%7D%26a_%7B20%7D%26a_%7B30%7D%26a_%7B01%7D%26a_%7B11%7D%26a_%7B21%7D%26a_%7B31%7D%26a_%7B02%7D%26a_%7B12%7D%26a_%7B22%7D%26a_%7B32%7D%26a_%7B03%7D%26a_%7B13%7D%26a_%7B23%7D%26a_%7B33%7D%5Cend%7Barray%7D%5Cright%29%5ET&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\alpha = \\left(\\begin{array}{cccccccccccccccc}a_{00}&amp;a_{10}&amp;a_{20}&amp;a_{30}&amp;a_{01}&amp;a_{11}&amp;a_{21}&amp;a_{31}&amp;a_{02}&amp;a_{12}&amp;a_{22}&amp;a_{32}&amp;a_{03}&amp;a_{13}&amp;a_{23}&amp;a_{33}\\end{array}\\right)^T' title='\\alpha = \\left(\\begin{array}{cccccccccccccccc}a_{00}&amp;a_{10}&amp;a_{20}&amp;a_{30}&amp;a_{01}&amp;a_{11}&amp;a_{21}&amp;a_{31}&amp;a_{02}&amp;a_{12}&amp;a_{22}&amp;a_{32}&amp;a_{03}&amp;a_{13}&amp;a_{23}&amp;a_{33}\\end{array}\\right)^T' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cbeta+%3D%5Cleft%28%5Cbegin%7Barray%7D%7Bcccccccccccccccc%7Df%280%2C0%29%26f%281%2C0%29%26f%280%2C1%29%26f%281%2C1%29%26f_x%280%2C0%29%26f_x%281%2C0%29%26f_x%280%2C1%29%26f_x%281%2C1%29%26f_y%280%2C0%29%26f_y%281%2C0%29%26f_y%280%2C1%29%26f_y%281%2C1%29%26f_%7Bxy%7D%280%2C0%29%26f_%7Bxy%7D%281%2C0%29%26f_%7Bxy%7D%280%2C1%29%26f_%7Bxy%7D%281%2C1%29%5Cend%7Barray%7D%5Cright%29%5ET&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\beta =\\left(\\begin{array}{cccccccccccccccc}f(0,0)&amp;f(1,0)&amp;f(0,1)&amp;f(1,1)&amp;f_x(0,0)&amp;f_x(1,0)&amp;f_x(0,1)&amp;f_x(1,1)&amp;f_y(0,0)&amp;f_y(1,0)&amp;f_y(0,1)&amp;f_y(1,1)&amp;f_{xy}(0,0)&amp;f_{xy}(1,0)&amp;f_{xy}(0,1)&amp;f_{xy}(1,1)\\end{array}\\right)^T' title='\\beta =\\left(\\begin{array}{cccccccccccccccc}f(0,0)&amp;f(1,0)&amp;f(0,1)&amp;f(1,1)&amp;f_x(0,0)&amp;f_x(1,0)&amp;f_x(0,1)&amp;f_x(1,1)&amp;f_y(0,0)&amp;f_y(1,0)&amp;f_y(0,1)&amp;f_y(1,1)&amp;f_{xy}(0,0)&amp;f_{xy}(1,0)&amp;f_{xy}(0,1)&amp;f_{xy}(1,1)\\end{array}\\right)^T' class='latex' \/><\/li>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=M%3D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M=' title='M=' class='latex' \/>\n<p><div id=\"attachment_433\" style=\"width: 315px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-433\" class=\"size-full wp-image-433\" title=\"M-matrix\" src=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix.png\" alt=\"\" width=\"305\" height=\"321\" srcset=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix.png 305w, https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix-285x300.png 285w\" sizes=\"auto, (max-width: 305px) 100vw, 305px\" \/><\/a><p id=\"caption-attachment-433\" class=\"wp-caption-text\">Coefficient Matrix for &#8216;a&#8217;-values<\/p><\/div><\/li>\n<\/ul>\n<p>Note that the <img src='https:\/\/s0.wp.com\/latex.php?latex=%5ET&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='^T' title='^T' class='latex' \/> refers to the transpose of these matrices, rather than an exponent (which would only make sense for a square matrix anyways). With these equations, we can use our favorite method (feel free to pick) of solving this set of linear equations to solve for the inverse of our weighting matrix, <img src='https:\/\/s0.wp.com\/latex.php?latex=M&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M' title='M' class='latex' \/>. Once this is done, we can save this matrix for use in any future implementations of bicubic interpolation, as there is no need to recalculate it again in the future. By simple matrix inversion (yes, you can do this by hand if you really want to, the matrix algebra is very simple, just time-consuming; it&#8217;d be better to do this with MATLAB), we get the inverted coefficient matrix, <img src='https:\/\/s0.wp.com\/latex.php?latex=M%5E%7B-1%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M^{-1}' title='M^{-1}' class='latex' \/>.<\/p>\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=M%5E%7B-1%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M^{-1}' title='M^{-1}' class='latex' \/> =<\/li>\n<\/ul>\n<div id=\"attachment_434\" style=\"width: 315px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix-inverted.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-434\" class=\"size-full wp-image-434\" title=\"M-matrix-inverted\" src=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix-inverted.png\" alt=\"\" width=\"305\" height=\"321\" srcset=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix-inverted.png 305w, https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/M-matrix-inverted-285x300.png 285w\" sizes=\"auto, (max-width: 305px) 100vw, 305px\" \/><\/a><p id=\"caption-attachment-434\" class=\"wp-caption-text\">Inverted Coefficient Matrix<\/p><\/div>\n<p>When <img src='https:\/\/s0.wp.com\/latex.php?latex=M%5E%7B-1%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M^{-1}' title='M^{-1}' class='latex' \/> is\u00a0 multiplied (via matrix multiplication of course) with our product matrix, <img src='https:\/\/s0.wp.com\/latex.php?latex=%5Cbeta&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\beta' title='\\beta' class='latex' \/>, this gives us the values of each of the 16 coefficients in our <img src='https:\/\/s0.wp.com\/latex.php?latex=%5Calpha&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\\alpha' title='\\alpha' class='latex' \/> matrix. We can now use the previously defined sigma-notation formula to determine the value of any interpolated data point using the formula:<\/p>\n<ul>\n<li><img src='https:\/\/s0.wp.com\/latex.php?latex=p%28J%2CK%29%3D%5Csum_%7Bm%3D0%7D%5E%7B3%7D%5Csum_%7Bn%3D0%7D%5E%7B3%7Da_%7Bmn%7D%281-w%29%5Em%281-h%29%5En&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^m(1-h)^n' title='p(J,K)=\\sum_{m=0}^{3}\\sum_{n=0}^{3}a_{mn}(1-w)^m(1-h)^n' class='latex' \/><\/li>\n<\/ul>\n<p>The following MATLAB M-function demonstrates this algorithm in action:<\/p>\n<pre class=\"lang:matlab decode:true \">% GBI.M\r\n% Written December 2009, (C) Matthew Giassa\r\n% teo@giassa.net, www.giassa.net\r\n% Returns an upsampled image using bicubic interpolation\r\nfunction output_image = gbi( input_image,x_res,y_res )\r\n%   input_image     -   an image on which to perform bicubic interpolation\r\n%   x_res           -   the new horizontal dimensions (in pixels)\r\n%   y_res           -   the new vertical dimensions (in pixels)\r\n%Define the inverted weighting matrix, M^(-1), no need to recalculate it\r\n%ever again\r\nM_inv = [\r\n 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;\r\n 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0;\r\n -3,3,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0;\r\n 2,-2,0,0,1,1,0,0,0,0,0,0,0,0,0,0;\r\n 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0;\r\n 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0;\r\n 0,0,0,0,0,0,0,0,-3,3,0,0,-2,-1,0,0;\r\n 0,0,0,0,0,0,0,0,2,-2,0,0,1,1,0,0;\r\n -3,0,3,0,0,0,0,0,-2,0,-1,0,0,0,0,0;\r\n 0,0,0,0,-3,0,3,0,0,0,0,0,-2,0,-1,0;\r\n 9,-9,-9,9,6,3,-6,-3,6,-6,3,-3,4,2,2,1;\r\n -6,6,6,-6,-3,-3,3,3,-4,4,-2,2,-2,-2,-1,-1;\r\n 2,0,-2,0,0,0,0,0,1,0,1,0,0,0,0,0;\r\n 0,0,0,0,2,0,-2,0,0,0,0,0,1,0,1,0;\r\n -6,6,6,-6,-4,-2,4,2,-3,3,-3,3,-2,-1,-2,-1;\r\n 4,-4,-4,4,2,2,-2,-2,2,-2,2,-2,1,1,1,1\r\n ];\r\n%Make a copy of the input image\r\nI = input_image;\r\n%Convert image to grayscale (intensity) values for simplicity (for now)\r\nI = double(rgb2gray(I));\r\n%Determine the dimensions of the source image\r\n%Note that we will have three values - width, height, and the number\r\n%of color vectors, 3\r\n[j k] = size(I);\r\n%Specify the new image dimensions we want for our larger output image\r\nx_new = x_res;\r\ny_new = y_res;\r\n%Determine the ratio of the old dimensions compared to the new dimensions\r\n%Referred to as S1 and S2 in my tutorial\r\nx_scale = x_new.\/(j-1);\r\ny_scale = y_new.\/(k-1);\r\n%Declare and initialize an output image buffer\r\ntemp_image = zeros(x_new,y_new);\r\n%Calculate the horizontal derivatives for each point (assume that at the\r\n%edge pixels of the source image, all derivatives are zero to maximize\r\n%smoothing). Take note - recreating this in C or C++ might not be so easy,\r\n%as you must pay attention to how this code is using matrix-style\r\n%addressing (x-y positions swapped).\r\nIx = double(zeros(j,k));\r\nfor count1 = 1:j\r\n for count2 = 1:k\r\n if( (count2==1) || (count2==k) )\r\n Ix(count1,count2)=0;\r\n else\r\n Ix(count1,count2)=(0.5).*(I(count1,count2+1)-I(count1,count2-1));\r\n end\r\n end\r\nend\r\n%Similarly, calculate the vertical derivatives\r\nIy = double(zeros(j,k));\r\nfor count1 = 1:j\r\n for count2 = 1:k\r\n if( (count1==1) || (count1==j) )\r\n Iy(count1,count2)=0;\r\n else\r\n Iy(count1,count2)=(0.5).*(I(count1+1,count2)-I(count1-1,count2));\r\n end\r\n end\r\nend\r\n%Finally, calculate the cross derivatives\r\nIxy = double(zeros(j,k));\r\nfor count1 = 1:j\r\n for count2 = 1:k\r\n if( (count1==1) || (count1==j) || (count2==1) || (count2==k) )\r\n Ixy(count1,count2)=0;\r\n else\r\n Ixy(count1,count2)=(0.25).*((I(count1+1,count2+1)+I(count1-1,count2-1)) - (I(count1+1,count2-1)+I(count1-1,count2+1)));\r\n end\r\n end\r\nend\r\n%Generate the output image\r\n%==========================================================================\r\n%Please note that this is definitely not the most efficient way to carry\r\n%out this operation, as we are recalculating our beta and alpha-vectors far\r\n%repeatedly when there is no need. I kept the code like this so you can see\r\n%the order in which we would carry out most operations. If you want to make\r\n%a more efficient version which pre-calculates the alpha vector for each\r\n%pixel in the source image, be my guest.\r\n%==========================================================================\r\nfor count1 = 0:x_new-1\r\n for count2 = 0:y_new-1\r\n %Calculate the normalized distance constants, h and w\r\n W = -(((count1.\/x_scale)-floor(count1.\/x_scale))-1);\r\n H = -(((count2.\/y_scale)-floor(count2.\/y_scale))-1);\r\n %Determine the indexes\/address of the 4 neighbouring pixels from\r\n %the source data\/image\r\n I11_index = [1+floor(count1.\/x_scale),1+floor(count2.\/y_scale)];\r\n I21_index = [1+floor(count1.\/x_scale),1+ceil(count2.\/y_scale)];\r\n I12_index = [1+ceil(count1.\/x_scale),1+floor(count2.\/y_scale)];\r\n I22_index = [1+ceil(count1.\/x_scale),1+ceil(count2.\/y_scale)];\r\n %Calculate the four nearest function values\r\n I11 = I(I11_index(1),I11_index(2));\r\n I21 = I(I21_index(1),I21_index(2));\r\n I12 = I(I12_index(1),I12_index(2));\r\n I22 = I(I22_index(1),I22_index(2));\r\n %Calculate the four nearest horizontal derivatives\r\n Ix11 = Ix(I11_index(1),I11_index(2));\r\n Ix21 = Ix(I21_index(1),I21_index(2));\r\n Ix12 = Ix(I12_index(1),I12_index(2));\r\n Ix22 = Ix(I22_index(1),I22_index(2));\r\n %Calculate the four nearest vertical derivatives\r\n Iy11 = Iy(I11_index(1),I11_index(2));\r\n Iy21 = Iy(I21_index(1),I21_index(2));\r\n Iy12 = Iy(I12_index(1),I12_index(2));\r\n Iy22 = Iy(I22_index(1),I22_index(2));\r\n %Calculate the four nearest cross derivatives\r\n Ixy11 = Ixy(I11_index(1),I11_index(2));\r\n Ixy21 = Ixy(I21_index(1),I21_index(2));\r\n Ixy12 = Ixy(I12_index(1),I12_index(2));\r\n Ixy22 = Ixy(I22_index(1),I22_index(2));\r\n %Create our beta-vector\r\n beta = [I11 I21 I12 I22 Ix11 Ix21 Ix12 Ix22 Iy11 Iy21 Iy12 Iy22 Ixy11 Ixy21 Ixy12 Ixy22];\r\n %Calculate our alpha vector (ie: the a-values) using simple matrix\r\n %multiplication\r\n %==================================================================\r\n %If we wanted to make sure this entire program is written entirely\r\n %from scratch, we would implement our own code to multiple an AxB\r\n %matrix and a BxC matrix right here. This is very simple to do, so\r\n %I won't go over it right now.\r\n %==================================================================\r\n alpha = M_inv*beta';\r\n temp_p=0;\r\n for count3 = 1:16\r\n w_temp = floor((count3-1)\/4);\r\n h_temp = mod(count3-1,4);\r\n %disp(sprintf('aij=%d  wsub=%d   hsub=%d\\n',count3,w_temp,h_temp))\r\n temp_p = temp_p + alpha(count3).*((1-W)^(w_temp)).*((1-H)^(h_temp));\r\n end\r\n temp_image(count1+1,count2+1)=temp_p;\r\n end\r\nend\r\noutput_image = temp_image;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Included below is a simple resampling of a 4&#215;4 checkerboard pattern to a much larger resolution using the code above.<\/p>\n<div id=\"attachment_440\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/bci-mine.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-440\" class=\"size-medium wp-image-440\" title=\"bci-mine\" src=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/bci-mine-300x265.png\" alt=\"\" width=\"300\" height=\"265\" srcset=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/bci-mine-300x265.png 300w, https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/bci-mine.png 568w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-440\" class=\"wp-caption-text\">Bicubic Interpolation on 4&#215;4 Checkerboard Pattern<\/p><\/div>\n<p>Before concluding this section, I should note that there are many other resampling methods that are definitely worth reading up on, such as Lanczos, Hermite spline, Super Eagle, 2xSAI, HQn, and so on. Many of these algorithms are used in commerical products such as image processing software digital cameras, even console emulators. I will now conclude this section with a brief comparison of &#8220;bicubic spline interpolation&#8221; and &#8220;generalized bicubic interpolation&#8221;, and will show why the two are <strong>NOT<\/strong> the same.<\/p>\n<p>First, observe the image pairs below. The first pair was generated by using bicubic spline interpolation, which was covered in the previous subsection, while the latter pair was generated with the generalized bicubic interpolation algorithm covered in this subsection (the two original smiley faces used are slightly different, but no matter):<\/p>\n<div id=\"attachment_442\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-halo1.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-442\" class=\"size-medium wp-image-442\" title=\"smile-halo\" src=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-halo1-300x209.png\" alt=\"\" width=\"300\" height=\"209\" srcset=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-halo1-300x209.png 300w, https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-halo1.png 656w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-442\" class=\"wp-caption-text\">Resampling Using Bicubic Spline Interpolation<\/p><\/div>\n<div id=\"attachment_441\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-bci.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-441\" class=\"size-medium wp-image-441\" title=\"smile-bci\" src=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-bci-300x202.png\" alt=\"\" width=\"300\" height=\"202\" srcset=\"https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-bci-300x202.png 300w, https:\/\/www.giassa.net\/wp-content\/uploads\/2009\/12\/smile-bci.png 843w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-441\" class=\"wp-caption-text\">Resampling Using Generalized Bicubic Interpolation<\/p><\/div>\n<p>If we observe the resampling smiley faces, we can see that both still have halos introduced due to our choice of resampling algorithms. One important difference exists between both of the sampled images, however &#8211; the former of the two (generated using bicubic spline interpolation) still demonstrates some sharp edges and even corners, while the latter does not. This is due to bicubic spline interpolation being a rough approximation of generalized bicubic interpolation at best, primarily due to it not making any use of the cross-derivatives of the source data.<\/p>\n<h1>References<\/h1>\n<p>[1] <em>Numerical recipes in C the art of scientific computing<\/em>. Cambridge: Cambridge UP, 1992. Print.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you haven&#8217;t read the previous section on bicubic spline interpolation, now would be a good time! As mentioned in the previous section, when we are performing bicubic interpolation, we are generating a smooth surface that interpolates data points on &hellip; <a href=\"https:\/\/www.giassa.net\/?page_id=371\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":200,"menu_order":3,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-371","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"A tutorial on the general concept of bicubic interpolation.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.giassa.net\/?page_id=371\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"GIASSA.NET | Engineering, DIY, and Everything Else\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Image Processing - Generalized Bicubic Interpolation | GIASSA.NET\" \/>\n\t\t<meta property=\"og:description\" content=\"A tutorial on the general concept of bicubic interpolation.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.giassa.net\/?page_id=371\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2009-12-29T23:43:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2025-08-24T15:03:52+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Image Processing - Generalized Bicubic Interpolation | GIASSA.NET\" \/>\n\t\t<meta name=\"twitter:description\" content=\"A tutorial on the general concept of bicubic interpolation.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=371#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.giassa.net\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=865#listItem\",\"name\":\"Projects\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=865#listItem\",\"position\":2,\"name\":\"Projects\",\"item\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=865\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=118#listItem\",\"name\":\"Image Processing Tutorials\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=118#listItem\",\"position\":3,\"name\":\"Image Processing Tutorials\",\"item\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=118\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=200#listItem\",\"name\":\"2 &#8211; Upsampling &#038; Interpolation\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=865#listItem\",\"name\":\"Projects\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=200#listItem\",\"position\":4,\"name\":\"2 &#8211; Upsampling &#038; Interpolation\",\"item\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=200\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=371#listItem\",\"name\":\"IV &#8211; Generalized Bicubic Interpolation\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=118#listItem\",\"name\":\"Image Processing Tutorials\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=371#listItem\",\"position\":5,\"name\":\"IV &#8211; Generalized Bicubic Interpolation\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=200#listItem\",\"name\":\"2 &#8211; Upsampling &#038; Interpolation\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/#organization\",\"name\":\"GIASSA.NET\",\"description\":\"Engineering, DIY, and Everything Else\",\"url\":\"https:\\\/\\\/www.giassa.net\\\/\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=371#webpage\",\"url\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=371\",\"name\":\"Image Processing - Generalized Bicubic Interpolation | GIASSA.NET\",\"description\":\"A tutorial on the general concept of bicubic interpolation.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.giassa.net\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.giassa.net\\\/?page_id=371#breadcrumblist\"},\"datePublished\":\"2009-12-29T16:43:20-07:00\",\"dateModified\":\"2025-08-24T08:03:52-07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.giassa.net\\\/#website\",\"url\":\"https:\\\/\\\/www.giassa.net\\\/\",\"name\":\"GIASSA.NET\",\"description\":\"Engineering, DIY, and Everything Else\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.giassa.net\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Image Processing - Generalized Bicubic Interpolation | GIASSA.NET","description":"A tutorial on the general concept of bicubic interpolation.","canonical_url":"https:\/\/www.giassa.net\/?page_id=371","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/www.giassa.net\/?page_id=371#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.giassa.net#listItem","position":1,"name":"Home","item":"https:\/\/www.giassa.net","nextItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=865#listItem","name":"Projects"}},{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=865#listItem","position":2,"name":"Projects","item":"https:\/\/www.giassa.net\/?page_id=865","nextItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=118#listItem","name":"Image Processing Tutorials"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=118#listItem","position":3,"name":"Image Processing Tutorials","item":"https:\/\/www.giassa.net\/?page_id=118","nextItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=200#listItem","name":"2 &#8211; Upsampling &#038; Interpolation"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=865#listItem","name":"Projects"}},{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=200#listItem","position":4,"name":"2 &#8211; Upsampling &#038; Interpolation","item":"https:\/\/www.giassa.net\/?page_id=200","nextItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=371#listItem","name":"IV &#8211; Generalized Bicubic Interpolation"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=118#listItem","name":"Image Processing Tutorials"}},{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=371#listItem","position":5,"name":"IV &#8211; Generalized Bicubic Interpolation","previousItem":{"@type":"ListItem","@id":"https:\/\/www.giassa.net\/?page_id=200#listItem","name":"2 &#8211; Upsampling &#038; Interpolation"}}]},{"@type":"Organization","@id":"https:\/\/www.giassa.net\/#organization","name":"GIASSA.NET","description":"Engineering, DIY, and Everything Else","url":"https:\/\/www.giassa.net\/"},{"@type":"WebPage","@id":"https:\/\/www.giassa.net\/?page_id=371#webpage","url":"https:\/\/www.giassa.net\/?page_id=371","name":"Image Processing - Generalized Bicubic Interpolation | GIASSA.NET","description":"A tutorial on the general concept of bicubic interpolation.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.giassa.net\/#website"},"breadcrumb":{"@id":"https:\/\/www.giassa.net\/?page_id=371#breadcrumblist"},"datePublished":"2009-12-29T16:43:20-07:00","dateModified":"2025-08-24T08:03:52-07:00"},{"@type":"WebSite","@id":"https:\/\/www.giassa.net\/#website","url":"https:\/\/www.giassa.net\/","name":"GIASSA.NET","description":"Engineering, DIY, and Everything Else","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.giassa.net\/#organization"}}]},"og:locale":"en_US","og:site_name":"GIASSA.NET | Engineering, DIY, and Everything Else","og:type":"article","og:title":"Image Processing - Generalized Bicubic Interpolation | GIASSA.NET","og:description":"A tutorial on the general concept of bicubic interpolation.","og:url":"https:\/\/www.giassa.net\/?page_id=371","article:published_time":"2009-12-29T23:43:20+00:00","article:modified_time":"2025-08-24T15:03:52+00:00","twitter:card":"summary","twitter:title":"Image Processing - Generalized Bicubic Interpolation | GIASSA.NET","twitter:description":"A tutorial on the general concept of bicubic interpolation."},"aioseo_meta_data":{"post_id":"371","title":"Image Processing - Generalized Bicubic Interpolation | #site_title","description":"A tutorial on the general concept of bicubic interpolation.","keywords":[{"label":"image processing","value":"image processing"},{"label":"MATLAB","value":"MATLAB"},{"label":"cubic","value":"cubic"},{"label":"bicubic","value":"bicubic"},{"label":"spline","value":"spline"},{"label":"interpolation","value":"interpolation"},{"label":"generalized","value":"generalized"},{"label":"MRI","value":"MRI"},{"label":"giassa","value":"giassa"},{"label":"matthew","value":"matthew"},{"label":"sfu","value":"sfu"},{"label":"engineering","value":"engineering"}],"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"WebPage","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2021-04-22 01:27:51","updated":"2025-08-24 15:30:04","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.giassa.net\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.giassa.net\/?page_id=865\" title=\"Projects\">Projects<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.giassa.net\/?page_id=118\" title=\"Image Processing Tutorials\">Image Processing Tutorials<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.giassa.net\/?page_id=200\" title=\"2 \u2013 Upsampling &amp; Interpolation\">2 \u2013 Upsampling &amp; Interpolation<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tIV \u2013 Generalized Bicubic Interpolation\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.giassa.net"},{"label":"Projects","link":"https:\/\/www.giassa.net\/?page_id=865"},{"label":"Image Processing Tutorials","link":"https:\/\/www.giassa.net\/?page_id=118"},{"label":"2 &#8211; Upsampling &#038; Interpolation","link":"https:\/\/www.giassa.net\/?page_id=200"},{"label":"IV &#8211; Generalized Bicubic Interpolation","link":"https:\/\/www.giassa.net\/?page_id=371"}],"_links":{"self":[{"href":"https:\/\/www.giassa.net\/index.php?rest_route=\/wp\/v2\/pages\/371","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.giassa.net\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.giassa.net\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.giassa.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.giassa.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=371"}],"version-history":[{"count":39,"href":"https:\/\/www.giassa.net\/index.php?rest_route=\/wp\/v2\/pages\/371\/revisions"}],"predecessor-version":[{"id":1095,"href":"https:\/\/www.giassa.net\/index.php?rest_route=\/wp\/v2\/pages\/371\/revisions\/1095"}],"up":[{"embeddable":true,"href":"https:\/\/www.giassa.net\/index.php?rest_route=\/wp\/v2\/pages\/200"}],"wp:attachment":[{"href":"https:\/\/www.giassa.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=371"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}