图像插值算法及其实现
sensor、codec、display device都是基于pixel的 , 高分辨率图像能呈现更多的detail , 由于sensor制造和chip的限制 , 我们需要用到图像插值(scaler/resize)技术 , 这种方法代价小 , 使用方便 。 同时 , 该技术还可以放大用户希望看到的感兴趣区域 。 图像缩放算法往往基于插值实现 , 常见的图像插值算法包括最近邻插值(Nearest-neighbor)、双线性插值(Bilinear)、双立方插值(bicubic)、lanczos插值、方向插值(Edge-directed interpolation)、example-based插值、深度学习等算法 。
插值缩放的原理是基于目标分辨率中的点 , 将其按照缩放关系对应到源图像中 , 寻找源图像中的点(不一定是整像素点) , 然后通过源图像中的相关点插值得到目标点 。 本篇文章 , 我们介绍Nearest-neighbor和Bilinear插值的原理及C实现 。
【图像插值算法及其实现】插值算法原理如下:
文章插图
1. Nearest-neighbor最近邻插值 , 是指将目标图像中的点 , 对应到源图像中后 , 找到最相邻的整数点 , 作为插值后的输出 。 如下图所示 , P为目标图像对应到源图像中的点 , Q11、Q12、Q21、Q22是P点周围4个整数点 , Q12与P离的最近 , 因此P点的值等于Q12
文章插图
的值 。 这里写图片描述由于图像中像素具有邻域相关性 , 因此 , 用这种拷贝的方法会产生明显的锯齿 。
2. Bilinear双线性插值使用周围4个点插值得到输出 , 双线性插值 , 是指在xy方法上 , 都是基于线性距离来插值的 。
如图1 , 目标图像中的一点对应到源图像中点P(x,y) , 我们先在x方向插值:
文章插图
然后 , 进行y方向插值:
文章插图
可以验证 , 先进行y方向插值再进行x方向插值 , 结果也是一样的 。 值得一提的是 , 双线性插值在单个方向上是线性的 , 但对整幅图像来说是非线性的 。
3. C实现使用VS2010 , 工程包含三个文件 , 如下:
文章插图
main.cpp
#include #include
resize.cpp
#include "resize.h"int clip3(int data, int min, int max){ return (data > max) ? max : ((data < min) ? min : data); if(data > max)return max; else if(data > min)return data; elsereturn min;}//bilinear takes 4 pixels (2×2) into account/** 函数名: bilinearHorScaler* 说明: 水平方向双线性插值* 参数:*/void bilinearHorScaler(int *src_image, int *dst_image, int src_width, int src_height, int dst_width, int dst_height){ double resizeX = (double)dst_width / src_width; for(int ver = 0; ver < dst_height; ++ver){for(int hor = 0; hor < dst_width; ++hor){double srcCoorX = hor / resizeX;double weight1 = srcCoorX - (double)((int)srcCoorX);double weight2 = (double)((int)(srcCoorX + 1)) - srcCoorX;double dstValue = http://kandian.youth.cn/index/*(src_image + src_width * ver + clip3((int)srcCoorX, 0, src_width - 1)) * weight2 + *(src_image + src_width * ver + clip3((int)(srcCoorX + 1), 0, src_width - 1)) * weight1;*(dst_image + dst_width * ver + hor) = clip3((uint8)dstValue, 0, 255);} }}/** 函数名: bilinearVerScaler* 说明: 垂直方向双线性插值* 参数:*/void bilinearVerScaler(int *src_image, int *dst_image, int src_width, int src_height, int dst_width, int dst_height){ double resizeY = (double)dst_height / src_height; for(int ver = 0; ver < dst_height; ++ver){for(int hor = 0; hor < dst_width; ++hor){double srcCoorY = ver / resizeY;double weight1 = srcCoorY - (double)((int)srcCoorY);double weight2 = (double)((int)(srcCoorY + 1)) - srcCoorY;double dstValue = *(src_image + src_width * clip3((int)srcCoorY, 0, src_height - 1) + hor) * weight2 + *(src_image + src_width * clip3((int)(srcCoorY + 1), 0, src_height - 1) + hor) * weight1;*(dst_image + dst_width * ver + hor) = clip3((uint8)dstValue, 0, 255);} }}/** 函数名: yuv420p_NearestScaler* 说明: 最近邻插值* 参数:*/void nearestScaler(int *src_image, int *dst_image, int src_width, int src_height, int dst_width, int dst_height){ double resizeX = (double)dst_width /src_width;//水平缩放系数 double resizeY = (double)dst_height / src_height;//垂直缩放系数 int srcX = 0; int srcY = 0; for(int ver = 0; ver
- 逛逛|淘宝内容化再升级:“买家秀”变身“逛逛”试图冲破算法局限
- 算法|【远见】个人信息保护法将出台 揭开数据算法的神秘“面纱”
- 算法|为什么长视频没有强算法推荐的产品
- 第二张“幻影”图像可能使特斯拉的自动驾驶仪蒙上阴影
- 数据结构与算法系列 - 深度优先和广度优先
- 快速概览 + 详细了解N:N聚类算法是如何应用的
- GitHub 热榜:《去你丫的算法》开放电子书下载
- 「远见」个人信息保护法将出台 揭开数据算法的神秘“面纱”
- 梯度直方图(HOG)用于图像多分类和图像推荐
- 随机森林(Random Forest)算法原理