计算机视觉

CV1 introduction

1.1图像表示

图像文件格式

  • Vector images向量表示(.ai,.eps,.ps)
    • 这种格式优点是在缩放时没有混叠和模糊
    • 然鹅难以获得,在实际应用中有限。
  • Bitmap位图:用比特位表示图像状态。
    • 容易实现,应用广泛
    • 通过光栅化将vector转换为位图。
    • 缺点是在缩放时会变的模糊和锯齿化。
  • GIF(Graphic Interchange Format)
    • 以8位色(即256种颜色)重现真彩色的图像。它实际上是一种压缩文档,采用LZW压缩算法进行编码。
    • 可以选择抖动–(将混合两种不同可用颜色的像素以创建另一种颜色的建议)
    • 可以用于实现动画、透明效果。
  • JPEG(Joint Photographic Experts Group)
    • 16位,在不需要dithering(抖动)的情况下能够同时显示数百万种颜色。
    • 大约 60% 的压缩设置将导致质量和文件大小的最佳平衡。(低于60%的压缩强度保留的图像效果比较好)
  • PNG(Portable Network Graphics)
    • 基于ZIP的无损压缩
    • 可以是透明的,(4通道图像,可以设置透明度)
  • BMP(Windows Bitmap)
    • 简单,未压缩
    • 可以索引,也可以不索引
    • DIB(Device Independent Bitmap)/ DDB(Device dependent bitmap)

图像表示(Bitmap)

image

可以表示为定义在2维空间上的函数,f(x,y)

image-iyws.png

数字图像

  • x,y,f(x,y)仅取离散的值,由有限的基本元素组成。
  • 图像的基本元素称为像素。
  • 数字图像由像素组成

image-nlzv.png

image-vgls.png

内存里的图像

2D or 3D array

交叉存储&顺序存储

image-tqpe.png

图像像素在内存中的保存方式

像素值以矩阵方式保存,矩阵的大小取决于图像采用的颜色模型。如果是灰度图,那么图像就是单通道的,图像中的每一个像素只需要一个矩阵元素来保存,一般就是0~255的值。

如果是彩色图,那么图像就是多通道的,一个像素需要多个矩阵元素来保存,可以采用交叉存储也可以采用顺序存储的方式。

交叉存储中,一个像素需要多列来进行存放,通常通道数为步长来访问取得一个像素。顺序存储中将像素的不同通道按顺序分别存放。

图像在内存中的大小取决于图像的分辨率dpi、宽高尺寸、像素的数量。(分辨率是单位面积的像素数量,通常单位为dpi或ppi,图像的清晰度不仅取决于像素数量,还与像素的点密度有关。分辨率高的图片能显示更多信息,画面更精细)。

颜色空间(RGB、CMYK,YUV、Lab,……)

图像通道(1,2,3,4,gray&color)

Bit Depth(number of bits for each channel,&bits)

Coordinate system:左手系和右手系。

image-vkge.png

程序里的图像

struct MyImage
{
     int   	width, height;   // 大小
     int   	type;	        // 类型,含通道数、位深度信息
		        /* CV_8UC3 	:   unsigned char [3]
		           CV_32SC1	:   int [1]
                   CV_32UC1 :   uint [1]
                   CV_32FC4	:   float [4]
                  */

     void*	data;	       // 图像数据
     int  step;	       // 步长(每行所占用的字节数)
};

封装在图像处理程序库中。

type标识了不同的图像类型(CV_8UC3……):
CV_<bit_depth>(S|U|F)C<number_of_channels)
其中(1)bit_depth:图像深度(位数),代表8、16、32、64位。(2)S|U|F: S(signed int,有符号整型),U(unsigned int,无符号整型)F(float,单精度浮点型)。(3)C<number_of_channels>所存储图片的通道数。

  1. GRAYIMG,灰度图像,单通道图像。
  2. 二值图像,2通道图像,用于图像压缩,傅里叶变化。
  3. RGB,彩色图像,3通道图像。(.jpg)
  4. 带Alpha通道的RGB彩色图像,为4通道图像。(.png)

