Is there an efficient way of applying a radial average in keras? - python

I would like to apply a radial average at the end of a keras pipeline.
At the second to last step, I have an image of size n x n. I then want to map this n x n image to a 1 x n/2 vector, where vector[x] = mean(image(radialPosition = x)). I.e. I want to average all points of distance X from the center of the image, and set this as output[x]. We can assume that n is odd, so the center point is a single point.
I have considered looping over all radii, and selecting the desired indices, as well as a dot product between the image and multiple "averaging" matrices, but neither of these seem computationally efficient.
Is there a better way of doing this?

Related

Can this be done faster with numpy?

There's a color image, a numpy array of shape (h,w,3) with N=h*w pixels; there's an array labels of shape (h,w), each label an integer between 1 and M. N is 10^6-10^7, M is 10^3-10^4.
I need to produce
a result image (h,w,3) where the color of each pixel labelled l is the mean color of all pixels labelled l. I.e.:
def recolor1(image, labels):
result = np.empty(shape=(h,w,3))
for label in np.unique(labels):
mask = labels==label
mean = np.mean(image[mask], axis=0)
result[mask] = mean
return result
The code is straightforward, but runs in O(M.N) (the computation of mask is O(N) and the loop runs M times).
An O(N) recolor2 is possible. Basically you go over the labels and image pixels twice. First to compute an auxiliary array, indexed by label, where you keep the sums of each primary and the number of pixels for that label. Then you compute the averages for each label. Then you go over labels and pixels again, computing result. The O(M) time to find the averages is noise.
With recolor2 written in Python, recolor1 and recolor2 break even for N=1000000 and M=1000 at ~4s. As expected, recolor1's time grows linearly to ~20s for M=5000, while recolor2's remains essentially the same.
4s for a relatively small image is not great and it will get much worse for larger images. I'm no expert in numpy and associated libraries. Is there an O(N) solution there?
Let's try np.bincount and loop over the channels:
result = np.stack([np.bincount(labels.flat, weights=img[...,i].flat)[labels-1]
for i in range(3)],
axis=-1)
which takes about 35ms on my system with h,w,M = 1000,1000,1000.
Note This compute the sum, but mean should be easy enough.

Computing 3D-homography with 5 3D-points

