快速双线性插值

本文介绍了快速双线性插值在图像缩放中的应用,特别是针对单通道8位灰度图像。通过使用可分离方式处理行和列、构建缓冲区减少重复计算以及利用整形运算替代浮点运算,实现了性能提升。代码中采用了四次展开循环来进一步加速运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

图像缩放是最常用的图像操作,最近实现了一次双线性插值,适用于单通道8位灰度图像,可以同时处理缩小,放大。

加速手段有三个:1) 使用可分离方式,先后处理行和列,  2)构建缓冲区,以避免对某些行重复插值。3) 使用整形运算,避免浮点运算。

代码

typedef struct _Image{
    int w;
    int h;
    int c;
    int step;
    int type;
    void* data;
} Image;
 
static void _ieInterpImageBilinear8UC1_RowFilter(unsigned char* src, long* dst, int len, int* leftIdx, int* rightIdx, long* weight, int shift)
{
    int i, j;
    for(i = 0, j = 1; i < len - 2; i+=2, j+=2){
        dst[i] = ((1<<shift) - weight[i])*src[leftIdx[i]] + weight[i]*src[rightIdx[i]];
        dst[j] = ((1<<shift) - weight[j])*src[leftIdx[j]] + weight[j]*src[rightIdx[j]];
 
    }
    for( ; j < len; j++){
        dst[j] = ((1<<shift) - weight[j])
双线性插值是一种图像处理算法,用于在图像缩放或变形时增强视觉效果。在矩阵计算中,双线性插值可以通过以下步骤实现快速计算: 1. 假设有一张 m × n 的原始图像,需要将其缩放到 p × q 的目标大小。 2. 假设缩放比例为 rx = p/m 和 ry = q/n,即行和列分别缩放 rx 和 ry 倍。 3. 首先将原始图像按照行进行缩放,即按照 rx 的比例缩放每一行,得到一个 m×p 的中间图像。这可以通过将每一行看成一个向量,左乘一个 p×m 的行向量来实现,其中行向量的每一个元素都是 rx。 4. 然后按列进行缩放,即按照 ry 的比例缩放每一列,并对行缩放后的中间图像进行插值,得到最终的 p×q 的目标图像。这可以通过对中间图像的每一列看成一个向量,左乘一个 m×q 的列向量来实现,其中列向量的每一个元素都是 ry,并且采用双线性插值公式进行计算。 实际的计算可参考以下代码: def bilinear_interp(input, output_size): batch_size, channels, height, width = input.size() new_height, new_width = output_size # 计算行方向的插值 row_indices = torch.linspace(0, height - 1, new_height).unsqueeze(1).expand(new_height, new_width) floor_rows = torch.floor(row_indices) ceil_rows = torch.ceil(row_indices) row_weights = row_indices - floor_rows floor_rows = floor_rows.clamp(0, height - 1) ceil_rows = ceil_rows.clamp(0, height - 1) top_left = input.index_select(2, floor_rows.long()) top_right = input.index_select(2, ceil_rows.long()) # 计算列方向的插值 col_indices = torch.linspace(0, width - 1, new_width).unsqueeze(0).expand(new_height, new_width) floor_cols = torch.floor(col_indices) ceil_cols = torch.ceil(col_indices) col_weights = col_indices - floor_cols floor_cols = floor_cols.clamp(0, width - 1) ceil_cols = ceil_cols.clamp(0, width - 1) top_left = top_left.index_select(3, floor_cols.long()) top_right = top_right.index_select(3, ceil_cols.long()) # 进行双线性插值 top_weights = (1 - row_weights) * (1 - col_weights) top_left *= top_weights.unsqueeze(dim=1) bottom_weights = row_weights * (1 - col_weights) bottom_left = input.index_select(2, ceil_rows.long()) bottom_left *= bottom_weights.unsqueeze(dim=1) left_weights = (1 - row_weights) * col_weights top_right *= left_weights.unsqueeze(dim=1) right_weights = row_weights * col_weights bottom_right = input.index_select(2, ceil_rows.long()) bottom_right = bottom_right.index_select(3, ceil_cols.long()) bottom_right *= right_weights.unsqueeze(dim=1) output = top_left + bottom_left + top_right + bottom_right return output
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值