How does Elevation of a Head Pose in Python-OpenCV work? - python-3.x

I am trying to estimate the head pose of single images mostly following this guide:
https://towardsdatascience.com/real-time-head-pose-estimation-in-python-e52db1bc606a
The detection of the face works fine - if i plot the image and the detected landmarks they line up nicely.
I am estimating the camera matrix from the image, and assume no lens distortion:
size = image.shape
focal_length = size[1]
center = (size[1]/2, size[0]/2)
camera_matrix = np.array([[focal_length, 0, center[0]],
[0, focal_length, center[1]],
[0, 0, 1]], dtype="double")
dist_coeffs = np.zeros((4, 1)) # Assuming no lens distortion
I am trying to get the head pose by matching points in the image with points in the 3D model using solvePNP:
# 3D-model points to which the points extracted from an image are matched:
model_points = np.array([
(0.0, 0.0, 0.0), # Nose tip
(0.0, -330.0, -65.0), # Chin
(-225.0, 170.0, -135.0), # Left eye corner
(225.0, 170.0, -135.0), # Right eye corner
(-150.0, -150.0, -125.0), # Left Mouth corner
(150.0, -150.0, -125.0) # Right mouth corner
])
image_points = np.array([
shape[30], # Nose tip
shape[8], # Chin
shape[36], # Left eye left corner
shape[45], # Right eye right corne
shape[48], # Left Mouth corner
shape[54] # Right mouth corner
], dtype="double")
success, rotation_vec, translation_vec) = \
cv2.solvePnP(model_points, image_points, camera_matrix, dist_coeffs)
finally, I am getting the euler angles from the rotation:
rotation_mat, _ = cv2.Rodrigues(rotation_vec)
pose_mat = cv2.hconcat((rotation_mat, translation_vec))
_, _, _, _, _, _, angles = cv2.decomposeProjectionMatrix(pose_mat)
now the azimuth is what i would expect - it is negative if i look to the left, zero in the middle and positive to the right.
the elevation however is strange - if i look in the middle it has a constant value but the sign is random - changing from image to image (the value is around 170).
When i look up the sign is positive and the value decreases the more i look up,
When i look down the sign is negative and the value decreases the more i look down.
Can someone explain this output to me?

Ok so it seems i have found a solution - the model points (which i have found in several blogs on the topic) seem to be wrong. The code seems to work with this combination of model and image points (no idea why it was trial and error):
model_points = np.float32([[6.825897, 6.760612, 4.402142],
[1.330353, 7.122144, 6.903745],
[-1.330353, 7.122144, 6.903745],
[-6.825897, 6.760612, 4.402142],
[5.311432, 5.485328, 3.987654],
[1.789930, 5.393625, 4.413414],
[-1.789930, 5.393625, 4.413414],
[-5.311432, 5.485328, 3.987654],
[2.005628, 1.409845, 6.165652],
[-2.005628, 1.409845, 6.165652],
[2.774015, -2.080775, 5.048531],
[-2.774015, -2.080775, 5.048531],
[0.000000, -3.116408, 6.097667],
[0.000000, -7.415691, 4.070434]])
image_points = np.float32([shape[17], shape[21], shape[22], shape[26],
shape[36], shape[39], shape[42], shape[45],
shape[31], shape[35], shape[48], shape[54],
shape[57], shape[8]])

Related

Surface triangulation and interpolation in python 3

