Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Align X and Y coordinates of face landmarks in R

here is a reprex example (sorry it’s a bit long but needed to demonstrate the issue )

reprex<- structure(list(lanmark_id = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 
59, 60, 61, 62, 63, 64, 65, 66, 67), x_new_norm = c(0.0209747069710061, 
0, 0, 0.0203578038247992, 0.0561381863047496, 0.101172115977792, 
0.156076495990129, 0.215299198025911, 0.318322023442319, 0.452190006169031, 
0.594694632942629, 0.735348550277607, 0.850709438618138, 0.924737816162864, 
0.958050586057989, 0.983960518198643, 1, 0.0154225786551511, 
0.0758790869833434, 0.141887723627391, 0.199876619370759, 0.253547193090684, 
0.470080197409007, 0.56323257248612, 0.652683528685996, 0.735965453423813, 
0.809376927822333, 0.338062924120913, 0.308451573103023, 0.278840222085133, 
0.248611967921036, 0.181986428130784, 0.227637260950032, 0.279457125231339, 
0.352251696483652, 0.424429364589759, 0.0703269586674898, 0.119062307217767, 
0.183220234423196, 0.23874151758174, 0.173349784083898, 0.112276372609501, 
0.529919802590994, 0.603331276989513, 0.674892041949415, 0.7347316471314, 
0.671807526218385, 0.6020974706971, 0.125231338679827, 0.163479333744602, 
0.233189389265885, 0.296113510178902, 0.380012338062924, 0.518815545959284, 
0.664404688463912, 0.526218383713757, 0.380012338062924, 0.288093769278224, 
0.217149907464528, 0.156076495990129, 0.154225786551512, 0.233806292412092, 
0.298581122763727, 0.382479950647749, 0.624305983960519, 0.385564466378779, 
0.298581122763727, 0.231955582973473), y_new_norm = c(0.191854233654877, 
0.30064308681672, 0.414255091103966, 0.531082529474812, 0.64898177920686, 
0.762057877813505, 0.866023579849946, 0.959271168274384, 0.997856377277599, 
1, 0.961414790996785, 0.908896034297964, 0.829046087888532, 0.719721329046088, 
0.585209003215434, 0.448017148981779, 0.313504823151125, 0.0337620578778134, 
0, 0.00482315112540196, 0.0209003215434084, 0.0535905680600213, 
0.0669882100750266, 0.0375133976420149, 0.0359056806002145, 0.0514469453376206, 
0.0980707395498391, 0.168810289389067, 0.251339764201501, 0.333333333333333, 
0.418542336548767, 0.460878885316184, 0.486066452304395, 0.508038585209003, 
0.491425509110397, 0.478563772775991, 0.170418006430868, 0.140943193997856, 
0.14898177920686, 0.190782422293676, 0.194533762057878, 0.188102893890675, 
0.213826366559486, 0.179528403001072, 0.183279742765273, 0.217577706323687, 
0.227224008574491, 0.22454448017149, 0.581993569131833, 0.556270096463022, 
0.553590568060021, 0.568595927116827, 0.561629153269025, 0.580385852090032, 
0.619506966773848, 0.709003215434084, 0.746516613076099, 0.7491961414791, 
0.737942122186495, 0.690246516613076, 0.595391211146838, 0.596998928188639, 
0.607181136120043, 0.603429796355841, 0.62593783494105, 0.686495176848875, 
0.688638799571275, 0.676312968917471)), row.names = c(NA, -68L
), class = c("tbl_df", "tbl", "data.frame"))

x_new_norm and y_new_norm are cordinates for points that represent a human face, here is what it looks when plotted
enter image description here

What I want to achieve is that the coordinates are aligned such that the points for eyes (based on points 39 and 42) are always at the same y coordinate, and points 27 and 8 would be in the same x coordinate. This would ensure that I can align multiple faces (taken during movement, or different people and poses).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

While I have some intuition on how this can be achieved I cannot work out how to implement it in R

>Solution :

You could do it by following these steps:

First, isolate the points of interest (the subject’s left and right eyes)

left_eye  <- reprex[reprex$lanmark_id == 42,]
right_eye <- reprex[reprex$lanmark_id == 39,] 

Now find the difference in the y co-ordinates and x co-ordinates between these two points:

diff_x <- left_eye$x_new_norm - right_eye$x_new_norm
diff_y <- left_eye$y_new_norm - right_eye$y_new_norm

The arctangent of the ratio will be the angle you need to rotate all the points by:

theta  <- atan2(-diff_y, diff_x)

To transform the points, you need to create a rotation matrix, which is a specific two-by-two matrix which you can use to rotate the original points:

enter image description here

mat <- matrix(c(cos(theta), sin(theta), -sin(theta), cos(theta)), 2)

Now we multiply each x, y point by this matrix to get our rotated points, and write it back into our original data frame:

reprex[,2:3] <- t(apply(reprex[,2:3], 1, function(x) mat %*% x))

Our eyes are now at the same level, as we can demonstrate by plotting:

p <- ggplot(reprex, aes(x_new_norm, y_new_norm, label = lanmark_id)) + 
  geom_point(color = 'gray') +
  geom_text() +
  scale_y_reverse() +
  theme_bw()

p

enter image description here

p + geom_hline(yintercept = reprex$y_new_norm[reprex$lanmark_id == 42],
               linetype = 2, color = 'red4', alpha = 0.5)

enter image description here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading