目录
一、问题描述
我们在处理图像的时候常常会遇到图像放大的问题,那么选择什么样的图像放大算法,能有什么样的效果,就是我们比较关心的问题了。最近(其实是很久以前),我根据网上大神们,关于双线性内插算法的资料,总结了一个用于图像缩放的算法的代码,我把它总结在博客里,希望能够方便自己和大家随时的使用。
二、算法原理
首先要介绍一下双线性内插算法的基本原理,这部分转载自 GoldBeetle 大佬的博客
https://www.cnblogs.com/GoldBeetle/archive/2018/09/17/9662871.html
双线性内插法
v(x,y) = ax + by + cxy + d
双线性内插法参数计算
已知Q11, Q12, Q21, Q22,要插值的点为P点,首先在x轴上,对R1,R2两个点进行插值
然后根据R1和R2对P点进行插值
化简得
对于边界值的处理,若x1 < 0 ,则直接令f(Q11), f(Q12) = 0
三、算法效果
这个算法期初被我用在了Qt的图像处理中,后来被我移植到了ESP8266的LCD屏幕驱动中,还是比较好用的,下面我先展示一下再Qt中放大的效果。
基于此算法,我为了方便只使用了灰度值进行数据处理,效果就是如图所示,当然也可以分为多个通道处理彩色图像。
后来我又修改此算法处理二值图像,用在ESP8266中作为文字的放大函数,使用小字库就可以在LCD屏幕上显示任意大的字体,也是非常方便的,节省了超大字体的字符所占用的空间。
四、算法代码
接下来我将代码展示一下,
输入参数分别是 输入图像的数组指针,输入图像的大小,输出图像指针,输出图像大小。
int offset_x=0,offset_y=0;
#define gray_to_RGB(gray) qRgb(gray,gray,gray)
void Bilinear(uint8_t* inpBmpBuf, int src_x,int src_y,uint8_t* outpBmpBuf,int dstWidth,int dstHeight)
{
double lx=1,ly=1;//缩小倍数
if(src_x/dstWidth>1) {lx=src_x/(double)dstWidth;}
else{lx=src_x/(double)dstWidth;}
if(src_y/dstHeight>1){ly=src_y/(double)dstHeight;}
else{ly=src_y/(double)dstHeight;}
int x1, x2, y1, y2, Fq11, Fq12, Fq21, Fq22;
double x, y, r1, Fr1, Fr2, Fp;
for (int i = 0; i < dstHeight; ++i){
for (int j = 0; j < dstWidth; ++j){
x = lx*j; // 原图像坐标
y = ly*i;
// 四个坐标值
x1 = floor(x); x2 = x1 + 1;// 取整ceil向上,floor向下
y1 = floor(y); y2 = y1 + 1;
// 四个坐标对应的灰度值
Fq11 = inpBmpBuf[x1*src_y+y1] ;
Fq12 = inpBmpBuf[x1*src_y+y2];
Fq21 = inpBmpBuf[x2*src_y+y1];
Fq22 = inpBmpBuf[x2*src_y+y2];
// x方向插值和y方向插值
Fr1 = 0; Fr2 = 0;
Fr1 = (x2 - x) / (x2 - x1)*Fq11 + (x - x1) / (x2 - x1)*Fq21;
Fr2 = (x2 - x) / (x2 - x1)*Fq12 + (x - x1) / (x2 - x1)*Fq22;
Fp = (y2 - y) / (y2 - y1)*Fr1 + (y - y1) / (y2 - y1)*Fr2;
// 新图像灰度值赋值
if (Fp >= 0 && Fp <= 255){
outpBmpBuf[i+j*dstHeight]=round(Fp); // 新图像
}
}
}
//将计算得到的像素值放入图像画布
for(int i=0;i<dstWidth && i<Show_image.size().width();i++)
{
for(int j=0;j<dstHeight && j<Show_image.size().height();j++)
{
Show_image.setPixel(i,j,gray_to_RGB(outpBmpBuf[(i+offset_x)*dstHeight+(j+offset_y)]));
}
}
}
今天的总结就到这里啦,欢迎大家给我点赞关注、与我交流讨论呀。O(∩_∩)O哈哈~