亚像素图像
大家有没有你想过,在软件层面,如何提高图像处理的精度?比如,我们要用图像处理测量工业零件的周长,怎么在不改变硬件条件的情况下尽可能得到更高的精度?
我们平时看到的图像都是由像素点组成的,不知道大家有没有思考过,相邻像素点之间像素值大小跳变太大的问题?
为了方便理解,这里举个稍微离谱一点的例子
将一张实际大小为 8cm x 8cm 的图片通过计算机转换为一张 4 x 4 个像素点的图像,那么每个像素点能够代表的是实际图片中 2cm x 2cm 大小的区域。如果在真实情况下,像素点取这么大的话,得到的实际图像就会变得十分模糊。因为每一个像素点只能有一个像素值,这就意味着下图所示的 2cm x 2cm 的区域中都只能是同一种颜色,这样显然是无法表现出图像特征的。
因此,我们就需要使用更好的感光元件,将图像分割成更多像素点,使得每个像素点内像素值的方差不至于过大,这样让图像看起来更加清晰。
那么,在图像处理中,要在软件层面提高精度,就可以选择那像素点来做文章,于是便可以引出亚像素的概念。顾名思义,在原有的像素点之间添加新的像素点,使得图像的像素点变多,得到的图像就被称为亚像素图像。这些新增的像素点并非通过外界获取,而是通过对原有像素点进行一些数学操作得到的。
如上图所示便是亚像素图像,通过一些数学手段(如插值、拟合等)在原有像素点(黑点)之间天界新像素点(红点),这样就能增加图像的分辨率,在一定程度上提高精度。
本文要介绍的是利用双线性插值获取亚像素图像的方法,这种方法计算量较大,计算时间较长,不适用于实时分析。但是,该方法可以有效提对高对图像测量的精度。
双线性插值法理论
双线性插值,如下图所示,先在Q11和Q21之间做线性插值,求中点的像素值R1,同理求出R2,然后在R1和R2之间求插值,就可以得到需要新增的像素点P。
像素值的计算方法如下,有一点点数学基础的同学就能看明白什么意思,其实说白了就是在两点的连线上取中点,多取几次。
{
f
(
x
,
y
1
)
≈
x
2
−
x
x
2
−
x
1
f
(
x
1
,
y
1
)
+
x
−
x
1
x
2
−
x
1
f
(
x
2
,
y
1
)
f
(
x
,
y
1
)
≈
x
2
−
x
x
2
−
x
1
f
(
x
1
,
y
2
)
+
x
−
x
1
x
2
−
x
1
f
(
x
2
,
y
2
)
\begin{cases} f(x,y_{1}) \approx \frac{x_{2} - x}{x_{2} - x_{1}}f(x_{1},y_{1}) + \frac{x - x_1}{x_{2} - x_{1}}f(x_{2},y_{1})\\ f(x,y_{1}) \approx \frac{x_{2} - x}{x_{2} - x_{1}}f(x_{1},y_{2}) + \frac{x - x_1}{x_{2} - x_{1}}f(x_{2},y_{2}) \end{cases}
{f(x,y1)≈x2−x1x2−xf(x1,y1)+x2−x1x−x1f(x2,y1)f(x,y1)≈x2−x1x2−xf(x1,y2)+x2−x1x−x1f(x2,y2)
最终整合成求P点像素值的公式如下
f
(
x
,
y
)
≈
y
2
−
y
y
2
−
y
1
f
(
x
,
y
1
)
+
y
−
y
1
y
2
−
y
1
f
(
x
,
y
2
)
f(x,y) \approx \frac{y_2 - y}{y_2 - y_1}f(x, y_1) + \frac{ y - y_1}{y_2 - y_1} f(x, y_2)
f(x,y)≈y2−y1y2−yf(x,y1)+y2−y1y−y1f(x,y2)
基于上述公式,可以求得
以上,Q为原有图像的像素点,P为插值得到的像素点,f表示的是像素的值。
代码实践
%% 图像读取和基本参数设置
I = "图像路径"; % I 为输入的图像
gain = 2; % 亚像素图像相对原图像的放大倍数
[I,M] = imread(I);
%% 亚像素图像初始化
[IH,IW,ID] = size(I);
GIH = round(IH*gain);
GIW = round(IW*gain);
GI = zeros(GIH,GIW,ID); % 先开一个放大后大小的矩阵
%% 像素预处理
IPRE = zeros(IH+2,IW+2,ID);
IPRE(2:IH+1,2:IW+1,:) = I; % 在原图像边缘多填充一个像素
% 为填充出来的像素赋值
IPRE(1,2:IW+1,:)=I(1,:,:);
IPRE(IH+2,2:IW+1,:)=I(IH,:,:);
IPRE(2:IH+1,1,:)=I(:,1,:);
IPRE(2:IH+1,IW+2,:)=I(:,IW,:);
IPRE(1,1,:) = I(1,1,:);
IPRE(1,IW+2,:) = I(1,IW,:);
IPRE(IH+2,1,:) = I(IH,1,:);
IPRE(IH+2,IW+2,:) = I(IH,IW,:);
%% 亚像素图像像素值计算
for gj = 1:GIW % 对图像进行按列逐元素扫描
for gi = 1:GIH
i = floor(ii); j = floor(jj); % 向下取整
% 新增点的坐标
u = (gi-1)/gain - i;
v = (gj-1)/gain - j;
i = i + 1; j = j + 1; % 更新
% 根据上述公式计算亚像素值
GI(gi,gj,:) = (1-u)*(1-v)*IPRE(i,j,:) +(1-u)*v*IPRE(i,j+1,:)...
+ u*(1-v)*IPRE(i+1,j,:) +u*v*IPRE(i+1,j+1,:);
end
end
%% 输出
GI = uint8(GI); % 输出图像
小结
实际测量时,需结合相机标定或其他能够获取深度信息的方法(如结构光、TOF、双目摄像机)进行使用。先对捕获到的图像亚像素化,然后再测量像素值,最后通过一定的方法换算成实际测量值。
利用亚像素图像进行测量,虽然能够提高测量精度,但仅有软件算法还是具有比较大的局限性,需要选择适当且合适的应用场景。