data是存放的图像数据(严谨地说是指针),步长是每行所占用的字节数。

步长(step?stride?)

为了数据对齐,是的每一行数据的地址都从4、8或16的整数倍开始,而步长就是每行所占用的字节数。

为了表示图像的子区域(ROI)

1.2 如何获取像素?

get_pixel

  • img_type=CV_8UC3:8位无符号、3通道数据
uchar*  get_pixel(const MyImage &img, int x, int y)
{
       //  return (uchar*)img.data+y*img.width*3+x*3;

        return (uchar*)img.data+y*img.step+x*3;
      //note: step!=width*channels
}
  • img_type=CV_32SC3:32位带符号、3通道数据
int*  get_pixel(const MyImage &img, int x, int y)
{
       //  return (int*)((char*)img.data+y*img.width*4+x*3*4);

        return (int*)((char*)img.data+y*img.step+x*3*4);
}

注意:step是一行所占的字节数,数值上不等于图像宽度乘以通道数:

CV_8UC3表示图像的像素由3通道表示,每个通道用8位无符号表示,即char,也就是1个字节,那么每个像素占3个字节,所以先由data+y*step得到对应的行所在的起始地址,再加上x方向的偏移量,也就是x*3.

类似的CV_32SC3,图像仍然是3通道,但是每个通道由32位有符号数据表示,即int,4个字节,所以一个像素占3*4个字节,所以x方向上的偏移量应该是x*3*4.

step始终是字节数!

所以正确的应该是step = width*channels*sizeof(dataType)

Scan Pixels

void scan_pixels(uchar *data, int width, int height, int step, int nc)
{
    //遍历图像的每一个像素
    //调用get_pixel函数即可
    //这里的height,width不一定是图像的原始尺寸
    for(int i=0;i<width;i++){
        for(int j=0;j<height;j++){
            auto pixel = get_pixel(data,i,j);
        }
    }
}

Scan Pixel in ROI

ROI是图像的一个子区域,遍历ROI中的像素是需要获取得到ROI区域的起始地址,然后调用scan_pixels即可

void scan_roi_pixels(MyImage &img, int x, int y, int roi_width, int roi_height)
{// 通道数nc=img.nc();
    scan_pixels( get_pixel(img, x, y),  roi_width, roi_height, img.step, img.nc() );
}

scan_pixels不需要做任何修改即可适配scan_roi_pixels,因为即便data是ROI区域的起始地址,data+y*step仍然会移动到与data同一列,然后加上x方向上的位移即可取到对应位置的像素。

CV2 Image Processing 1

如何描述一个像素?

  • 空间坐标(x,y)
  • 像素颜色(RGB,YUV,···)

像素(x,y,R,G,B)

2.1 基本的图像处理

  • 从空间坐标上进行处理(x,y):几何加工
  • 在像素颜色上进行处理(RGB,YUV):代数处理(计算像素通道数据)

代数运算:像素灰度变换(Gray Level Transformation)

像素灰度变换时最简单的图像处理任务,输入一张图像,输出处理后的图像。

灰度变换需要逐像素地进行处理,对每一个像素进行会的转换:

  • 亮度调整(Intensity Adjustment)
  • 对比度调整(Contrast Adjustment)
  • ···
L' = T(L),L、L' \in [0,255]
void scan_pixels(uchar *data, int width, int height, int step, int nc)
{
      uchar *row=data;
      for(int yi=0; yi<height; ++yi, row+=step)
      {
          uchar *px=row;
          for(int xi=0; xi<width; ++xi, px+=nc)
          {
               //逐像素进行处理
               // px now address the pixel  (xi, yi)
               //对px执行灰度转换即可
          }
      }
}

void gray_transform(uchar *data, int width, int height, int step,int nc)
{
      uchar *row=data;
      for(int yi=0; yi<height; ++yi, row+=step)
      {
          uchar *px=row;
          for(int xi=0; xi<width; ++xi, px++)
          {
               uchar L=*px;
               *px= Transform (L);//调用Transform函数
          }
      }
}


也可以通过查表的方式直接更改数值进行转换

