尺度空间
尺度空间就是试图在图像领域中模拟人眼观察物体的概念与方法。
这是由于通过计算机视觉系统,我们无法直接获取所关注物体、对象的大小,这时候就需要一个尺度空间来描述
感觉还是有点抽象,再引用一段说明:
在一定的范围内,无论物体是大还是小,人眼都可以分辨出来。然而计算机要有相同的能力却不是那么的容易,在未知的场景中,计算机视觉并不能提供物体的尺度大小,其中的一种方法是把物体不同尺度下的图像都提供给机器,让机器能够对物体在不同的尺度下有一个统一的认知。在建立统一认知的过程中,要考虑的就是在图像在不同的尺度下都存在的特征点。
一、局部不变性
对于目标物体,我们希望通过一些特征来描述它。比如车,可以选取车牌、轮廓等特征,对于人脸,则有五官、面型等特征。
分析图像物体时,我们关注的是目标与背景的差异性,局部不变性就是特征分析的重要性质。其包括:
- 尺度不变性
- 旋转不变性
(1)尺度不变性:摄像头相对于物体远近呈现出来的物体尺寸不受其大小影响。 貌似说:就是不管你的物体大小如何,摄像头都可以改变目标物体的图像大小,只不过是摄像头放的远近问题。比如说:两个除了尺寸之外都一样的球,摄像头离大的球远一些,离小的球近一些,在某个点上,就会出现图像上两个球一样大小的情况。
(2)旋转不变性:描述物体发生旋转操作与目标认知分析无关。
即若图像按下式进行变换(相当于所有坐标在极坐标下旋转θ角度):
图像的某些特征值不变,(某些函数值不变,如hu矩)
另外一个熟悉的具有旋转不变形的是拉普拉斯算子,具体证明参见:为什么拉普拉斯算子具有旋转不变性
二、二维图像的尺度空间定义:
三、特征点尺度变换
这里给出一个利用图像金字塔和高斯卷积操作产生多尺度空间的例子。
参见《Opencv图像处理编程实例》
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//尺度变换的一种实现
void CreateScaleSpace(Mat srcImage, vector<vector<Mat>>&ScaleSpace, vector<vector<Mat>>&DoG)
{
Size ksize(5, 5);
double sigma;
Mat srcBlurMat, up, down;
//高斯滤波
GaussianBlur(srcImage, srcBlurMat, ksize, 0.5);
//金字塔
pyrUp(srcBlurMat, up);
ScaleSpace[0].push_back(up);
//GaussianBlur
GaussianBlur(ScaleSpace[0][0], ScaleSpace[0][0],
ksize, 1.0);
//图像遍历
int i;
for (i = 0; i < 4; i++){
//平滑因子
double sigma = 1.4142135;
for (int j = 0; j < 5 + 2; j++){
sigma = sigma*pow(2.0, j / 2.0);
//对下一尺度进行高斯操作
Mat tmp1,tmp2;
GaussianBlur(ScaleSpace[i][j],tmp1,
ksize, sigma);
ScaleSpace[i].push_back(tmp1);
imshow("tmp", tmp1);
waitKey(0);
//生成多尺度空间
tmp2 = ScaleSpace[i][j] - ScaleSpace[i][j + 1];
DoG[i].push_back(tmp2);
//输出对应特征空间尺度
//imshow("tmp", tmp);
}
//如果不能完成,继续进行金字塔操作
if (i < 3){
//金字塔下采样
pyrDown(ScaleSpace[i][0], down);
ScaleSpace[i + 1].push_back(down);
}
}
}
int main()
{
Mat srcImg = imread("F:\\opencv_re_learn\\flash.jpg");
if (!srcImg.data){
cout << "failed to read" << endl;
system("pause");
return -1;
}
vector<vector<Mat>>ScaleSpace(100);
vector<vector<Mat>>DoG(100);
CreateScaleSpace(srcImg, ScaleSpace, DoG);
imshow("src", srcImg);
imshow("scale", ScaleSpace[2][1]);
waitKey(0);
return 0;
}