Find Eucledian distance between landmarks of faces - python

I've got multiple frames and I've detected the faces in each frame using Retinaface. I would like to keep track of the faces using their landmarks.
To find the similarity between 2 landmarks, I tried to calculate the Eucledian distance :
Input :
landmark_1 = [1828, 911], [1887, 913], [1841, 942], [1832, 974], [1876, 976]
landmark_2 = [1827, 928], [1887, 926], [1848, 963], [1836, 992], [1884, 990]
After referring other links, I wrote the below function, but the values produced are very high :
def euclidean_dist(vector_x, vector_y):
vector_x, vector_y = np.array(vector_x), np.array(vector_y)
if len(vector_x) != len(vector_y):
raise Exception('Vectors must be same dimensions')
ans = sum((vector_x[dim] - vector_y[dim]) ** 2 for dim in range(len(vector_x)))
return np.sqrt(np.sum(ans**2))
Output :
euclidean_dist(landmark_1, landmark_2)
>> 1424.9424549784458
(Expecting some smaller value in this case)
I guess the code can only be used for an one dimensional vector, but I'm really stuck here. Any help would be really appreciated.

It looks like you're squaring the answer twice (ans**2). But you can also simplify the function somewhat:
def euclidean_dist(vector_x, vector_y):
vector_x, vector_y = np.array(vector_x), np.array(vector_y)
return np.sqrt(np.sum((vector_x - vector_y)**2, axis=-1))
This will automatically raise an exception when the vectors are incompatible shapes.
EDIT: If you use axis=-1 it will sum over the last axis of the array, so you can use a 2-D array of vectors, for example.

You can use linalg.nor too.
def euclidean_dist(vector_x, vector_y):
distances = np.linalg.norm(np.array(vector_x)-np.array(vector_y), axis=1)
return distances.tolist()

Related

Is there something wrong with my Python Hamming distance code?

I am trying to implement the Hamming distance in Python. Hamming distance is typically used to measure the distance between two codewords. The operation is simply performing exclusive OR. For example, if we have the codewords 10011101 and 10111110, then their exclusive OR would be 00100011, and the Hamming distance is said to be 1 + 1 + 1 = 3.
My code is as follows:
def hamming_distance(codeword1, codeword2):
"""Calculate the Hamming distance between two bit strings"""
assert len(codeword1) == len(codeword2)
x, y = int(codeword1, 2), int(codeword2, 2) # '2' specifies that we are reading a binary number
count, z = 0, x^y
while z:
count += 1
z &= z - 1
return count
def checking_codewords(codewords, received_data):
closestDistance = len(received_data) # set default/placeholder closest distance as the maximum possible distance.
closestCodeword = received_data # default/placeholder closest codeword
for i in codewords:
if(hamming_distance(i, received_data) < closestDistance):
closestCodeword = i
closestDistance = hamming_distance(i, received_data)
return closestCodeword
print(checking_codewords(['1010111101', '0101110101', '1110101110', '0000000110', '1100101001'], '0001000101'))
hamming_distance(codeword1, codeword2) takes the two input parameters codeword1 and codeword2 in the form of binary values and returns the Hamming distance between the two input codewords.
checking_codewords(codewords, received_data) should determine the correct codeword IFF there are any errors in received data (i.e., the output is the corrected codeword string). Although, as you can see, I haven't added the "IFF there are any errors in received data" part yet.
I just tested the checking_codewords function with a set of examples, and it seems to have worked correctly for all of them except one. When I use the set of codewords ['1010111101', '0101110101', '1110101110', '0000000110', '1100101001'] and the received data '0001000101' the output is 0101110101, which is apparently incorrect. Is there something wrong with my code, or is 0101110101 actually correct and there is something wrong with the example? Or was this just a case where there was no error in the received data, so my code missed it?
For my point of view, is not clear why your algorithm transforms the initial string into an integer to do a bitwise difference.
I mean, after the assert the equal length you can simply compute the difference using the zip function:
sum([c1!=c2 for c1,c2 in zip(codeword1,codeword2)])
For sum function, python consider True==1, False==0.
Doing a little simplification on your code:
def hamming_distance(codeword1, codeword2):
"""Calculate the Hamming distance between two bit strings"""
assert len(codeword1) == len(codeword2)
return sum([c1!=c2 for c1,c2 in zip(codeword1,codeword2)])
def checking_codewords(codewords, received_data):
min_dist, min_word = min([(hamming_distance(i, received_data), received_data) for i in codewords])
return min_word
print(checking_codewords(['1010111101', '0101110101', '1110101110', '0000000110', '1100101001'], '0001000101'))