void gray_transform(uchar *data, int width, int height, int step, const uchar T[256] )
{
      uchar *row=data;
      for(int yi=0; yi<height; ++yi, row+=step)
      {
          uchar *px=row;
          for(int xi=0; xi<width; ++xi, px++)
          {
        	*px= T[ *px ];
          }
      }
}

亮度调整:Other Functions

image-rvdy.png

变换函数

  • 对数变换

    • s = c*log(1+r)
    • c为常量
  • 幂律变换

    • s=c*r^\gamma
    • c,\gamma:都是正的常数
    • 通过调整\gamma来调整变换的程度

image-csfg.png

不同的γ对灰度的影响

image-pxsw.png

对比度调整

image-bwcf.png

image-sqgf.png

image-hcwy.png

对比度的调整就是调整处理图像的灰度的动态变化范围

image-fpoi.png

横坐标是原始图像的灰度,纵坐标是对应转换后的灰度

多图代数处理

输入多张大小相同的图像,输出与输入图像大小相同的图像。基于对应像素图像进行计算。

alpha图像混合

C=\alpha F + (1-\alpha)B

image-qzsf.png

抠图

图像合成的逆过程,由合成的结果C求出α。从图像中提取特定对象或区域(获取alpha map)

用C减去背景得到α

2.2 基本几何处理

翻转、缩放

基本的几何处理包括:翻转、旋转、缩放、变形、透视变换、仿射变换

  • 水平&垂直翻转(flip):左右或者上下翻转或者镜像处理
void vflip(const void *in, int width, int height, int istep,  int pix_size, void *out, int ostep)
{//垂直翻转
       out=(char*)out+(height-1)*ostep;
       for(int yi=0; yi<height; ++yi, in=(char*)in+istep, out=(char*)out-ostep)
       {//可以整行交换
            memcpy(out, in, width*pix_size);
        }
}

void hflip(const void *in, int width, int height, int istep,  int pix_size, void *out, int ostep)
{//水平翻转
       char * _in=(char*)in;
       char *_out=(char*)out+(width-1)*pix_size;//获取镜像位置的像素地址
  
       for(int yi=0; yi<height; ++yi, _in+=istep, _out+=ostep)
       {//两个指针一个向左移动,一个向右移动来完成镜像位置的像素的复制
        //逐像素进行交换
            char *in_x=_in, 
            char *out_x=_out;
             for(int xi=0; xi<width; ++xi, in_x+=px_size, out_x-=px_size)
                  memcpy(out_x, in_x, px_size) ;
        }
}


  • 缩放(resize/zoom in/zoom out/scale)

对于图像放大

放大处理的方案有两个:投影和查找

投影:对于小图中的每个像素,计算其对应在大图中的像素位置。

查找:对于大图中的每个像素,计算它对应在小图中的像素位置。

显然投影方案存在很多空隙,大图中的像素做不到都有小图中的像素对应,而查找方案可以让每个大图中的像素都有对应的小图像素对应。

如何解决浮点数坐标的像素颜色问题?计算得到的对应坐标可能是小数,这时候如何取得对应的像素值呢?

Resampling (重采样)

基于邻近像素的值,计算非整数位置上的颜色值。

  • 最近邻

    • 找到距离采样点最近的源像素,输出他的像素颜色。
    • x=int(x+0.5),y=int(y+0.5)
  • 双线性插值

    • 对浮点坐标周围的四个像素点,分别进行一次水平和垂直的一维线性插值。
    • 2次水平和1次垂直,与两次垂直一次水平是一样的效果。

image-lyxv.png

float bilinear(float a, float b, float c, float d, float dx, float dy)
{//双线性插值
//一次双线性插值最少需要3次乘法运算
       float  h1=a+dx*(b-a);           // = (1-dx)*a + dx*b
       float  h2=c+dx*(d-c);
       return h1+dy*(h2-h1);
}

双三次插值使用三次多项式完成插值任务,涉及采样像素点周围16个像素点image-eoqr.png

离散函数的导数

f'(x) = \frac{[f(x+1)-f(x)]+[f(x)-f(x-1)]}{2}
f'(x)=\frac{[f(x+1)-f(x-1)]}{2}

