Convert Vision face detection VNFaceLandmarkRegion2D points into frame coordinates to be scale - objective-c

I'm using vision framework to detect face landmark and it's working fine but i need to transform the face landmarks like nose, eyes and for that i need to get nose, eyes position in frame coordinate as face landmark is drawing using VNFaceLandmarkRegion2D points.
Please let me know how to convert VNFaceLandmarkRegion2D points to frame coordinate. So i can get the location in view for transformation or suggest any other way to to transform face landmark.

This code from Joshua Newnham solves your problem.
func getTransformedPoints(
landmark:VNFaceLandmarkRegion2D,
faceRect:CGRect,
imageSize:CGSize) -> [CGPoint]{
// last point is 0.0
return landmark.normalizedPoints.map({ (np) -> CGPoint in
return CGPoint(
x: faceRect.origin.x + np.x * faceRect.size.width,
y: imageSize.height - (np.y * faceRect.size.height + faceRect.origin.y))
})
}

As a newbie this is what I could find to get face marks as a CGPoint:
First converted the selected image to CIImage
Used faceDetector on the image
Parsed the image for each face in case it has more than one
Code:
let chosenPicture = CIImage(data: (self.selectedimage.image?.tiffRepresentation)!)
let selectedFace = faceDetector?.features(in: chosenPicture!, options: [CIDetectorSmile:true])
for person in selectedFace as! [CIFaceFeature] {
let p1LeftEye = person.leftEyePosition
let p1RightEye = person.rightEyePosition
let p1Mouth = person.mouthPosition

Related

Cesium: Having the camera in an entity's first person view

I would like to have my camera follow the first-person view of a moving entity. I do not believe that trackedEntity will work for this use case because I don't want to look at the entity, but I want to look out from it. I would also like the user to be able to use the mouse to turn the camera with respect to the moving entity (for example, to look out the left window of a moving plane).
In a traditional game engine, I would do this by attaching the camera to the entity, so it would move with it, but retain its own local transform with respect to the entity so that it was free to move with respect to the entity.
The only way I can think of right now is to keep track of the "user-controlled" transform separately and multiply it with the entity transform at every clock tick. Is there a better way?
Have a look at Cesium's Cardboard sandcastle example. Here you are on board of a hot-air balloon and perceive the world from there. After scrolling out, you can pan with the mouse to look around. Since the calculations are quite complicated, I cannot give any details how it works, but it seems that the camera view is aligned to the moving direction of the entity. The essential part of the script is:
// Set initial camera position and orientation to be when in the model's reference frame.
var camera = viewer.camera;
camera.position = new Cesium.Cartesian3(0.25, 0.0, 0.0);
camera.direction = new Cesium.Cartesian3(1.0, 0.0, 0.0);
camera.up = new Cesium.Cartesian3(0.0, 0.0, 1.0);
camera.right = new Cesium.Cartesian3(0.0, -1.0, 0.0);
viewer.scene.postUpdate.addEventListener(function (scene, time) {
var position = entity.position.getValue(time);
if (!Cesium.defined(position)) {
return;
}
var transform;
if (!Cesium.defined(entity.orientation)) {
transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
} else {
var orientation = entity.orientation.getValue(time);
if (!Cesium.defined(orientation)) {
return;
}
transform = Cesium.Matrix4.fromRotationTranslation(
Cesium.Matrix3.fromQuaternion(orientation),
position
);
}
// Save camera state
var offset = Cesium.Cartesian3.clone(camera.position);
var direction = Cesium.Cartesian3.clone(camera.direction);
var up = Cesium.Cartesian3.clone(camera.up);
// Set camera to be in model's reference frame.
camera.lookAtTransform(transform);
// Reset the camera state to the saved state so it appears fixed in the model's frame.
Cesium.Cartesian3.clone(offset, camera.position);
Cesium.Cartesian3.clone(direction, camera.direction);
Cesium.Cartesian3.clone(up, camera.up);
Cesium.Cartesian3.cross(direction, up, camera.right);
});
Maybe you can try to modify the camera vectors or multiply the transform with another rotation matrix to simulate turning one's head (to look left/right/back) while being in the initial perspective. For instance, you can try to combine the example above with code from a repository called Cesium First Person Camera Controller.
Had to figure this out myself as well.
Camera.setView and self-defined utility functions are your friend.
E.g. Here is a naive implementation of rotation (does not work well when the pitch of the camera is too "birds-eye-view" like):
Cesium.Camera.prototype.rotateView = function(rotation) {
let { heading, pitch, roll } = rotation;
heading = this.heading + (heading || 0);
pitch = this.pitch + (pitch || 0);
roll = this.roll + (roll || 0);
const destination = this.position;
this.setView({
destination,
orientation: {
heading,
pitch,
roll
}
});
};
Similarly you can update the position with the position of the entity by providing destination.

Bound camera to sprite bounds

I have a scene camera following a unit (sprite's position), this unit is standing on a terrain sprite, This camera not only follows it, it also zooms in and out using the pinch gesture. Everything works well, except that I want to limit the camera's lower bound to be limited by the lower bound of the terrain sprite. In other words, I don't want the camera to display anything below the terrain sprite. And by this I mean that instead the camera could shift upwards and preserve the scale.
Any swift, obj-c or even pseudo-code answers would help. Thanks!
This is my attempt
let halfTerrain = terrain.size.height/2
let halfViewport = scene!.size.height/2
let distanceFromCenter = halfTerrain - cameraPosition.y
let scaledDistanceFromCenter = distanceFromCenter/cameraScale
let gapSize = halfViewport - halfTerrain/cameraScale
let isOverlapping = scaledDistanceFromCenter < halfViewport
if isOverlapping {
camera?.runAction(SKAction.moveTo(CGPoint(x: cameraPosition.x,
y: -gapSize * cameraScale), duration: movingSpeed))
} else {
camera?.runAction(SKAction.moveTo(cameraPosition,
duration: movingSpeed))
}
camera?.runAction(SKAction.scaleTo(cameraScale,
duration: scaleSpeed))

Projection issue with ESRI JSAPI and ArcGIS map service

I was trying to obtain a gpx file with some coordinates by drawing on an Openlayers map with an ArcGIS baseMap.
When I draw the polyline and create the gpx, if I open it on Google Earth, what I see is not what I drawed before, the line is totally different from the original and not positioned where I drawed it.
I know it's a projection problem, I've tried trasforming the geometry object from Mercator to Geographic, also getting directly the geographic coordinates from the map coordinates, but nothing.
I tried to set "spatialReference" to 4362 and then to 3857, but nothing changes.
I'm going to use that .gpx on a gps device (the next week I'll go to the Svalbard islands and I need some gps tracks to go around Longyearbyen by snowmobile, there there aren't any sign of life out the town, so I must be prepared to it), when I'll be there I'll adjust the output right for the device they will rent to me, but now I need to save on the .gpx file almost the right coordinates.
I'm getting from the map those coordinates:
lat: 61.22582068741976
lon: 4.684820015391338
when I'm expecting instead something around 78. lat and 15. lon.
This is some of the code I use to create the map (I'm not pasting the code I know it's not responsible of my problems):
var initialExtent = new esri.geometry.Extent({"xmin":505615.5801124362,"ymin":8678955.717187276,"xmax":525935.6207525175,"ymax":8689168.654279819,"spatialReference":{"wkid":32633,"latestWkid":32633}});
map = map = new esri.Map("map", {extent: initialExtent, logo : false});
basemapURL = "http://geodata.npolar.no/ArcGIS/rest/services/inspire1/NP_TopoSvalbard_U33_CHL/MapServer/";
map.addLayer(new esri.layers.ArcGISTiledMapServiceLayer(basemapURL));
Here I'm using wkid 32633 that is the default for that map, tried to change with known ones, but nothing happened.
And now the code I use to get the coordinates:
dojo.connect(tb, "onDrawEnd", getCoords);
function getCoords(geo) {
var r=confirm("Salvare tracciato?");
if (r==true) {
geo = esri.geometry.webMercatorToGeographic(geo);
for ( var path = 0; path < geo.paths.length; path ++ ) {
for ( var pt = 0; pt < geo.paths[path].length; pt++ ) {
tra += '<wpt lat="'+geo.paths[path][pt][1]+'" lon="'+geo.paths[path][pt][0]+'"></wpt>';
}
}
}
}
"tra" is a variable that stores all the code I'll insert into the gpx file with an other function.
The "webMercatorToGeographic" function transform the map coordinates to geographic ones.
Thanks to Devdatta Tengshe on GIS.stackexchange I got what I need:
Use the proj4js library in your application. To do this, follow these
steps:
Download the latest library from
https://github.com/proj4js/proj4js/releases In your HTML file use
You'll
need to define the projections before you can use it. You can do this
by using the following lines of code: var UTM33N= "+proj=utm +zone=33
+ellps=WGS84 +datum=WGS84 +units=m +no_defs"; var GCS84="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
When you need to transform, you can use the following line: var
transformed=proj4(UTM33N,GCS84,[x,y]); where x & y are the coordinates
in your given projection. As output you'll get an array with two
elements, the longitude, & the Latitude
That worked fine.

THREE.js rotating camera around an object using orbit path

I am struggling in solving this problem.
On my scene, I have a camera which looks at the center of mass of an object. I have a some buttons that enable to set camera position on particular view (front view, back view,...) along a invisible sphere that surroung the object (constant radius).
When I click on the button, i would like the camera to move from its start position to the end position along the sphere surface. When camera moves I would like it to keep fixing center of mass of the object.
Has anyone have a clue on how to achieve this?
Thanks for help!
If you are happy/prefer to use basic trigonometry then in your initialisation section you could do this:
var cameraAngle = 0;
var orbitRange = 100;
var orbitSpeed = 2 * Math.PI/180;
var desiredAngle = 90 * Math.PI/180;
...
camera.position.set(orbitRange,0,0);
camera.lookAt(myObject.position);
Then in your render/animate section you could do this:
if (cameraAngle == desiredAngle) { orbitSpeed = 0; }
else {
cameraAngle += orbitSpeed;
camera.position.x = Math.cos(cameraAngle) * orbitRange;
camera.position.y = Math.sin(cameraAngle) * orbitRange;
}
Of course, your buttons would modify what the desiredAngle was (0°, 90°, 180° or 270° presumably), you need to rotate around the correct plane (I am rotating around the XY plane above), and you can play with the orbitRange and orbitSpeed until you hare happy.
You can also modify orbitSpeed as it moves along the orbit path, speeding up and slowing down at various cameraAngles for a smoother ride. This process is called 'tweening' and you could search on 'tween' or 'tweening' if you want to know more. I think Three.js has tweening support but have never looked into it.
Oh, also remember to set your camera's far property to be greater than orbitRadius or you will only see the front half of your object and, depending on what it is, that might look weird.

Glut glLoadMatrixf camera equivalent

In my glut application I'm simulating a plane with the camera. When the planes speed is low I intend to have the nose start to point towards the ground as the camera falls. My first instinct was to just change the pitch until it was pointed downwards at -90degrees. However I can't just change the pitch because if the plane is tilted on its side or upside down then it would note be changing direction towards the ground.
Now i'm trying to do a rough simulation of this by shifting the 'lookAt.y' downwards. To do this I am trying to get all the current camera coordinates that I use to set the camera
(eye.x, eye.y, eye.z, look.x, look.y, look.z, up.x, up.y, up.z). Then recall the set with the new modified values.
I've been working with the Camera.cpp and Camera.h to control my camera functions. They can be found here
after adding methods to get all the values, only the eye values are actually updated when various camera motions are made. I guess my question is how do I retrieve these values.
The glLoadMaxtrix call is in this function
void Camera :: setModelViewMatrix(void)
{ // load model view matrix with existing camera values
float m[16];
Vector3 eVec(eye.x, eye.y, eye.z);
m[0] = u.x; m[4] = u.y; m[8] = u.z; m[12] = -eVec.dot(u);
m[1] = v.x; m[5] = v.y; m[9] = v.z; m[13] = -eVec.dot(v);
m[2] = n.x; m[6] = n.y; m[10] = n.z; m[14] = -eVec.dot(n);
m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1.0;
look.x = u.y; look.y = v.y; look.z = n.y;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(m);
}
Is there a way to get 'eye', 'lookAt', and 'up' values from the matrix here? Or should I do something else to get these values?
-Thanks in advance for your help
The camera class you link to is not an actual OpenGL class, but it should be simple enough to work with.
The function quoted just takes the current values of the camera object and sends them to OpenGL. If you look at the camera's set function, you can see how the program calculates the values it actually stores.
The eye value is stored directly. The lookAt value is just the value of (eye - n), by vector math. The up value is the hardest, but if I remember my vector math correctly, I believe that up = (n cross u).