首页 > 编程知识 正文

图像插值实验,secx图像

时间:2023-05-03 17:25:09 阅读:34452 作者:4277

在谈插值之前,首先谈像素重采样的概念。 假设有图像a和图像b。 其中a是源图像,b是目标图像,a和b的坐标具有对应关系f。

(xa, ya)=f(xb, yb)

根据关系f,将a的像素值代入b的对应像素点中的过程被称为图像a的像素重新采样,并且图像b是重新采样后的图像。 例如,对于b的任意像素点(x,y ),如果对应的a的像素点为) x '、y ' ),则将a中点) x '、y ' )的像素值a ) x '、y ' )作为b中点) x、y )的像素值b ) x、y

(x‘, y’)=f(x, y)

B(x, y)=A(x', y')

像素重采样的常用场景是图像缩放和图像对齐。 在实际的APP应用中,原始图像a的对应坐标往往是浮点数据而不是整数,因此如下图所示,无法将其像素值直接分配给目标图像上的对应点。 此时,插值算法对获取点a(x )、y )的像素值很有帮助。

插值是使用浮点坐标点周围的整数点的像素值来计算该浮点坐标点的像素值。 例如,在上图中,点(x )、y ) )是浮点坐标点,利用其周围整数点p0、p1、p2、p3的像素值计算其像素值a ) x )、y )。 这个过程就是插值。

常见的插值算法包括最近邻插值、双线性插值和双立方插值。 无论是哪种插值算法,本质上对浮点坐标点周围n*n个整数坐标点的像素值进行加权相加,得到该浮点坐标点的像素值,如下式所示。

插值算法的不同在于权重w的计算不同。 分别详细介绍最近邻插值、双线性插值、双三次插值的计算原理和实现。

1. 最邻近插值

最近邻插值也可被看作将最接近浮点坐标点的点的像素值设置为其像素值,并且使用浮点坐标点周围2*2个整数点的像素值来计算其像素值,只是最近点的权重是1,其他三个点的权重系数都是0。

的插值计算如下:

其权重按以下公式计算。

最近邻插值的代码实现最简单,直接四舍五入浮点坐标即可。 假设浮点坐标为(x_float,y_float ),利用最近邻插值计算a(x_float,y_float )的代码实现如下:

intx=(int ) ) x_float 0.5; 等效于将//0.5相加并四舍五入的inty=(int ) (y_float 0.5 ); ucharinner_value=a.ptruchar(y ) [x] //a(x ),y )=a (x,y )2. 双线性插值

双线性插值与最近邻插值类似,使用浮点坐标点周围2*2个整数点的像素值计算像素值,但周围每个整数点的权重不是0。 也就是说,权重的计算与最近邻插值不同。

浮点坐标点(x_float,y_float )双线性插值的代码实现如下:

intx0=floor(x_float ); int x1=x0 1; inty0=floor(y_float ); int y1=y0 1; floatfracRow=y_float-y0; //求出浮点坐标小数部分floatfracCol=x_float-x0; float k0=1.0 - fracRow; float k1=1.0 - fracCol; floatw0=k0*k1; floatw1=fracRow*k1; floatw2=k0*fracCol; floatw3=fracRow*fracCol; uchar inner _ value=(uchar (w0 * a.ptr uchar ) Y0 ) W1*A.ptruchar ) X0 ) w2 * a.ptr uchar (y0 ) XX0 )。http://ww

双三次插值使用以浮点坐标为中心的4*4个整数点的像素值来计算像素值,如下图所示。

浮点坐标点的插值是周围4*4整数坐标点像素值的加权和。

这里,权重w(I,j )的计算如下式。 这里,a取值范围-1~0之间,一般取固定值-0.5。


双三次插值的实现代码如下。

首先是权重函数的实现:

float cubic_coeff(float x, float a){ if(x <= 1) { return 1-(a+3)*x*x+(a+2)*x*x*x; } else if(x < 2) { return -4*a+8*a*x-5*a*x*x+a*x*x*x; }    return 0.0;}

接着是权重系数的计算实现:

void cal_cubic_coeff(float x, float y, float *coeff){ /*calc the coeff*/    float u = x - floor(x);    float v = y - floor(y); u += 1; v += 1;    float a = -0.15; float a_mul_4 = (a + a) + (a + a); float a_mul_5 = a_mul_4 + a; float a_mul_8 = a_mul_4 + a_mul_4; float a_add_3 = a + 3;   float a_add_2 = a + 2; float A[4]; A[0] = cubic_coeff(abs(u), a); A[1] = cubic_coeff(abs(u-1), a); A[2] = cubic_coeff(abs(u-2), a); A[3] = cubic_coeff(abs(u-3), a); for (int s = 0; s < 4; s++)    { float C = cubic_coeff(abs(v-s), a); coeff[s*4] = A[0]*C; coeff[s*4+1] = A[1]*C; coeff[s*4+2] = A[2]*C; coeff[s*4+3] = A[3]*C; }}

最后,是双三次插值代码:

uchar cubic_inner(Mat A, float x_float, float y_float, float a){ float coeff[16]; cal_cubic_coeff(x_float, y_float, coeff); //计算权重系数 float sum = 0.0; int x0 = floor(x_float) - 1;   int y0 = floor(y_float) - 1;    for(int i = 0; i < 4; i++) {      for(int j = 0; j < 4; j++) {           sum += coeff[i*4+j]*A.ptr<uchar>(y0+i)[x0+j]; } } uchar inner_value = (uchar)sum;   return inner_value;}

从插值效果来说:双三次插值>双线性插值>最邻近插值,从计算复杂度来说,同样是:双三次插值>双线性插值>最邻近插值。所以实际使用时,根据自己的需要选择合适的插值算法。

欢迎扫码关注以下微信公众号,接下来会不定时更新更加精彩的内容噢~

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。