图像变换

旋转

image-nkxp.png

image-oerm.png

以任意坐标为旋转中心进行旋转,可以先将旋转中心平移到坐标原点,然后用旋转矩阵进行旋转,最后平移回原位置即可。

image-gubp.png

多个变换的复合可以表示为其变换矩阵的乘积。

image-cusz.png

仿射变换=线性变换+平移

线性变换满足:f(a+b)=f(a)+f(b),f(ka) = kf(a);

刚性变换

  • 只包含平移和旋转
  • 保持物体的形状(保角)和尺寸
  • 相当于正交变换

相似变换

  • 只包含平移、旋转和等比缩放
  • 保持物体的形状

投影变换

  • 仿射变换是在同一平面内部的变换
  • 投影变换可以表示不同视角观察到的同一个平面,或同一视角观察到的不同平面之间的变换。

应用:图像匹配

  • 基于仿射变换的图像匹配
    • 先计算从第t帧到第t+1帧的仿射变换A
    • 利用A对第t帧的图像进行变换,将变换的结果作为与第t+1帧配准的图像
  • 估计两幅图像之间的仿射变换?
    • 不共线的3个平面点对决定一个二维仿射变换

image-bzjd.png

大于3个点对则求解损失最小的变换矩阵A

image-jwcg.png

点对如何获得?

  • 通过特征点跟踪获得

图像变形

正向变形比较抽象,可以反向来逆向查找。

image-tnuw.png

image-nvyr.png

逆向查找的局限性?

image-sxod.png

正向变换如何实现?遍历每一个像素,计算像素在目标图像中的位置,设置目标图像的像素。

小结

  • 简述图像几何变换的两种方式:正向投射和逆向查找,并说明两种方式需要解决的问题。
    • 正向投射遍历源图像中的每个像素,计算目标图像中的位置,然后设置目标图像的像素值。需要解决离散化和间隙问题,由于目标图像中的像素位置是离散的,在投射过程中有部分像素没有被映射到目标图像中使得目标图像中产生间隙。覆盖和重叠的问题,源图像中的像素可能映射到目标图像的同一个位置,导致覆盖和重叠的问题,需要进行适当处理。插值问题,对产生的间隙和重叠进行插值。
    • 逆向查找遍历目标图像中的每一个像素,计算源图像中的位置,然后设置目标图像的像素值。逆向查找也有离散化和插值问题,目标图像的像素位置映射到源图像像素的位置可能是浮点类型,需要对像素值进行插值。边界问题,逆向查找过程中,有可能映射到源图像之外的位置,需要进行边界处理,如边缘扩展等。计算复杂度问题,逆向查找需要计算变换矩阵的逆矩阵,这增加了计算的复杂性,同时每个像素都选哟进行插值计算,导致计算效率比较低。
  • 双线性插值由于仅考虑最近的4个像素,结果图像的边缘往往较为锐利,容易产生锯齿;三次插值则考虑了更大范围的像素,使得插值结果更加平滑,因此在边缘处的过渡更加自然,减小了锯齿效应。
  • n已知两幅图像中的N个点对(p_i,q_i),i=1,…,N, N>3, 请简述求两幅图像之间符合这N个点对约束的仿射变换A的方法。

目标函数:

image-yxlg.png

CV3 空间滤波(Spatial Filtering)

Filter(过滤、过滤器、滤波器)

从混合物中提取特定的成分

图像的成分

不同尺度(频率)的内容、以及噪音、角点、边缘等

3.1 空间滤波

空间域滤波器

对任意的像素P

p'=f(N_p)N_p为像素P的某个领域的像素集合

image-vpso.png

  • 均值滤波器:f=avaerage
    • p'=\frac{1}{9}(p_0+p_1+...+p_8)
  • 最大值滤波器:f=max
    • p'=max(p_0,p_1,p_2,...p_8)

线性滤波器(Linear Filter)

邻域像素的加权平均

p'=\sum_{i=0}^{8}(w_i*p_i)

卷积形式

image-rfcc.png

w(s,t)为卷积核(kernel、mask、template)