How to remove the mean of some values in the 3rd dimension of a matrix?

I have been stuck trying to do this with numpy with no luck. I am trying to move from MATLAB to Python, however, the transition hasn't been so easy. Anyway, that doesn't matter.
I am trying to code the Python analog of this simple MATLAB line of code:
A(:,:,condtype==1 & Mat(:,9)==contra(ii)) = A(:,:, condtype ==1 & Mat(:,9)==contra(ii))-mean(A(:,:, condtype ==1 & Mat(:,9)==contra(ii)),3);
Right, so the above convoluted line of code does the following. Indexes a condition which is half of the 3rd dimension of A and removes the mean of those indexes which simultaneously changing the values in A to the new mean removed values.
How would one go about doing this in Python?
I actually figured it out. I was trying to use and when I should have been using np.isequal. Also, I needed to use keepdims=True for the mean. Here it is for anyone that wants to see:
def RmContrastMean(targettype,trialsMat,Contrastlvls,dX):
present = targettype==1
absent = targettype==0
for i in range(0,Contrastlvls.size):
CurrentContrast = trialsMat[:,8]==Contrastlvls[i]
preIdx = np.equal(present, CurrentContrast)
absIdx = np.equal(absent, CurrentContrast)
#mean
dX[:,:,preIdx] = dX[:,:,preIdx]-np.mean(dX[:,:,preIdx],axis=2,keepdims=True)
dX[:,:,absIdx] = dX[:,:,absIdx]-np.mean(dX[:,:,absIdx],axis=2,keepdims=True)
#std
dX[:,:,preIdx] = dX[:,:,preIdx]/np.std(dX[:,:,preIdx],axis=2,keepdims=True)
dX[:,:,absIdx] = dX[:,:,absIdx]/np.std(dX[:,:,absIdx],axis=2,keepdims=True)
return dX

Using Values from Lists in an equation/loop

I have a short list with coordinates: (0|0) (10|0) (10|10) (0|10). Im trying to use these coordinates to calculate the area of the square they build.
for loop should run 4 times and perfom the math written below.
when running i get the following error in the area = .... line:
TypeError: 'int' object is not subscriptable
list = [[0,10,10,0],[0,0,10,10]]
def gaussarea(coords):
area = 0
for coords in coords:
area = area + (coords[0][0] - coords[0][1]) * (coords[1][0]+coords[1][1])
return area
a = (gaussarea(list))
You are trying to access the index of an int, which is meaningless, since each coords is a list, not a nested list.
Assuming you get a rectangle (or square) for sure, you are good enough with
def gaussarea(coords):
area = (coords[0][1] - coords[0][0]) * (coord[1][2] - coords[1][1])
return area
the value of cords[0] is an int. Therefore cords[0][0] is trying to index into an int, hence your error. You can remove the for loop and your code should work.

How to reconstruct an image that has been divided into several pieces?

