首页 > 编程知识 正文

bilinear函数用法

时间:2023-05-05 10:26:49 阅读:184867 作者:1169

by chuckGao 2009

最近在研究对视频流放大播放时进行图形缩放的bilinear和bicubic算法。这里给出最近一个项目中对图像进行2倍放大的算法。而对于算法的优化,可以考虑用建立缩放映射表的方法。

bilinear算法:

int bilinear_scale

(long newx,

long newy,

unsigned long oldBytesperline,

unsigned long newBytesperline,

int format,

unsigned char* newImage,

Image image)

{

unsigned char* ptr;

if (newx==0 || newy==0){

return SIZE_ERROR;

}

if (image.width==newx && image.height==newy){

newImage = image.bits;

return NOT_TRANS;

}

float xScale, yScale, fX, fY;

xScale = (float)0.5;

yScale = (float)0.5;

long ifX, ifY, ifX1, ifY1, xmax, ymax;

float ir1, ir2, ig1, ig2, ib1, ib2, dx, dy;

unsigned char r,g,b;

scale_RGBQUAD rgb1, rgb2, rgb3, rgb4;

xmax = image.width-1;

ymax = image.width-1;

for(long y=0; ywidth,修改使程序减少for跨层计算*/

fY = y * yScale;

ifY = (int)fY;

ifY1 = min(ymax, ifY+1);

dy = fY - ifY;

for(long x=0; x

fX = x * xScale;

ifX = (int)fX;

ifX1 = min(xmax, ifX+1);

dx = fX - ifX;

// Interpolate using the four nearest pixels in the source

unsigned char* ptr;

ptr = image.bits + ifY*oldBytesperline + ifX*format;

rgb1.rgbRed = *ptr++;

rgb1.rgbGreen= *ptr++;

rgb1.rgbBlue =*ptr;

ptr = image.bits + ifY*oldBytesperline + ifX1*format;

rgb2.rgbRed = *ptr++;

rgb2.rgbGreen= *ptr++;

rgb2.rgbBlue =*ptr;

ptr = image.bits + ifY1*oldBytesperline + ifX*format;

rgb3.rgbRed = *ptr++;

rgb3.rgbGreen= *ptr++;

rgb3.rgbBlue =*ptr;

ptr = image.bits + ifY1*oldBytesperline + ifX1*format;

rgb4.rgbRed = *ptr++;

rgb4.rgbGreen= *ptr++;

rgb4.rgbBlue =*ptr;

// Interplate in x direction:

ir1 = rgb1.rgbRed   + (rgb3.rgbRed   - rgb1.rgbRed)   * dy;

ig1 = rgb1.rgbGreen + (rgb3.rgbGreen - rgb1.rgbGreen) * dy;

ib1 = rgb1.rgbBlue  + (rgb3.rgbBlue  - rgb1.rgbBlue)  * dy;

ir2 = rgb2.rgbRed   + (rgb4.rgbRed   - rgb2.rgbRed)   * dy;

ig2 = rgb2.rgbGreen + (rgb4.rgbGreen - rgb2.rgbGreen) * dy;

ib2 = rgb2.rgbBlue  + (rgb4.rgbBlue  - rgb2.rgbBlue)  * dy;

// Interpolate in y:

r = (unsigned char)(ir1 + (ir2-ir1) * dx);

g = (unsigned char)(ig1 + (ig2-ig1) * dx);

b = (unsigned char)(ib1 + (ib2-ib1) * dx);

// Set output

ptr = newImage + y*newBytesperline + x*format;

*ptr++ = (unsigned char)r;

*ptr++ = (unsigned char)g;

*ptr   = (unsigned char)b;

}

}

return 0;

}

bicubic算法:

int bicubic_scale

(long newx,

long newy,

unsigned long oldBytesperline,

unsigned long newBytesperline,

int format,

unsigned char* newImage,

Image image)