非线性滤波

image-nwzl.png

平滑滤波(Smoothing Filter)

低通滤波:领域像素的加权平均,包括均值滤波、高斯滤波(卷积核的权重不一样),卷积核的尺寸越大,结果越模糊。

实现:均值滤波、高斯滤波

边界的处理:对边界附近的像素,滤波核的部分可能落在图像之外

image-cuui.png

  • 对边界外某个范围的区域进行填充(Padding)
    • 常数填充
    • 镜像填充,以边界为轴,取图像内对称点的像素值进行填充
  • 在边界附近调整滤波核的大小

3.2 积分图

图像I的积分图S是与其大小相同的图像,S的每一像素S(u,v)存贮的是I(u,v)左上角所有像素的颜色值之和。(2维前缀和)

积分图可以增量计算,只需要对原图进行一遍扫描

image-pbjq.png

void  integral_image(const  uchar *src, int width, int height, int sstride, int *pint, int istride)
{//求图像的积分图S
        int *prow=new int[width];

        memset(prow,0,sizeof(int )*width);

        for(int yi=0; yi<height; ++yi, src+=sstride, pint+=istride)
       {
            prow[0]+=src[0];  pint[0]=prow[0];   //for the first pixel
   
           for(int xi=1; xi<width; ++xi)
           {
                  prow[xi]+=src[xi];
                  pint[xi]=pint[xi-1]+prow[xi];
          }
      }

     delete[]prow;
}

基于积分图的快速均值滤波

设滤波窗口大小为2w+1,滤波结果为O,则:

image-aidw.png

Z = (2w+1)*(2w+1)为窗口内的像素个数,中括号内即为滤波窗口覆盖的像素颜色之和。

3.3 高斯滤波

高斯滤波以高斯函数为滤波核,用二维高斯函数,以窗口中心为原点计算窗口各个位置的权重。

image-xsik.png

行列可分离性:核大小为M的二维高斯滤波,等价于同样核大小的一维高斯滤波在行列方向的叠加。

image-zxum.png

σ越大,核应该越大,M = [6σ-1].

3.4 锐化滤波

3.4.1 基础锐化滤波

高通滤波模板的特点:

  • 滤波器应该在中心有正系数,而在边缘上有负系数。
  • 模板总和为0,sum=0
  • 在平坦变化的区域很暗,在剧烈变化的区域很亮(边缘)
  • 模板尺寸较大时,边缘较宽

3.4.2 梯度滤波

一阶导数:梯度

  • Robert算子
  • Prewitt算子
  • Sobel算子

二阶导数:拉普拉斯

图像平均类似于积分,导致图像模糊

图像差分则可能有相反的效果,导致图像锐化。

  • 一阶导数:f'(x) = f(x+1)-f(x)
  • 二阶导数:f''(x)=f(x+1)+f(x-1)-2f(x)

图像处理中最常见的差分方法即梯度。(x,y)处的梯度为:

image-hovu.png

梯度是一个向量,指向灰度变化最大的方向,其长度为:

image-fdat.png

x方向的梯度图使得图像的列方向边缘更明显,y方向的梯度图使得图像的横向边缘更明显。

梯度简约的计算公式:

image-zwjn.png

三种典型的梯度算子

  • Roberts算子
  • Prewitt算子
  • Sobel算子

Roterts算子

Robert算子的定义:对于(x,y)的3x3领域域,G_x = (z_9-z_5)

G_y=(z_8-z_6)

Roberts梯度的近似计算:

image-yfty.png

Prewitt算子

image-zlxs.png

Sobel算子

image-goea.png

通常噪声会对滤波效果产生很大的影响,图像的梯度很可能在小范围内具有很大的波动然而整体的图像呈现平坦,导致基于梯度的锐化滤波的边缘锐化效果不佳。

image-pala.png

所以在锐化之前通常先进行平滑处理减少噪声的影响。使用高斯滤波来达到平滑的效果。

image-uxtv.png

拉普拉斯算子

使用二阶导数;

拉普拉斯定义为x,y方向上的二阶导数的和。

image-kwja.png