I've got a set of 3D-points in a projective space and I want to transform them into a metric 3D space so that I could measure distances in meters.
In order to do so, I need a 3D to 3D homography, which is a 4x4 matrix with 15 degrees of freedom (so I need 5 3D-points to get 15 equations).
I have a set of these 5 3D-points from the projective space and their corresponding 5 3D-points aligned in the metric space (which I expect the 5 projective points to be transformed to).
I can't figure out how to estimate the homography matrix. At first I tried:
A=np.vstack([p1101.T, p1111.T, p0101.T, p0001.T, p0011.T])
b=np.array([[1,1,0,1], [1,1,1,1], [0,1,0,1], [0,0,0,1], [0,0,1,1]])
x, _, _, _ = np.linalg.lstsq(A,b)
H = x.T
where p1101 is a [X,Y,Z,1] point which corresponds to [1,1,0,1] in the 3D metric space, etc..
However, this is not correct since I'm in projective space, so I need to create somehow an equation set where I divide the rows of H with its last or something like that.
I thought maybe there is an implemented method that will do it for me, for example in opencv, but didn't find. Any help would be appreciated.
I finally solved this question with a friend, and would like to share the solution.
Since in projective space, one needs to solve an equation set where the homogene coordinate of the outcome is the denominator of each other coordinate. i.e, if you want to find a 4x4 homography matrix H, and you have matching 3D points x and b (b is in the meteric space), you'll need to optimize the search of H parameters such that H applied on x will give a vector v with 4 coordinates, such that all the first three coordinates of v divided by the last coordinate are b. written in numpy:
v = H.dot(x)
v = v[:3]/v[3]
v == b # True
mathematically, the optimization is based on this (this is focused on the first coordinate only, for simplicity, but other coordinates are done the same way):
so in python one needs to arrange the equations for the solver in the explained manner, with 5 matching points. The way that was purposed in the question is good (just didn't solve the right problem), and in these terms it will make Ax=b least squares optimization such that A is 15x15 matrix, and b is a 15 dimensional vector.
Each matching point generates 3 equations, then 5 matching points will generate 15 equations built into the matrix A, thus solving the 15 DOF of the 3D homography H.

Finding the nearest neighbours for a subset of samples

I have a dataset of about 3 million samples (each with just 3 features). I'm using scikit's sklearn.neighbors module - specifically radius_neighbor_graph - to find which samples fall within a small radius of a specific sample.
This works fine, but unsurprisingly it's really, really slow to compute this graph.
It's also very wasteful, because I only ever need to know the neighbors for a small subset of my samples (~ 100,000 of them) - and I know this subset in advance.
So... is there any way of being more efficient by calculating the neighbours within a given radius for just this subset of samples? It seems like it should be simple, but I can't think of an easy way of doing it.
First of all, the task of creating a radius-neighborhood-graph involves reading the N by N distance-matrix associated to your dataset. Since distance matrices have nice properties you can save some time, but still complexity lies somewhere in O(N^2). Here N is the number of data points in your data set X.
So one could say, that only a small number of n < N points are of interest as the center of a neighborhood, but the majority of points are just interesting as neighbors. This would result in an n by N distance matrix, where row i contains the distances of data point i to each other data point j, 1 <= i <= n, 1 <= j <= N. But this "distance matrix" has none of the desirable properties of a normal distance matrix (it is not even a square matrix), that you could use to speed up the process of creating an epsilon-neighborhood-graph.
Therefore I don't think that you find a predefined function for your case. If you want to build one your own, the steps should be as follows: Let X be your data set and i be the data point of interest.
Create the distance matrix D associated to your data set, use scipy.spatial.distance_matrix and take as x the small subset of your data set and as y the whole data set.
Create a list, neighbors = []
Loop over the i'th row of the distance matrix. If D(i,j) < epsilon, then save j in neighbors. It is the index of a data point in the epsilon neighborhood of i.
Return neighbors
Of course the computation of the distance matrix should happen once at the beginning (maybe in init() if you wrap everything up in a class), and the function/method that returns all epsilon neighbors of a data point should only depend on the index of the data point in question.
Hope this helps!

Calculating the Angle Between Vectors by using a vector as a reference point:

I have been trying to find a fast algorithm of calculating all the angle between n vectors that are of length x. For example if x=3 and n=4, my data would look something like this:
A: [1,2,3]
B: [2,3,4]
C: [...]
D: [...]
I was wondering is it acceptable to find the the angle between all of be vectors (A,B,C,D) with respect to some fix vector (i.e. X:[100,100,100,100]) and then the subtract the angles of (A,B,C,D) found with respect to that fixed value, to find the angle between all of them. I want to do this because I would only have to compute the angle once and then I can subtract angles all of my vectors to find the different between them. In short, I want to know is it safe to make this assumption?
angle_between(A,B) == angle_between(A,X) - angle_between(B,X)
and the angle_between function is the Cosine similarity.
That approach will only work for 2-D vectors. For higher dimensions any two vectors will define a hyperplane, and only if the third (reference) vector also lies within this hyperplane will your approach work. Unfortunately instead of only calculating n angles and subtracting, in order to determine the angles between each pair of vectors you would have to calculate all n choose 2 of them.

Numpy Array python dimension uniform

I have 2 dimensional array with 15 elements in one dimension and variable length in second dimension
for example
>>print abc.size()
15
>>print abc[0].size()
5873
>>print abc[1].size()
9825
How can i make array dimensions uniform either using numpy or skikit sparse array. the data is hog features of an image.
Assuming you want to align all the arrays to the left, and pad to the right with zeros, then you could first find the maximum length with
max_len = max([abc[i].size() for for i in range(abc.size())])
and then pad using zeros:
import numpy as np
for i in range(abc.size()):
abc[i] = np.append(abc[i], np.zeros(max_len - abc[i].size())
We have here two possible cases:
abc is a list of images, and for each image abc[i] is the set of hog features of the image i.
abc is one image and each abc[i] is the i-th hog feature of the image
For the first case, the image sizes or the hog parameters (size for the neighbour) differ from one image to another, so you need to adjust the parameters in order to calculate the hog features properly for all the images (if you want fixed sized descriptors).
For the second case, your hog computation is not correct (it shouldn't happen that the sizes of the hog descriptors are different for the same image).
So, in any of the cases, there is no way of resizing your arrays. You need to fix your hog computations.
Edit: related to your problem, you have a dataset of different size images. The are two possible common approaches for image classification with hog descriptors. But first, a quick summary of HOG:
HOG splits the image in M x N windows of size m x n each and calculates a histogram oriented gradients with fixed W number of bins (number of orientations) in that window. Hence, you will end up with M x N x W features. Features are usually flattened in a 2D vector of size K x W with K = M x N.
Now, for classification there are 2 common approaches:
Combine all the features of an image in one, this is, perform an average (or weighted average or norm) over the K features to end up with a vector of size W for each image (the number of orientations).
To preserve (more or less) the spatial relationship of the features, another more common approach is to concatenate all the features in order to end up with a flattened 1D vector of size Z, with Z = K x W/
From your data, I think you are trying to perform the 2nd step. The problem you are facing is that the images have different size, and therefore, for a fixed window size m x n the number of features differ from one image to another.
The way you could fix that, is by fixing the number of features M x N you want, and for a given image, calculate m = height / M and n = width / N and calculate the HOG descriptors with that custom m x n window size (which is different for every image). This way, you will end up with an K = M x N vector with the same K (but different window size) for every image.
With a fixed K and therefore fixed Z you would be able to perform classification.
I don't know which library are you using for computing the HOG, but m x n window size parameter should be easy to manually set up for every image.
Hope it helps!

Categories

Resources