Выровняйте координаты X и Y ориентиров лица в R

вот пример репрекса (извините, он немного длинный, но он необходим для демонстрации проблемы)

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 и y_new_norm — координаты точек, изображающих человеческое лицо, вот как оно выглядит на графике

Чего я хочу добиться, так это того, чтобы координаты были выровнены таким образом, чтобы точки для глаз (на основе точек 39 и 42) всегда находились в одной и той же координате y, а точки 27 и 8 были бы в одной и той же координате x. Это гарантировало бы, что я могу выровнять несколько лиц (снятых во время движения или разных людей и поз).

Хотя у меня есть некоторая интуиция о том, как этого можно достичь, я не могу понять, как реализовать это в R.

Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
2
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете сделать это, выполнив следующие действия:

Во-первых, изолируйте точки интереса (левый и правый глаза субъекта).

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

Теперь найдите разницу координат y и координат x между этими двумя точками:

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

Арктангенс отношения будет углом, на который нужно повернуть все точки:

theta  <- atan2(-diff_y, diff_x)

Чтобы преобразовать точки, вам нужно создать матрицу вращения, которая представляет собой специальную матрицу два на два, которую вы можете использовать для поворота исходных точек:

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

Теперь мы умножаем каждую точку x, y на эту матрицу, чтобы получить наши повернутые точки, и записываем их обратно в наш исходный фрейм данных:

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

Наши глаза теперь находятся на одном уровне, что мы можем продемонстрировать, построив график:

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

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

спасибо, это почти идеально, просто не работает с вертикальными центрами 8 и 27. Также можно обернуть это в фрагмент, который работает с dplyr, например, для группировки по изображениям (при работе с несколькими изображениями) или в а. петля? огромное спасибо

Myriad 18.11.2022 18:45

@Myriad, вы не можете выровнять 39 и 42 по горизонтали, а 8 и 27 выровнять только за счет вращения. Вам также придется выполнить преобразование сдвига, что сложнее (хотя все же возможно). Написание кода таким образом, чтобы он работал в dplyr, по существу включало бы обертывание логики в функцию, которая принимает столбец x, столбец y, столбец id и номера идентификаторов левого глаза, правого глаза и вертикальных точек, поэтому это было бы не очень естественно для трубы dplyr.

Allan Cameron 18.11.2022 18:55

спасибо, это было очень полезно, я посмотрю на преобразование сдвига

Myriad 18.11.2022 19:35

Другие вопросы по теме