离散函数的二阶导数表示:

image-yjfi.png

拉普拉斯的两种定义对应两种不同的拉普拉斯算子(符号相反而已)

image-higz.png

image-dztm.png

可以使用拉普拉斯滤波检测到的边缘来锐化图像。在原始图像上加上拉普拉斯检测到的边缘图像(二阶导数图),在计算上可以直接在拉普拉斯滤波上加上一个中心为1其他位置为0的滤波用于锐化处理。

注意:使用拉普拉斯锐化图像时噪声也被放大了。

可以用拉普拉斯对太空图像进行处理得到星球表面的边缘来观察地形。

高斯拉普拉斯(LOG)

卷积的导数定理

image-ayns.png

image-uomn.png

3.5 非线性滤波

3.5.1 order statics filter

将窗口内的像素值排序然后选择特定位置的像素作为输出。

  • 中值滤波(median filter):排序后选择中间位置的像素作为输出。
  • 最大值滤波(max filter):选择像素最大值作为输出。max filter的结果通常比源图像更亮。
  • 最小值滤波(min filter):选择像素最小值作为输出。min filter的结果通常比源图像的结果更暗。

中值滤波

主要用于消除噪声(椒盐噪声),相比于均值滤波,中值滤波有着更好的去除噪声效果。模板尺寸越大,处理的结果越模糊。

Fast Max/Min Filter

image-dtqp.png

pc为初始3的位置,辅助数组T从pc两边向pc看起分别求pi到pc区间内的最大值或pc到pi区间内的最大值,最终的输出为数组O,数组O中每个元素的计算只需要观察以他为中心的区间的两端的数值的最大值即可。

3.5.2 双边滤波

对于高斯滤波,在消除噪声的同时也会使得边缘变得模糊,所以对其进行改进。

双边滤波:对高斯滤波进行改进,在计算权重的同时考虑空间位置和像素颜色之差。

image-fbtj.png

CV4 Matching 1

图像匹配:同一场景的点在不同图像之间像素的对应关系。

图像匹配:特征检测 👉特征匹配👉运动估计。

4.1 局部特征

局部:特征的计算只涉及图像的局部区域,不会与整个图像都相关。

全局特征面临以下情况时回面临难以克服的困难:遮挡、形变、环境变化。

相比于考虑局部领域范围的局部特征,全局特征则是从整个图像中抽取特征,较多地运用在图像检索领域,例如图像的颜色直方图、特征词袋模型等。

4.1.1 特征检测

什么样的点才应该是特征点?

  • 稳定检测:特征点能够在不同角度被重复检测出来。
  • 易于匹配

特征检测与匹配的挑战:

  1. 对图像几何变换的稳定性
  2. 对颜色光照变化的稳定性
  3. 对尺度缩放变化的稳定性
4.1.1.1 角点检测

角点是在窗口在其邻域内向任意方向移动都会导致窗口内像素剧烈变化的点。

image-rypw.png

如何区分这三种点?

在角点处,沿着任意方向运动都会引起像素颜色的明显变化,等价于在角点附近,图像梯度至少有两个主方向。

Harris角点检测

image-adxk.png

E可以近似的估计为:

image-duec.png

M是2x2的矩阵,由图像梯度计算得到。上述式子怎么来的呢?

根据泰勒展开,可以得到窗口平移后图像的一阶近似

2f0eaxk5.png

image-ysob.png

image-dcfh.png

image-lkak.png

不同区域的图像灰度梯度分布:
当图像中灰度变化较为平坦时,Ix和Iy集中分布在原点附近
当图像中存在边缘点时,x和y其中一方具有较大的梯度
当图像中存在角点时,x和y都具有较大的梯度

其中,E(u',v')=u^2 λ_1+v^2 λ_2可以看成一个椭圆函数;

平坦区域:两个特征值都小,且近似相等,能量函数在各个方向上都较小;
边缘区域:一个特征值大,另一个特征值小,能量函数在某一方向上增大,其他方向较小;
角点区域:两个特征值都大,且近似相等,能量函数在所有方向上都增大。

所以可以通过M的两个特征值的大小对图像点进行分类。这样一来我们就可以仅通过矩阵M的特征值,来评估图像是否存在角点,不需要设置特定的uv。

事实上Harris角点的计算方法甚至不需要用到特征值,只需要计算一个Harris响应值R,R=det M-k(trance M)^2

detM是矩阵的行列式,trance M是矩阵的迹。

而对于n阶方阵,矩阵的行列式等于特征值之积,矩阵的迹等于特征值之和。

所以

det M = \lambda_1\lambda_2=AB-C^2\\ tranceM = \lambda_1+\lambda_2=A+B\\ R=detM-\alpha trance(M)^2=\lambda_1\lambda_2-\alpha(\lambda_1+\lambda_2)^2

参数α的范围为0.04-0.06

因此通过计算harris响应值R可以进行角点检测。

Harris角点检测的基本步骤

  1. 计算窗口中个像素点在x和y方向上的梯度;
  2. 计算两个方向梯度的乘积,即I_x^2,I_y^2,I_xI_y(可以用一阶梯度算子求得图像梯度。)
  3. 使用滤波核随窗口中每一个像素进行加权,生成矩阵M和元素A、B、C
  4. 计算每一个像素的Harris响应值R,对小于阈值T的R置0;
  5. 由于角点所在区域的一定领域都可能被检测为角点,为了防止角点聚集,最后在3x3或者5x5的邻域内进行非极大值抑制,局部最大值点即为图像中的角点。

Harris对光照变化和几何变换的稳定性

  • 对于矩阵M表示的椭圆,旋转后形状不变即特征值不变,所以角点响应值R具有旋转不变性。
  • Harris角点检测不具有尺度不变性,当图像放大时,角点将会被识别为边界点(放大时,角点处会变得平滑)
  • 矩阵M由图像的梯度计算得到,所以具有对加法的不变性,即对颜色和光照变化的不变性。
4.1.1.2 斑点检测

高斯拉普拉斯算子(LoG)

高斯差分算子(DoG)

二阶导数Hessian矩阵

Hessian具有旋转不变性和光照颜色变化不变性。

如何实现“尺度变化不变性”?

尺度空间与图像金字塔

图像的尺度是指图像内容的粗细程度。尺度的概念是用来模拟观察者距离物体远近的程度。尺度越大(观察者越远)图像的分辨率约低,尺度越小(观察细节)图像的分辨率越高。

图像的尺度空间时一幅图像经过不同的高斯核形成的模糊图像的几何,用来模拟人眼看到物体的远近程度以及模糊程度。图像尺度的改变不等于图像分辨率的改变。

为什么需要尺度空间?计算机在进行图像分析时斌不知道图像的真实尺寸大小,需要考虑多尺度以获得感兴趣的物体的最佳尺度。同时在一幅图像的不同尺度检测出相同的关键点来匹配可以使得结果具有尺度不变性。

图像的分辨率本质上时图像在水平和垂直方向的量化程度(离散化),直观上理解是图像能展现的细节程度。量化的过程是模拟信号转变成数字信号的过程,这一过程是不可逆的信息损失过程。因此,量化级别的高低决定了该数字信号能否更好的表示原本的模拟信号。图像是二维数组,水平像素和垂直像素的数量便是图像量化的级别,多像素图像更能展示图像的细节。

为什么需要多分辨率
我们观察图像时,看到的通常是由相似纹理和灰度级连成的区域,它们相结合就形成了物体。如果物体的尺寸较小或对比度较低,那么我们需要以较高的分辨率来研究它们;如果物体的尺寸较大或对比度较高,则以低分辨率进行粗略的观察就已足够。如果较小物体和较大物体(或对比度较低和对比度较高的物体)同时存在,那么以不同分辨率来研究它们将更具优势,这就是多分辨率处理的基本动机。

换言之,图像分辨率越低,伴随的细节就越少。图像的低分辨率级别用于分析较大的结构或图像的整体内容;而高分辨率级别适合于分析物体的细节特性。这种由粗到细的分析策略在模式识别中特别有用。