I'm trying to write a code which gets the pieces of an image, that are represented by an m X m matrix. two pieces belong together if the right side of the matrix of one piece is the same as the left side of the other piece, these two pieces should be "glued".
I wrote the function join which joins two pictures together, I started writing the puzzle solving function but I got stuck and I don't know how to continue.
def join_h(mat1, mat2):
""" joins two matrices, side by side with some separation """
n1,m1 = mat1.dim()
n2,m2 = mat2.dim()
m = m1+m2+10
n = max(n1,n2)
new = Matrix(n, m, val=255) # fill new matrix with white pixels
new[:n1,:m1] = mat1
new[:n2,m1+10:m] = mat2
'''
#without slicing:
for i in range(n1):
for j in range(m1):
new[i,j] = mat1[i,j]
for i in range(n2):
for j in range(m2):
new[i,j+m1+10] = mat2[i,j]
'''
return new
def reconstruct_image(m):
matlst=getlistmatrix()
for i in range(len(matlst)):
if matlst[i][i]==matls[i+1][i+1]
def getlistmatrix():
matrixlst=[]
for i in range(1,1601):
matrixlst.append(Matrix.load('./im'+str(i) +'.bitmap'))
return matrixlst
scikit-learn library provides you with the function 'reconstruct_from_patches_2d' - sklearn.feature_extraction.image.reconstruct_from_patches_2d
If you know the order of the overlapping blocks, then you should be able to use this.
Refer: http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.image.reconstruct_from_patches_2d.html#sklearn.feature_extraction.image.reconstruct_from_patches_2d
An example provided by them for the same - http://scikit-learn.org/stable/auto_examples/decomposition/plot_image_denoising.html#example-decomposition-plot-image-denoising-py

getting more precise answer in python

I am trying to implement a simple formula with python . In the case of "RLSR" there two approach to calculate the coefficient "C" by C=k^-1*y where k is the kernel matrix and y is the target value vector.
The second way is by using eigenvalues(w) and eigenvectors(v) of the kernel method and using formula :
Sum(u(i)*<u(i),y> / w(i) ).
to check the answer of the result I'm checking whether y=kc or not! in the first case it's ok , but the latter case it's not.but the problem is my c vectors in both method look the same.
output from invers algorithm :
[ 19.49840251 18.82695226 20.08390355 15.01043404 14.79353281
16.75316736 12.88504257 16.92127176 16.77292954 17.81827473
20.90503787 17.09359467 18.76366701 18.14816903 20.03491117
22.56668264 21.45176136 25.44051036 30.40312692 22.61466379
22.86480382 19.34631818 17.0169598 19.85244414 16.63702471
20.35280156 20.58093488 22.42058736 20.54935198 19.35541575
20.39006958 19.74766081 20.41781019 22.33858797 17.57962283
22.61915219 22.54823733 24.96292824 22.82888425 34.18952603
20.7487537 24.82019935 22.40621769 21.15767304 27.58919263
18.39293156 21.55455108 18.69532341]
output from second(eigendecomposition ) algorithm :
[ 19.25280289 18.73927731 19.77184991 14.7650427 14.87364331
16.2273648 12.29183797 16.52024239 16.66669961 17.59282615
20.83059115 17.02815857 18.3635798 18.16931845 20.50528549
22.67690164 21.40479524 25.54544 30.94618128 22.72992565
23.06289609 17.6485592 15.2758427 19.50578691 16.45571607
20.19960765 20.35352859 22.60091638 20.36586912 18.90760728
20.57141151 19.43677153 20.43437031 22.39310576 17.72296978
22.82139991 22.50744791 25.10496617 22.30462867 34.80540213
20.77064617 25.18071618 22.5500315 20.71481252 27.91939784
18.29868659 22.00800019 18.71266093]
this how I have implemented it:
so let say if we have 48 samples the size of K is 48x48 , y is 48x1
def cpu_compute(y,k):
w, u=LA.eigh(k)
uDoty=np.dot(u,y)
temp=np.transpose(np.tile(w,(len(u),1)))
div=np.divide(u,temp)
r=np.tile(uDoty,(len(div),1))
a=div*r.T
c=sum(a)
return c
and the result from
print np.allclose(Y,np.dot(K,c))
is false.
also the norm of difference from the true result is 3.13014997999.
now I have no idea how can I fix this . I thought maybe some how by doing more precise answer.
Appreciate any help!
To solve k c = y with numpy, use numpy.linalg.solve:
c = solve(k, y)
This uses an algorithm that is much more robust than the methods you are trying.

Categories