I have two samples of 3D point cloud of human face. The blue point cloud denote target face and the red point cloud indicates the template. The image below shows that the target and template face are aligned in different directions (target face roughly along x-axis, template face roughly along y-axis).
Figure 1:
The region around the nose is displayed in Figure 1.
I want to rotate my target face (blue face) with nasal tip as the center of rotation (I translated the target to the template prior to Figure1 so that the tip of nose, i.e., the centerpt
, for both faces are superimposed) to grossly align with the template face (red face). I rotated the target face with the following MATLAB code:
% PCA for the target face
targetFaceptfmt = pointCloud(targetFace); % Convert to point cloud format
point = [templateFace(3522, 1), templateFace(3522, 2), templateFace(3522, 3)]; % The 3522th point in the templateFace is the nasal tip point used as center of rotation later on
radius = 20; % 20mm
[NNTarIndex, NNTarDist] = findNeighborsInRadius(Locationptfmt, point, radius); % Find all vertices within 20 of the nasal tip point on the target face
NNTar = select(Locationptfmt, NNTarIndex); % Select the identified points for PCA
[TarVec,TarSCORE,TarVal] = pca(NNTar.Location); % Do PCA for target face using vertices close to the nasal tip
% PCA for the template face
templateFaceptfmt = pointCloud(templateFace); % Convert to point cloud format
[NNTemIndex, NNTemDist] = findNeighborsInRadius( templateFaceptfmt, point, radius); % Find all vertices within 20 of the nasal tip point on the template
NNTem = select(templateFaceptfmt, NNTemIndex); % Select the identified points for PCA
[TemVec,TemSCORE,TemVal] = pca(NNTem.Location); % Do PCA for template face using vertices close to the nasal tip
% Rotate target face with nasal tip point as the center of rotation
targetFace_r = R * (targetFace-cenertpt)' + centerpt';
targetFace_new = targetFace_r';
where targetFace
and templateFace
contains coordinates for the unrotated target face and the template face, respectively. The targetFace_r
contains coordinates for the target face after rotation around nasal tip, R
is the rotation matrix calculated through PCA (See here for source of formula for rotation), and centerpt
is the nasal tip point which is used as the center of rotation. I then plotted the transposed targetFace_r
, i.e., the targetFace_new
, with normals added to each vertex:
Before rotation, the normals for the target face and template face are generally pointing toward similar directions (Figure 1). After rotation, the target and template face are both aligned along the y-axis (which is what I want), however, normals for the target face and template face point toward opposite directions. Bearing in mind that no changes were made to the template face, I realized that normals of the target face calculated after rotation are flipped. But I do not know why. I used the checkFaceOrientation
function of the Rvcg package in R to check if expansion along normals increases centroid size. I was returned TRUE for the template face but FALSE for the target face, which confirms that vertex normals for the target face are flipped.
Vertex normals were calculated in MATLAB as follows:
TR = triangulation(Faces, Vertices); % Triangulation based on face and vertex information
VN = vertexNormal(TR); % Calculate vertext normal
where Faces
contains face information, i.e., the connectivity list, and Vertices
contains coordiantes for vertices. For target face before rotation, target face after rotation, and template face, vertex normals were calcuated separately. I used the same Faces
data for calculation of vertex normal before and after rotating the target face.
The flipped vertex normals resulted in errors for some further analyses. As a result, I have to manually flip the normals to make them pointing similarly to normals of the template face.
Figure 3:
Figure 3 shows that after manually flip the normals, normals of the target and template face are generally pointing similarly in direction.
My question is why does the normals of the target face calculated after rotation flipped? In what case does rotation of 3D point cloud result in flipping of vertex normals?
Some further informaiton that may be useful: the rotation matrix R
I obtained is as follows for your reference:
0.0473096146726546 0.867593376108813 -0.495018720950670
0.987013081649028 0.0355601323276586 0.156654567895508
-0.153515396665006 0.496001220483328 0.854643675613313
Since trace(R) = 1 + 2cos(alpha)
, I calcualted alpha through acos((trace(R)-1)/2)*180/pi
, which yielded an angle of rotation of 91.7904, relative to the nasal tip point.