图像金字塔
图像金字塔(image pyramid)是同一张图片不同分辨率子图的集合,是通过对原图像不断地下采样而产生的。高分辨率原始图像在底部,自底向上,分辨率(尺寸)逐渐降低,堆叠起来便形成了金字塔状。通常情况下,每向上移动一级,图像的宽和高都降低为原来的1/2。

高斯金字塔
最简单的图像金字塔可以通过不断地删除图像的偶数行和偶数列得到,例如原图像大小是NN,删除其偶数行和偶数列后得到一幅(N/2)(N/2)大小的图像,此时图像大小变为原来的1/4,不断重复该过程即可得到该图像的图像金字塔。

也可以先对原始图像进行滤波,得到原始图像的近似图像,然后将近似图像的偶数行偶数列删除以获得向下采样的结果。有多种滤波器可以选择,常用高斯滤波器(高斯滤波),原始图像与各次下采样的结果图像共同构成了高斯金字塔。

拉普拉斯金字塔

将高斯金字塔当前层的图像减去上采样得到下一层扩展的图像就得到了拉普拉斯金字塔对应层的图像。

image-edar.png

实现“尺度不变”

在不同尺度同时进行检测与匹配!!!

最朴素的方法:在多尺度上进行暴力搜索,比较不同尺度下的特征描述符。虽然可以实现特征匹配,但是计算效率低下,不允许大型数据集的检测。

是否可能自动估计每个特征点的尺度?

自动尺度选择

解决方案:设计一个区域内具有尺度不变性的函数,比如区域的平均强度(像素颜色),遂于相应的区域即便是不同的尺度它们的函数值是相同的。取函数的局部极大值,区域的尺寸需要对于极大值的选择具有尺度无关性。每个具有这样的尺度无关性的region size(窗口大小)对于每一张图像是相互独立设置的。

SIFT 特征检测

  • 在不同尺度空间检测DoG的局部极大值。
  • 筛除低于阈值的响应点。
  • 消除边缘响应

4.1.2 特征匹配

特征👉特征描述

将特征所在的局部图像块转换为一个描述特征的向量。👉向量搜索匹配。

对特征描述的要求:不变性、区分性。

对齐误差

SSD(sum of square difference)平方误差

image-mkqr.png

平方运算使得微小的对齐误差也会对结果造成极大影响,因此不具有对齐误差稳定性。

SAD(sum of absolute difference)绝对值误差

image-zhdc.png

绝对值不会放大异常值,对于光照变化不敏感,精确度相较于SSD较低但是鲁棒性更高,对对齐误差具有更高的稳定性。

NCC(normalized cross correlation)

image-vdbf.png

通过计算两个图像块之间的归一化相关性来衡量相似度,对于光照变化具有很好的鲁棒性,因为他考虑了均值和标准差的归一化,稳定性较高,缺点是计算复杂性较高。

BRIFT(Binary Robust Independent Elementary Features)

BRIEF是一种二进制描述子方法,通过对图像块内随机选择的一对像素进行比较,生成二进制字符串作为特征描述子。

image-ivjn.png

计算效率高,但是对大范围的噪声和形变敏感,由于采用二值编码像素间的大小关系,对齐误差不会对像素关系造成较大的影响。

image-tuzp.png

特征匹配👉向量搜索

  • 暴力搜索
  • 基于哈希的方法:LSH
  • 基于树的方法:ANN、FLANN库

全局特征表示

  • 对图像或者目标的整体进行编码表示
  • 主要面向高层语义相关的任务,如识别、检测、检索等。

颜色直方图:统计图像的颜色直方图,并将直方图作为图像的特征表示。但是只能表达图像的整体颜色分布,不能表示语义信息。

梯度方向直方图:利用了目标的形状信息,但是对形状变化敏感。

词袋模型:将目标表示为局部特征(字典词典)的分布。具有较强的语义表达能力,对目标的形变不敏感,但是丢失了局部特征的空间信息。

DPM:局部可形变,兼有整体的空间关系约束。

卷积神经网络:越靠后的卷积层,语义表达能力越强;可以将最后一层的输出作为图像的全局特征表示。(成熟的图像特征提取工具)