I have 3 lists of equal length of x, y and z coordinates.
With them, I need to triangulate a surface, and retrieve values that lie in a line over that surface. In other words, I need the values that lie on that surface that intersect a given plane.
Problem is, I have no idea where to start.
I have tried scipy interp2d, but it seems I need more z values them what I actually have (like shown in this answer: Python interpolation and extracting value of z for x and y?.
# this is the data I have
x = [0.0, 17.67599999997765, 49.08499999996275, 90.57299999985844, 136.60500000044703]
y = [0.0, 45.22349889159747, 66.50303846438841, 114.04427618243405, 187.7707039612985]
z = [0.0, 1.8700000000000045, 1.9539999999999509, 1.3929999999999154, 1.6299999999999955]
I need a final grid with x y z values that look something like this:
I don't really need too much resolution
My desired final result is to be able to retrieve specific values on top of that surface
Like the point line in this image:
I have also tried looking at geospatial libraries, but I couldn't find a solution either.
Maybe it's possible to interpolate the z values that I need? But I'm not really sure how to do this. I have never used scipy library before, and I'm still struggling to understand it.
I'm using python 3.9
You barely have any data, so if you don't choose your intersecting plane carefully, you'll get no results back (or nonsense back). This includes the case of x=y; you can't do that at all - so the graph you've shown is entirely inapplicable to your data.
import numpy as np
import scipy.interpolate
x = [0.0, 17.6759999999776500, 49.0849999999627500, 90.5729999998584400, 136.6050000004470300]
y = [0.0, 45.2234988915974700, 66.5030384643884100, 114.0442761824340500, 187.7707039612985000]
z = [0.0, 1.8700000000000045, 1.9539999999999509, 1.3929999999999154, 1.6299999999999955]
xyi = np.empty((200, 2))
xyi[:, 0] = np.arange(200)
xyi[:, 1] = xyi[:, 0] * 1.374
zi = scipy.interpolate.griddata(
points=(x, y), values=z,
xi=xyi,
method='cubic',
)
good_vals = ~np.isnan(zi)
xyz = np.empty((np.count_nonzero(good_vals), 3))
xyz[:, :2] = xyi[good_vals, :]
xyz[:, 2] = zi[good_vals]
print(xyz)
[[0.00000000e+00 0.00000000e+00 0.00000000e+00]
[1.00000000e+00 1.37400000e+00 4.68988354e-02]
[2.00000000e+00 2.74800000e+00 9.44855957e-02]
[3.00000000e+00 4.12200000e+00 1.42698116e-01]
[4.00000000e+00 5.49600000e+00 1.91474231e-01]
[5.00000000e+00 6.87000000e+00 2.40751776e-01]
[6.00000000e+00 8.24400000e+00 2.90468585e-01]
[7.00000000e+00 9.61800000e+00 3.40562494e-01]
[8.00000000e+00 1.09920000e+01 3.90971337e-01]
[9.00000000e+00 1.23660000e+01 4.41632950e-01]
[1.00000000e+01 1.37400000e+01 4.92485168e-01]
[1.10000000e+01 1.51140000e+01 5.43465824e-01]
[1.20000000e+01 1.64880000e+01 5.94512755e-01]
[1.30000000e+01 1.78620000e+01 6.45563795e-01]
[1.40000000e+01 1.92360000e+01 6.96556779e-01]
[1.50000000e+01 2.06100000e+01 7.47429542e-01]
[1.60000000e+01 2.19840000e+01 7.98119919e-01]
[1.70000000e+01 2.33580000e+01 8.48565744e-01]
[1.80000000e+01 2.47320000e+01 8.98704854e-01]
[1.90000000e+01 2.61060000e+01 9.48475082e-01]
[2.00000000e+01 2.74800000e+01 9.97814263e-01]
[2.10000000e+01 2.88540000e+01 1.04666023e+00]
[2.20000000e+01 3.02280000e+01 1.09495083e+00]
[2.30000000e+01 3.16020000e+01 1.14262388e+00]
[2.40000000e+01 3.29760000e+01 1.18961722e+00]
[2.50000000e+01 3.43500000e+01 1.23586870e+00]
[2.60000000e+01 3.57240000e+01 1.28131613e+00]
[2.70000000e+01 3.70980000e+01 1.32589737e+00]
[2.80000000e+01 3.84720000e+01 1.36955024e+00]
[2.90000000e+01 3.98460000e+01 1.41221257e+00]
[3.00000000e+01 4.12200000e+01 1.45382221e+00]
[3.10000000e+01 4.25940000e+01 1.49431699e+00]
[3.20000000e+01 4.39680000e+01 1.53363474e+00]
[3.30000000e+01 4.53420000e+01 1.57171329e+00]
[3.40000000e+01 4.67160000e+01 1.60849049e+00]
[3.50000000e+01 4.80900000e+01 1.64390417e+00]
[3.60000000e+01 4.94640000e+01 1.67789216e+00]
[3.70000000e+01 5.08380000e+01 1.71039230e+00]
[3.80000000e+01 5.22120000e+01 1.74134241e+00]
[3.90000000e+01 5.35860000e+01 1.77068035e+00]
[4.00000000e+01 5.49600000e+01 1.79834394e+00]
[4.10000000e+01 5.63340000e+01 1.82427101e+00]
[4.20000000e+01 5.77080000e+01 1.84839941e+00]
[4.30000000e+01 5.90820000e+01 1.87066696e+00]
[4.40000000e+01 6.04560000e+01 1.89101151e+00]
[4.50000000e+01 6.18300000e+01 1.90937088e+00]
[4.60000000e+01 6.32040000e+01 1.92570604e+00]
[4.70000000e+01 6.45780000e+01 1.94056076e+00]
[4.80000000e+01 6.59520000e+01 1.95421968e+00]
[4.90000000e+01 6.73260000e+01 1.96719695e+00]
[5.00000000e+01 6.87000000e+01 1.97928362e+00]
[5.10000000e+01 7.00740000e+01 1.98942207e+00]
[5.20000000e+01 7.14480000e+01 1.99700320e+00]
[5.30000000e+01 7.28220000e+01 2.00180807e+00]
[5.40000000e+01 7.41960000e+01 2.00361776e+00]
[5.50000000e+01 7.55700000e+01 2.00221333e+00]
[5.60000000e+01 7.69440000e+01 1.99737586e+00]
[5.70000000e+01 7.83180000e+01 1.98888640e+00]
[5.80000000e+01 7.96920000e+01 1.97652604e+00]
[5.90000000e+01 8.10660000e+01 1.96007583e+00]
[6.00000000e+01 8.24400000e+01 1.93931685e+00]
[6.10000000e+01 8.38140000e+01 1.91403017e+00]
[6.20000000e+01 8.51880000e+01 1.88497097e+00]
[6.30000000e+01 8.65620000e+01 1.85740456e+00]
[6.40000000e+01 8.79360000e+01 1.83466390e+00]
[6.50000000e+01 8.93100000e+01 1.81970145e+00]
[6.60000000e+01 9.06840000e+01 1.81546971e+00]
[6.70000000e+01 9.20580000e+01 1.82177337e+00]
[6.80000000e+01 9.34320000e+01 1.82842946e+00]
[6.90000000e+01 9.48060000e+01 1.83439551e+00]
[7.00000000e+01 9.61800000e+01 1.83969621e+00]
[7.10000000e+01 9.75540000e+01 1.84435625e+00]
[7.20000000e+01 9.89280000e+01 1.84840034e+00]
[7.30000000e+01 1.00302000e+02 1.85185316e+00]
[7.40000000e+01 1.01676000e+02 1.85473940e+00]
[7.50000000e+01 1.03050000e+02 1.85708377e+00]
[7.60000000e+01 1.04424000e+02 1.85891096e+00]
[7.70000000e+01 1.05798000e+02 1.86024566e+00]
[7.80000000e+01 1.07172000e+02 1.86111256e+00]
[7.90000000e+01 1.08546000e+02 1.86153636e+00]
[8.00000000e+01 1.09920000e+02 1.86154176e+00]
[8.10000000e+01 1.11294000e+02 1.86115344e+00]
[8.20000000e+01 1.12668000e+02 1.86039610e+00]
[8.30000000e+01 1.14042000e+02 1.85929444e+00]
[8.40000000e+01 1.15416000e+02 1.85787402e+00]
[8.50000000e+01 1.16790000e+02 1.85624017e+00]
[8.60000000e+01 1.18164000e+02 1.85445481e+00]
[8.70000000e+01 1.19538000e+02 1.85252055e+00]
[8.80000000e+01 1.20912000e+02 1.85043999e+00]
[8.90000000e+01 1.22286000e+02 1.84821574e+00]
[9.00000000e+01 1.23660000e+02 1.84585039e+00]
[9.10000000e+01 1.25034000e+02 1.84334656e+00]
[9.20000000e+01 1.26408000e+02 1.84070685e+00]
[9.30000000e+01 1.27782000e+02 1.83793385e+00]
[9.40000000e+01 1.29156000e+02 1.83503019e+00]
[9.50000000e+01 1.30530000e+02 1.83199845e+00]
[9.60000000e+01 1.31904000e+02 1.82884125e+00]
[9.70000000e+01 1.33278000e+02 1.82556119e+00]
[9.80000000e+01 1.34652000e+02 1.82216087e+00]
[9.90000000e+01 1.36026000e+02 1.81864290e+00]
[1.00000000e+02 1.37400000e+02 1.81500988e+00]
[1.01000000e+02 1.38774000e+02 1.81126441e+00]
[1.02000000e+02 1.40148000e+02 1.80740911e+00]
[1.03000000e+02 1.41522000e+02 1.80344657e+00]
[1.04000000e+02 1.42896000e+02 1.79937940e+00]
[1.05000000e+02 1.44270000e+02 1.79521020e+00]
[1.06000000e+02 1.45644000e+02 1.79094157e+00]
[1.07000000e+02 1.47018000e+02 1.78657613e+00]
[1.08000000e+02 1.48392000e+02 1.78211648e+00]
[1.09000000e+02 1.49766000e+02 1.77756521e+00]
[1.10000000e+02 1.51140000e+02 1.77292494e+00]
[1.11000000e+02 1.52514000e+02 1.76819827e+00]
[1.12000000e+02 1.53888000e+02 1.76338780e+00]
[1.13000000e+02 1.55262000e+02 1.75849613e+00]
[1.14000000e+02 1.56636000e+02 1.75352588e+00]
[1.15000000e+02 1.58010000e+02 1.74847964e+00]
[1.16000000e+02 1.59384000e+02 1.74336002e+00]
[1.17000000e+02 1.60758000e+02 1.73816962e+00]
[1.18000000e+02 1.62132000e+02 1.73291105e+00]
[1.19000000e+02 1.63506000e+02 1.72758692e+00]
[1.20000000e+02 1.64880000e+02 1.72219982e+00]
[1.21000000e+02 1.66254000e+02 1.71675236e+00]
[1.22000000e+02 1.67628000e+02 1.71124714e+00]
[1.23000000e+02 1.69002000e+02 1.70568677e+00]
[1.24000000e+02 1.70376000e+02 1.70007386e+00]
[1.25000000e+02 1.71750000e+02 1.69441100e+00]
[1.26000000e+02 1.73124000e+02 1.68870081e+00]
[1.27000000e+02 1.74498000e+02 1.68294588e+00]
[1.28000000e+02 1.75872000e+02 1.67714882e+00]
[1.29000000e+02 1.77246000e+02 1.67131224e+00]
[1.30000000e+02 1.78620000e+02 1.66543873e+00]
[1.31000000e+02 1.79994000e+02 1.65953091e+00]
[1.32000000e+02 1.81368000e+02 1.65359138e+00]
[1.33000000e+02 1.82742000e+02 1.64762273e+00]
[1.34000000e+02 1.84116000e+02 1.64162758e+00]
[1.35000000e+02 1.85490000e+02 1.63560853e+00]
[1.36000000e+02 1.86864000e+02 1.62956819e+00]]

How to fix "Key Error :'not in index' " error in Jupyter Notebooks

The code is to plot the colored graph of the total number of cases in red and recovered cases in green.
There is a key error of not in the index, I checked the spelling and also the syntax, Stil can't find the solution.
#Visulizating Data using Seaborn
f, ax = plt.subplots(figsize=(12, 8))
data = df_full[['Name of the State / UT', 'Total Confirmed Cases (Indian National)', 'Recovered',
'Deaths']]
data.sort_values('Total cases', ascending=False, inplace=True)
sns.set_color_codes("pastel")
sns.barplot(x="Total Confirmed Cases (Indian National)", y="Name of the State / UT",
data=data,lable="Total", color="r")
sns.set_color_codes("muted")
sns.barplot(x="Recovred", y="Name of the State / UT", data=data,label="Reccovered", color="g")
#ADD a legend and informative axis label
ax.legend(ncol=2, loc="lower right", frameon=True)
ax.set(xlim=(0, 35), ylabel="", xlabel="Cases")
sns.despine(left=True, bottom=True)
**ERROR**
KeyError: "['Name of the State / UT'] not in index"

Aspect ration of a image for instagram

i want to change the aspect ratio of an image for the instagram with python .here is my code for change the aspact ration :
width,height=imageFile.size
aspectRatio = width/height
if(aspectRatio>=0.80 and aspectRatio<=1.90):
print("yeah")
else:
if(height>width):
futureHeight = width/.85
print(str(width)+" ,"+str(futureHeight))
print(width/futureHeight)
left = 0
int(futureHeight)
teetet = height-futureHeight/2
top = teetet / 4
right = width
bottom = height -150
im1 = imageFile.crop((left, top, right, bottom))
print(im1.size)
im1.show()
im1.save(image)
but still it show
ValueError: Incompatible aspect ratio.
whenever i try to upload this image
i resolved that using basic dimensions. using the inspector i saw that instagram convert images to 598.02x598.02 in the home page, so i typed:
im=PIL.Image.open(path)
im=im.resize((598,598), Image.ANTIALIAS)
im.save(path) # overwrite the image
instead of
im=PIL.Image.open(path)
baseheight = 560
hpercent = (baseheight / float(im.size[1]))
wsize = int((float(im.size[0]) * float(hpercent)))
im=im.resize((wsize, baseheight), PIL.Image.ANTIALIAS)
im.save(path)
in wich aspect ratio is out of range anyway.
now you can post it using something like instabot without troubles 'cause the aspect ratio is 1.0 .

Python 3D image segmentation find local peaks in distance map for watershed

I am trying to segment 3d tomographs of porous networks in python. I am able to calculate the distance map with ndimage.distance_transform_edt and the peaks with feature.peak_local_max. when I apply the watershed algorithm a get an acceptable result, but the markers of the peaks are not located at the visible peaks, see image, of the distance map
Thanks in advance
Here the code a is the image
D = ndimage.distance_transform_edt(a)
localMax = feature.peak_local_max(D, indices=False, min_distance=50,
labels=a)
localMax2 = feature.peak_local_max(D, indices=True, min_distance=50,
labels=a)
markers = ndimage.label(localMax, structure=np.ones((3,3,3)))[0]
labels = morphology.watershed(-D,markers,mask=a)
I found a way:
i had to exclude the borders and apply a threshold
D = ndimage.distance_transform_edt(a)
localMax = feature.peak_local_max(D, indices=False, min_distance=30,
labels=a,threshold_abs=9,exclude_border=1)
localMax2 = feature.peak_local_max(D, indices=True, min_distance=30,
labels=a,threshold_abs=9,exclude_border=1)
#markers = ndimage.label(localMax, structure=np.ones((3,3,3)))[0]
markers = ndimage.label(localMax, structure=np.ones((3,3,3)))[0]
labels = morphology.watershed(-D,markers,mask=a)
regions=measure.regionprops(labels,intensity_image=a)

How to increase resolution of gif image?

How to increase resolution of gif image generated by rgl package of R (plot3d and movie3d functions) - either externally or through R ?
R Code :
MyX<-rnorm(10,5,1)
MyY<-rnorm(10,5,1)
MyZ<-rnorm(10,5,1)
plot3d(MyX, MyY, MyZ, xlab="X", ylab="Y", zlab="Z", type="s", box=T, axes=F)
text3d(MyX, MyY, MyZ, text=c(1:10), cex=5, adj=1)
movie3d(spin3d(axis = c(0, 0, 1), rpm = 4), duration=15, movie="TestMovie",
type="gif", dir=("~/Desktop"))
Output :
Update
Adding this line at the beginning of code solved the problem
r3dDefaults$windowRect <- c(0, 100, 1400, 1400)
I don't think you can do much about the resolution of the gif itself. I think you have to make the image much larger as an alternative, and then when you display it smaller it looks better. This is untested as a recent upgrade broke a thing or two for me, but this did work under 2.15:
par3d(windowRect = c(0, 0, 500, 500)) # make the window large
par3d(zoom = 1.1) # larger values make the image smaller
# you can test your settings interactively at this point
M <- par3d("userMatrix") # save your settings to pass to the movie
movie3d(par3dinterp(userMatrix=list(M,
rotate3d(M, pi, 1, 0, 0),
rotate3d(M, pi, 0, 1, 0) ) ),
duration = 5, fps = 50,
movie = "MyMovie")
HTH. If it doesn't quite work for you, check out the functions used and tune up the settings.

Resources