双线性插值算法公式分析及FPGA实现初步构架-FPGA常见问题社区-FPGA CPLD-ChipDebug

双线性插值算法公式分析及FPGA实现初步构架

一、双线性插值概述

     双线性插值作为OpenCV中默认使用的图像缩放算法,其效果和速度都是不错的。并且效果也比较稳定,计算复杂度并不算太高。我看了很多网上的算法,自己也没看太懂,下面是从网上找的双线性插值 算法的讲解。

  “图像的双线性插值放大算法中,目标图像中新创造的象素值,是由源图像位置在它附近的2*2区域4个邻近象素的值通过加权平均计算得出的。双线性内插值算法放大后的图像质量较高,不会出现像素值不连续的的情况。然而此算法具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。”

二、双线性插值与最近邻插值对比

  双线性插值算法和最近邻插值算法比较类似。在最近邻插值算法中,目标图像中的某个点(x,y)是去源图像中找最邻近的一个点(x0, y0)即可。目标图像中的点(x, y)对应于源图像中的点(x0′,y0′),x0’、y0’很可能不是整数,而是小数,而最近邻插值算法是找其邻近整型值(int(x0’+0.5f),int(y0’+0.5f))(四舍五入处理)。

    在双线性插值中,我们现在找x0′, y0’所在位置旁边的四个点,再根据这四个点与(x0′,y0′)距离的关系得到权重值,最后计算出目标图像中(x,y)一点的像素值。

三、双线性插值算法实现

算法描述如下:

(1)计算源图像与目标图像宽与高的比例

w0 : 表示源图像的宽度

h0 : 表示源图像的高度

w1 : 表示目标图像的宽度

h1 : 表示目标图像的高度

float fw = float(w0-1)/(w1-1);  //在FPGA实现中一般会进行四舍五入取整操作

float fh = float(h0-1)/(h1-1);

(2)针对目标图像的一个点(x, y),计算在源图像中的对应坐标,结果为浮点数。

float x0 = x * fw;

float y0 = y * fh;

int x1 = int(x0);  //取整处理

int x2 = x1 + 1;

int y1 = int(y0);

int y2 = y1+1;

所求的源图像中的四个点坐标为(x1, y1) (x1, y2) (x2, y1) (x2,y2)

(3)求周围四个点所占的权重比值

如上图,

fx1 = x0 – x1;

fx2 = 1.0f – fx1;

fy1 = y0 – y1; 

fy2 = 1.0f – fy1;

float s1 = fx1*fy1;

float s2 = fx2*fy1;

float s3 = fx2*fy2;

float s4 = fx1*fy2;

我们以value(坐标)来代表取得此点的坐标值,则:

value(x0,y0) = value(x2,y2)*s1+value(x1,y2)*s2+value(x1,y1)*s3+value(x2,y1)*s4;

如果 对上述运算不够明白 的话,可以这样来求。

我们先要求得(x0, y1) 和(x0,y2)的像素值。

则float value(x0,y1) = value(x1,y1)*fx2 + value(x2,y1)*fx1;

float value(x0,y2) = value(x1,y2)*fx2 + value(x2,y2)*fx1;

注释:离某点越近,离权重越大,故取其与1的差值。

float value(x0,y0) = value(x0,y1)*fy2 + value(x0,y2)*fy1;

验证后与上边公式一样。

(4)求得值后填充到目标图像上就可以了。

我的理解:算法概念理解相对容易,但是如何在FPGA上实现却需要考虑一些问题,在此提出大体构架,日后再具体实现

1、算法中的浮点数运算,能否简单的用四舍五入取整处理代替?

2、输入的数据可以先缓存到两块RAM内,RAM0和RAM1进行乒乓操作,

     当RAM0缓存满一行数据时,算法模块可以读取RAM0数据进行操作,

     同时,RAM1缓存第二行数据。

3、在操作过程中,单独的一行一行处理只能实现线性插值,也就是输出数据只跟一行输入数据有关,如何实现4个临近像素相关?

4、基于问题3,现有参考代码是先进行垂直插值再进行水平插值,垂直插值输出像素值和垂直插值权重,再将其作为输入,进行水平

     线性插值运算,最终得到目标点像素值。

5、插值后的数据就可以进行后续操作最终输出到HDMI

请登录后发表评论

    没有回复内容