从七十年代以来,随着认知心理学自身的发展,认知心理学关于模式识别的研究在取向上出现了某些重要的变化。一些认知心理学家继续在物理符号系统假设的基础上进行研究,探讨计算机和人的识别模式的特点;而另一些认知心理学家则转向用神经网络的思想来研究识别模式的问题。下面介绍的一些模型是近十多年来有重要影响的理论模型。
视觉计算理论(computational theory of vision)是在20世纪70年代由马尔(David Marr)提出的。1982发表代表作《视觉计算理论》。马尔认为,视觉就是要对外部世界的图像(iamge)构成有效的符号描述,它的核心问题是要从图像的结构推导出外部世界的结构。视觉从图像开始,经过一系列的处理和转换,最后达到对外部现实世界的认识。
三个重要概念:
表征(representation):指能把某些客体或几类信息表达清楚的一种形式化系统,以及说明该系统如何行使其职能的若干规则。使用某一表征描述某一实体所得的结果,就是该实体在这种表征下的一个描述。
处理(process):是指某种操作,它促使事物的转换。视觉从接收图像到认识一个在空间内排列的、完整的物体,需要经过一系列的表征阶段。从一种表征转换为另一种表征,必须借助于某些处理过程。
零交叉(zero crossing)代表明暗度的不连续变化或突然变化,是形成物体轮廓的基础。对零交叉的检测就是视觉系统对二维表面轮廓或边界的检测。
人和机器的最终目的:了解一个场景或一个图像的意义。马尔把视觉图像的形成划分为三个阶段。阶段如下:
⑴二维基素图(2-D sketch):视觉过程的第一阶段,由输入图像而获得基素图。视觉的这一阶段也称为早期视觉。所谓基素图主要指图像中强度变化剧烈处的位置及其几何分布和组织结构,其中用到的基元包括斑点、端点、边缘片断、有效线段、线段组、曲线组织、边界等。这些基元都是在检测零交叉的基础上产生的。
这一阶段的目的在于把原始二维图像中的重要信息更清楚地表示出来。
⑵ 2.5维要素图:视觉过程的第二阶段,通过符号处理,将线条、点和斑点以不同的方式组织起来而获得2.5维图。视觉过程的这一阶段也称为中期视觉。所谓2.5维图指的是在以观察者为中心的坐标系中,可见表面的法线方向、大致的深度以及它们的不连续轮廓等,其中用到的基元包括可见表面上各点的法线方向、和各点离观察者的距离(深度)、深度上的不连续点、表面法线方向上的不连续点等等。由于2.5维图中包含了深度的信息,因而比二维要多,但还不是真正的三维表示,所以得名2.5维图。视觉的这一阶段,按马尔的理论,是由一系列相对独立的处理模块组成的。这些处理模块包括:体现、运动、由表面明暗恢复形状、由表面轮廓线恢复形状、由表面纹理恢复形状等。它的作用是揭示一个图像的表面特征。马尔声称,早期视觉加工的目标就是要建立一个2.5维的要素图,这是把一个表面解释为一个特定的物体或一组物体之前的最后一步。
⑶三维模型表征(3-D model representation):视觉过程的第三阶段,由输入图像、基素图、2.5维图而获得物体的三维表示。视觉过程的这一阶段,也称为后期视觉。所谓物体的三维表示指的是在以物体为中心的坐标系中,用含有体积基元(即表示形状所占体积的基元)和面积基元的模块化分层次表象,描述形状和形状的空间组织形式,其表征包括容积、大小和形状。当三维模型表征建立起来时,其最终结果是对我们能够区别的物体的一种独特的描述。
这里学习了RoPS特征进行面部提取,ROPS是一种基于mesh的局部特征描述子,其主要应用为物体识别,所以在此之前应进行三角网格重建,以下内容皆基于此基础上进行。第一步,对于一个给定的兴趣点局部的表面将会被削平。局部表面包含了在半径内的点和三角形。对于给定的局部表面LRF将被计算。LRF是向量的3个组之一。真正重要的是使用那些具有旋转不变的向量。为了做到这一点,我们把感兴趣的点作为原点来做转换,再这之后我们旋转局部表面,以至于LRF向量关于Ox,Oy,Oz坐标轴对称。完成这些后,我们开始了特征导出。对于每个Ox,Oy,Oz坐标轴,我们会把这些这些坐标轴作为当前的坐标轴。
close all;
clc;
clear all;
load data\pointcloud_view1;
%============================detect keypoints============================%
%keypoints are randomly seleted in this demo, any other 3D keypoint detection methods can be used
pointcloud.vertices = pointcloud;
keypntNum = 100;
temp = randperm(length(pointcloud.vertices));
pointcloud.keypntIdx = temp(1:keypntNum);
%============================preprocessing============================%
kdtreeVertices = KDTreeSearcher(pointcloud.vertices,'Distance','euclidean');
[idx,dist] = knnsearch(kdtreeVertices, pointcloud.vertices,'k',2,'Distance','euclidean');
pointcloud.res = mean(dist(:,2));
%============================show the pointcloud and its keypoints============================%
pointcloudX = pointcloud;
angle = 0;%-90;
R = [1,0,0; 0,cos(angle*pi/180),sin(angle*pi/180); 0, -sin(angle*pi/180), cos(angle*pi/180)]'; %for illustration
pointcloudX.vertices = pointcloud.vertices*R;
figure; plot3(pointcloudX.vertices(:,1),pointcloudX.vertices(:,2),pointcloudX.vertices(:,3), 'b.'); hold on;
plot3(pointcloudX.vertices(pointcloudX.keypntIdx,1),pointcloudX.vertices(pointcloudX.keypntIdx,2),pointcloudX.vertices(pointcloudX.keypntIdx,3),'r.', 'MarkerSize', 20); axis equal;
%============================extract RoPS features at the keypoints on a point-cloud============================%
para.RoPS_nbSize = 15*pointcloud.res;
para.RoPS_binSize = 5;
para.RoPS_rotaSize = 3;
pointcloud.LRF = LRFforPntCldFunc(pointcloud, pointcloud.keypntIdx, para.RoPS_nbSize);
disp('LRF calculation finished');
RoPS = RoPSFunc(pointcloud, para.RoPS_nbSize, para.RoPS_binSize, para.RoPS_rotaSize,pointcloud.LRF);
pointcloud.RoPS = RoPS;
disp(['RoPS feature generated']);
close all;
clc;
clear all;
keypntNum = 1000;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
load data\pointcloud_view1;
% %============================transform a pointcloud into a triangular mesh============================%
mesh = pointCloud2mesh(pointcloud,[0 0 1],0.4); %other methods can also be used to perform triangulation
%============================preprocessing============================%
out = preprocessingFunc(mesh);
mesh.faceCenter = out.centroid;
mesh.faceArea = out.area;
mesh.res = out.res ;
%============================detect keypoints============================%
%keypoints are randomly seleted in this demo, any other 3D keypoint detection methods can be used
keypntNum = 1000;
temp = randperm(length(mesh.vertices));
mesh.keypntIdx = temp(1:keypntNum);
%============================extract RoPS features at the keypoints on a mesh============================%
para.RoPS_nbSize = 15*mesh.res;
para.RoPS_binSize = 5;
para.RoPS_rotaSize = 3;
mesh.LRF = LRFforMeshFunc(mesh, mesh.keypntIdx, para.RoPS_nbSize);
disp('LRFs calculated');
RoPS = RoPSFunc(mesh, para.RoPS_nbSize, para.RoPS_binSize, para.RoPS_rotaSize,mesh.LRF);
mesh.RoPS = RoPS;
disp(['RoPS features generated']);
mesh1 = mesh;
mesh1Features = [];
for keypntIdx = 1:keypntNum
temp = trans2Dto1DFunc(mesh.RoPS{keypntIdx});
mesh1Features = [mesh1Features; temp];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
load data\pointcloud_view2;
% %============================transform a pointcloud into a triangular mesh============================%
mesh = pointCloud2mesh(pointcloud,[0 0 1],0.4); %other methods can also be used to perform triangulation
%============================preprocessing============================%
out = preprocessingFunc(mesh);
mesh.faceCenter = out.centroid;
mesh.faceArea = out.area;
mesh.res = out.res ;
%============================detect keypoints============================%
%keypoints are randomly seleted in this demo, any other 3D keypoint detection methods can be used
keypntNum = 1000;
temp = randperm(length(mesh.vertices));
mesh.keypntIdx = temp(1:keypntNum);
%============================extract RoPS features at the keypoints on a mesh============================%
para.RoPS_nbSize = 15*mesh.res;
para.RoPS_binSize = 5;
para.RoPS_rotaSize = 3;
mesh.LRF = LRFforMeshFunc(mesh, mesh.keypntIdx, para.RoPS_nbSize);
disp('LRFs calculated');
RoPS = RoPSFunc(mesh, para.RoPS_nbSize, para.RoPS_binSize, para.RoPS_rotaSize,mesh.LRF);
mesh.RoPS = RoPS;
disp(['RoPS features generated']);
mesh2 = mesh;
mesh2Features = [];
for keypntIdx = 1:keypntNum
temp = trans2Dto1DFunc(mesh.RoPS{keypntIdx});
mesh2Features = [mesh2Features; temp];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %============================feature matching============================%
NNDRthreshold = 0.9;
corNum = 0;
kdtreeMesh1Features = KDTreeSearcher(mesh1Features,'Distance','euclidean');
for keypntIdx1 = 1:size(mesh2Features,1)
[idxSort,distSort] = knnsearch(kdtreeMesh1Features, mesh2Features(keypntIdx1,:),'k',2,'Distance','euclidean');
IDX = idxSort(1);
if distSort(1)/distSort(2)<=NNDRthreshold
corNum = corNum+1;
corPntIdx(corNum,:) = [IDX, keypntIdx1];
featureDis(corNum) = distSort(1);
end
end
showCorresFunc(mesh1, mesh2, mesh1.keypntIdx(corPntIdx(:,1)), mesh2.keypntIdx(corPntIdx(:,2)), [0,200,0]);