{

unsigned char* ptr;

if (newx==0 || newy==0){

return SIZE_ERROR;

}

if (image.width==newx && image.height==newy){

return NOT_TRANS;

}

float xScale, yScale, fX, fY;

xScale = (float)0.5;

yScale = (float)0.5;

// bicubic interpolation by chuckGao

float f_x, f_y, a, b, rr, gg, bb, r1, r2;

int   i_x, i_y, xx, yy;

scale_RGBQUAD rgb;

for(long y=0; y

f_y = (float) y * yScale - 0.5f;

i_y = (int) floor(f_y);

a   = f_y - (float)floor(f_y);

for(long x=0; x

f_x = (float) x * xScale - 0.5f;

i_x = (int) floor(f_x);

b   = f_x - (float)floor(f_x);

rr = gg = bb = 0.0f;

for(int m=-1; m<3; m++) {

r1 = kernelBSpline((float) m - a);

yy = i_y+m;

if (yy<0) yy=0;

if (yy>=image.height) yy = image.height-1;

for(int n=-1; n<3; n++) {

r2 = r1 * kernelBSpline(b - (float)n);

xx = i_x+n;

if (xx<0) xx=0;

if (xx>=image.width){

xx=image.width-1;

}

ptr  = image.bits + yy*oldBytesperline + xx*format;

rgb.rgbRed = *ptr++;

rgb.rgbGreen= *ptr++;

rgb.rgbBlue  = *ptr;

rr += rgb.rgbRed * r2;

gg += rgb.rgbGreen * r2;

bb += rgb.rgbBlue * r2;

}

}

ptr = newImage + y*newBytesperline + x*format;

*ptr++ = (unsigned char)rr;

*ptr++ = (unsigned char)gg;

*ptr   = (unsigned char)bb;

}

}

return 0;

}

float kernelBSpline(const float x)

{

if (x>2.0f) return 0.0f;

// thanks to Kristian Kratzenstein

float a, b, c, d;

float xm1 = x - 1.0f; // Was calculatet anyway cause the "if((x-1.0f) < 0)"

float xp1 = x + 1.0f;

float xp2 = x + 2.0f;

if ((xp2) <= 0.0f) a = 0.0f; else a = xp2*xp2*xp2; // Only float, not float -> double -> float

if ((xp1) <= 0.0f) b = 0.0f; else b = xp1*xp1*xp1;

if (x <= 0) c = 0.0f; else c = x*x*x;

if ((xm1) <= 0.0f) d = 0.0f; else d = xm1*xm1*xm1;

return (0.16666666666666666667f * (a - (4.0f * b) + (6.0f * c) - (4.0f * d)));

}

在windows上用QT写了一个opencv的视频采集程序,今天测试的结果为:

1.对于640x480放大到1280x960,采用bicubic算法,fps = 1 or 2,采用bilinear算法,fps为6,而不进行缩放的图像播放fps为12

2.预计改换显示大小为320x240,放大到640x480时fps有所增强

3.这里的fps值只是近似得到,并不绝对,只能进行相对比较

(9月22日补充)

对于图像缩放算法的优化,在很大程度上是对其运算速度进行c语言级甚至是汇编级的优化。首先要做c语言级的优化,一般采用两种方法:

1.运算流程的优化,尽量减少跨层计算

2.以空间换时间,牺牲内存空间以加快计算速度

在基本清楚优化原则的前提下,也要对如下概念有清楚的认识:

1.算法中涉及到的int、long、short(包括unsigned)以及float、double等数值类型的掌握。要知道,对于图像缩放后精度的控制,必须清楚的知道计算时这些类型数据的情况,比如在对float类型数据(假设变量名为rgb)赋值时:

float rgb = 0.5 和float rgb = 0.5f在精度上就有所差异,前者自动转换类型为double型,64位数据,而后者为float 32位

2.在32-bit计算机中,long和int的size一般是相等的,即占4bytes,32位。但计算时,特别在malloc时,还是应慎重使用sizeof(long)来确定其大小

3.抛开算法本身不谈,计算中数据类型为unsigned char的运算肯定比float的快,但精确度肯定不如后者。在实际编程中的取舍可以根据图像显示效果和速度来决定

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