Bilinear image interpolation / scaling - A calculation example - image
I would like to ask you about some bilinear interpolation / scaling details. Let's assume that we have this matrix:
|100 | 50 |
|70 | 20 |
This is a 2 x 2 grayscale image. Now, I would like scale it by factor of two and my matrix looks like this:
| 100 | f1 | 50 | f2 |
| f3 | f4 | f5 | f6 |
| 70 | f7 | 20 | f8 |
so if we would like to calculate f4, the calculation is defined as
f1 = 100 + 0.5(50 - 100) = 75
f7 = 70 + 0.5(20 - 70) = 45
and now finally:
f4 = 75 + 0.5(45 - 75) = 60
However, I can't really understand what calculations are proper for f3 or f1
Do we do the bilinear scaling in each direction separately? Therefore, this would mean that:
f3 = 100 + 0.5(70 - 100) = 85
f1 = 100 + 0.5(50 - 100) = 75
Also, how should I treat f2, f6, f8. Are those points simply being copied like in the nearest neighbor algorithm?
I would like to point you to this very insightful graphic from Wikipedia that illustrates how to do bilinear interpolation for one point:
Source: Wikipedia
As you can see, the four red points are what is known. These points you know before hand and P is the point we wish to interpolate. As such, we have to do two steps (as you have indicated in your post). To handle the x coordinate (horizontal), we must calculate what the interpolated value is row wise for the top row of red points and the bottom row of red points. This results in the two blue points R1 and R2. To handle the y coordinate (vertical), we use the two blue points and interpolate vertically to get the final P point.
When you resize an image, even though we don't visually see what I'm about to say, but imagine that this image is a 3D signal f. Each point in the matrix is in fact a 3D coordinate where the column location is the x value, the row location is the y value and the z value is the quantity / grayscale value of the matrix itself. Therefore, doing z = f(x,y) is the value of the matrix at location (x,y) in the matrix. In our case, because you're dealing with images, each value of (x,y) are integers that go from 1 up to as many rows/columns as we have depending on what dimension you're looking at.
Therefore, given the coordinate you want to interpolate at (x,y), and given the red coordinates in the image above, which we call them x1,y1,x2,y2 as per the diagram - specifically going with the convention of the diagram and referencing how images are accessed: x1 = 1, x2 = 2, y1 = 2, y2 = 1, the blue coordinates R1 and R2 are computed via 1D interpolation column wise using the same row both points coincide on:
R1 = f(x1,y1) + (x - x1)/(x2 - x1)*(f(x2,y1) - f(x1,y1))
R2 = f(x1,y2) + (x - x1)/(x2 - x1)*(f(x2,y2) - f(x1,y2))
It's important to note that (x - x1) / (x2 - x1) is a weight / proportion of how much of a mix the output consists of between the two values seen at f(x1,y1) and f(x2,y1) for R1 or f(x1,y2) and f(x2,y2) for R2. Specifically, x1 is the starting point and (x2 - x1) is the difference in x values. You can verify that substituting x1 as x gives us 0 while x2 as x gives us 1. This weight fluctuates between [0,1] which is required for the calculations to work.
It should be noted that the origin of the image is at the top-left corner, and so (1,1) is at the top-left corner. Once you find R1 and R2, we can find P by interpolating row wise:
P = R2 + (y - y2)/(y2 - y1)*(R1 - R2)
Again, (y - y2) / (y2 - y1) denote the proportion / mix of how much R1 and R2 contribute to the final output P. As such, you calculated f5 correctly because you used four known points: The top left is 100, top right is 50, bottom left is 70 and bottom right is 20. Specifically, if you want to compute f5, this means that (x,y) = (1.5,1.5) because we're halfway in between the 100 and 50 due to the fact that you're scaling the image by two. If you plug in these values into the above computation, you will get the value of 60 as you expected. The weights for both calculations will also result in 0.5, which is what you got in your calculations and that's what we expect.
If you compute f1, this corresponds to (x,y) = (1.5,1) and if you substitute this into the above equation, you will see that (y - y2)/(y2 - y1) gives you 0 or the weight is 0, and so what is computed is just R2, corresponding to the linear interpolation along the top row only. Similarly, if we computed f7, this means we want to interpolate at (x,y) = (1.5,2). In this case, you will see that (y - y2) / (y2 - y1) is 1 or the weight is 1 and so P = R2 + (R1 - R2), which simplifies to R1 and is the linear interpolation along the bottom row only.
Now there's the case of f3 and f5. Those both correspond to (x,y) = (1,1.5) and (x,y) = (2,1.5) respectively. Substituting these values in for R1 and R2 and P for both cases give:
f3
R1 = f(1,2) + (1 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(1,2)
R2 = f(1,1) + (1 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,1)
P = R1 + (1.5 - 1)*(R1 - R2) = f(1,2) + 0.5*(f(1,2) - f(1,1))
P = 70 + 0.5*(100 - 70) = 85
f5
R1 = f(1,2) + (2 - 1)/(2 - 1)*(f(2,2) - f(1,2)) = f(2,2)
R2 = f(1,1) + (2 - 1)/(2 - 1)*(f(1,2) - f(1,1)) = f(1,2)
P = R1 + (1.5 - 1)*(R1 - R2) = f(2,2) + 0.5*(f(2,2) - f(1,2))
P = 20 + 0.5*(50 - 20) = 35
So what does this tell us? This means that you are interpolating along the y-direction only. This is apparent when we take a look at P. Examining the calculations more thoroughly of P for each of f3 and f5, you see that we are considering values along the vertical direction only.
As such, if you want a definitive answer, f1 and f7 are found by interpolating along the x / column direction only along the same row. f3 and f5 are found by interpolating y / row direction along the same column. f4 uses a mixture of f1 and f7 to compute the final value as you have already seen.
To answer your final question, f2, f6 and f8 are filled in based on personal preference. These values are considered to be out of bounds, with the x and y values both being 2.5 and that's outside of our [1,2] grid for (x,y). In MATLAB, the default implementation of this is to fill any values outside of the defined boundaries to be not-a-number (NaN), but sometimes, people extrapolate using linear interpolation, copy the border values, or perform some elaborate padding like symmetric or circular padding. It depends on what situation you're in, but there is no correct and definitive answer on how to fill in f2, f6 and f8 - it all depends on your application and what makes the most sense to you.
As a bonus, we can verify that my calculations are correct in MATLAB. We first define a grid of (x,y) points in the [1,2] range, then resize the image so that it's twice as large where we specify a resolution of 0.5 per point rather than 1. I'm going to call your defined matrix A:
A = [100 50; 70 20]; %// Define original matrix
[X,Y] = meshgrid(1:2,1:2); %// Define original grid of points
[X2,Y2] = meshgrid(1:0.5:2.5,1:0.5:2.5) %// Define expanded grid of points
B = interp2(X,Y,A,X2,Y2,'linear'); %// Perform bilinear interpolation
The original (x,y) grid of points looks like:
>> X
X =
1 2
1 2
>> Y
Y =
1 1
2 2
The expanded grid to expand the size of the matrix by twice as much looks like:
>> X2
X2 =
1.0000 1.5000 2.0000 2.5000
1.0000 1.5000 2.0000 2.5000
1.0000 1.5000 2.0000 2.5000
1.0000 1.5000 2.0000 2.5000
>> Y2
Y2 =
1.0000 1.0000 1.0000 1.0000
1.5000 1.5000 1.5000 1.5000
2.0000 2.0000 2.0000 2.0000
2.5000 2.5000 2.5000 2.5000
B is the output using X and Y as the original grid of points and X2 and Y2 are the points we want to interpolate at.
We get:
>> B
B =
100 75 50 NaN
85 60 35 NaN
70 45 20 NaN
NaN NaN NaN NaN
Related
Formula to get next question in quiz basing on previous statistics
My goal is to dynamically determine what question should be next in quiz by using statistics of previous answers So, I have: Question with difficulty field (1-100) Maximum score you can get in question (let it be 256) Score user have reached in question (x out of max) I want to somehow combine these paramaters in formula to choose most suitable next question for user How can I do it? My idea was to give user a question with median difficulty as first one and then check if user scored less than 50% of maximum, then get questions with 25 percentile difficulty else get 75 percentile. Then repeat this schema on a smaller stint (25-50 percentile or 50-75 percentile and so on)
Let's assume that the player has a fixed function score = f(difficulty) that gives for each difficulty the expected score percentage. Once we know this function, we can invert it and find the difficulty level that will give us the expected score we want. However, the function is not known. But we have samples of this function in the form of our previous questions. So, we can fit a function to these samples. If you have knowledge about the form of the dependence, you can include that knowledge in the shape of your fitted function. I will simply assume a truncated linear function: score = f(difficulty) = max(0, min(m * difficulty + n, 1)) The two parameters that we need to find are m and n. If we remove all sample questions where the user scored 100% or 0%, we can ignore the truncation. Then, we have a list of samples that form a linear system of equations: score1 = m * difficulty1 + n score2 = m * difficulty2 + n score3 = m * difficulty3 + n ... This system will usually not have a solution. So, we can solve for a least-squares solution. To do this, we will incrementally build a 2x2 matrix A and a 2-dimensional vector b that represent the system A * x = b. We will start with the zero matrix and the zero vector. For each question, we will update: / A11 A12 \ += / difficulty * difficulty difficulty \ \ A21 A22 / \ difficulty 1 / / b1 \ += / difficulty * score \ \ b2 / \ score / Once we have added at least two questions, we can solve: m = (A12 * b2 - A22 * b1) / (A12 * A12 - A11 * A22) n = (A12 * b1 - A11 * b2) / (A12 * A12 - A11 * A22) And we can find the difficulty for an expected score of P as: difficulty = (P - n) / m Let's do an example. The following table contains a few questions and the state of the function after adding the question. diff score | A11 A12 A22 b1 b2 | m n --------------+----------------------------+------------- 70 0.3 | 4900 70 1 21 0.3 | 50 0.4 | 7400 120 2 41 0.7 | -0.005 0.65 40 0.5 | 9000 160 3 61 1.2 | -0.006 0.74 35 0.7 | 10225 195 4 85.5 1.9 | -0.010 0.96 Here is the fitted function and the sample questions: And if we want to find the difficulty for an expected score of e.g. 75%, we get: difficulty(0.75) = 21.009
Set values of a matrix on positions inside a triangle
I have a N x N matrix will all values equal to zero, then I need to get the coordinates of a triangle and set the values inside this triangle to one (1). How can I determine the position of each element in the matrix that forms the triangle faces? Like this 10x10 matrix, I have a triangle set at (9,1),(5,5) and (9,5): 0000000000 0000000000 0000000000 0000000000 0000000000 0000010000 0000110000 0001010000 0010010000 0111110000 I don't need the code made for me, I want to check if there is a proper way (maybe using math) to get the "coordinates".
When you have two points x1,y1 and x2,y2, you can use these to create a formula for the line using "point-slope form" Calculate slope with m = (y1 - y2) / (x1 - x2) Then you have a formula of y - y1 = m(x - x1) This further goes to y = m(x - x1) + y1 So in your example of (9,1),(5,5) you calculate the m = (1 - 5) / (9 - 5) = (-4) / (4) = -1 Then your formula becomes, for that line, y = (-1)(x - 9) + 1 Then iterate between 5 and 9. f(5) = -(5-9) + 1 = -(-4) + 1 = 4 + 1 = 5 f(6) = -(6-9) + 1 = -(-3) + 1 = 3 + 1 = 4 f(7) = -(7-9) + 1 = -(-2) + 1 = 2 + 1 = 3 f(8) = -(8-9) + 1 = -(-1) + 1 = 1 + 1 = 2 f(9) = -(9-9) + 1 = -(0)) + 1 = 0 + 1 = 1
Triangles have nice properties allowing a very simple algorithm to suffice. Find Ymax, the topmost Y coordinate set in the triangle. Then for Ymax, find Xmin and Xmax, of the left and rightmost pixels set in that row. Now there are 2 cases. If Xmin == Xmax, then one vertex is (Xmin,Ymax), otherwise two of the coordinates are (Xmin, Ymax) and (Xmax, Ymax). With this you've found the topmost coordinate or coordinates. It's pretty simple to continue this reasoning to find the other ones. I'll let you puzzle it out for the fun... You can combine the min and max-finding in the algorithm above with the algorithm that does the filling as required in the second part of the problem.
Matlab - Algorithm for calculating 1d consecutive line segment edges from midpoints?
So I have a rectilinear grid that can be described with 2 vectors. 1 for the x-coordinates of the cell centres and one for the y-coordinates. These are just points with spacing like x spacing is 50 scaled to 10 scaled to 20 (55..45..30..10,10,10..10,12..20,20,20) and y spacing is 60 scaled to 40 scaled to 60 (60,60,60,55..42,40,40,40..40,42..60,60) and the grid is made like this e.g. x = 1 2 3, gridx = 1 2 3, y = 10 11 12, gridy = 10 10 10 1 2 3 11 11 11 1 2 3 12 12 12 so then cell centre 1 is 1,10 cc2 is 2,10 etc. Now Im trying to formulate an algorithm to calculate the positions of the cell edges in the x and y direction. So like my first idea was to first get the first edge using x(1)-[x(2)-x(1)]/2, in the real case x(2)-x(1) is equal to 60 and x(1) = 16348.95 so celledge1 = x(1)-30 = 16318.95. Then after calculating the first one I go through a loop and calculate the rest like this: for aa = 2:length(x)+1 celledge1(aa) = x(aa-1) + [x(aa-1)-celledge(aa-1)] end And I did the same for y. This however does not work and my y vector in the area where the edge spacing should be should be 40 is 35,45,35,45... approx. Anyone have any idea why this doesnt work and can point me in the right direction. Cheers Edit: Tried to find a solution using geometric alebra: We are trying to find the points A,B,C,....H. From basic geometry we know: c1 (centre 1) = [A+B]/2 and c2 = [B+C]/2 etc. etc. So we have 7 equations and 8 variables. We also know the the first few distances between centres are equal (60,60,60,60) therefore the first segment is 60 too. B - A = 60 So now we have 8 equations and 8 variables so I made this algorithm in Matlab: edgex = zeros(length(DATA2.x)+1,1); edgey = zeros(length(DATA2.y)+1,1); edgex(1) = (DATA2.x(1)*2-diffx(1))/2; edgey(1) = (DATA2.y(1)*2-diffy(1))/2; for aa = 2:length(DATA2.x)+1 edgex(aa) = DATA2.x(aa-1)*2-edgex(aa-1); end for aa = 2:length(DATA2.y)+1 edgey(aa) = DATA2.y(aa-1)*2-edgey(aa-1); end And I still got the same answer as before with the y spacing going 35,45,35,45 where it should be 40,40,40... Could it be an accuracy error?? Edit: here are the numbers if ur interested and I did the same computation as above only in excel: http://www.filedropper.com/workoutedges
It seems you're just trying to interpolate your data. You can do this with the built-in interp1 x = [30 24 19 16 8 7 16 22 29 31]; xi = interp1(2:2:numel(x)*2, x, 1:(numel(x)*2+1), 'linear', 'extrap'); This just sets up the original data as the even-indexed elements and interpolates the odd indices, including extrapolation for the two end points. Results: xi = Columns 1 through 11: 33.0000 30.0000 27.0000 24.0000 21.5000 19.0000 17.5000 16.0000 12.0000 8.0000 7.5000 Columns 12 through 21: 7.0000 11.5000 16.0000 19.0000 22.0000 25.5000 29.0000 30.0000 31.0000 32.0000
In Matlab Finding gradient of an image using first derivative
How can I do enhancements on an image using the first derivative. I do not want to use operators like sobel.. I want to find the gradient using the first derivative
You're always free to define your own impulse response and then convolve that with your image. diff1X =[1/2, 0, -1/2] %first derivative in the x direction diff1Y = [1/2; 0; -1/2] %first derivative in the y direction %These are finite difference approximations to the first derivative note they %are time reversed because the convolution involves a time reversal x = [1,2,3; 2,4,6; 4,8,12] x = 1 2 3 2 4 6 4 8 12 conv2(x, diff1X, 'same') %same parameter cuts results to initial image size ans = 1 1 -1 2 2 -2 4 4 -4 %note that the image is zero padded so the derivative at the edges reflects this conv2(x, diff1Y, 'same') ans = 1.0000 2.0000 3.0000 1.5000 3.0000 4.5000 -1.0000 -2.0000 -3.0000
Method for interpolating value at the midpoint of a square, given the values, first and second derivatives at the corners?
All the practical examples of spatial interpolation I've been able to find work by sampling additional surrounding points to estimate the derivatives. But is there a simpler method if the derivatives are already known—and if you only need the value (and derivatives) for the single point at the center of the known points? To illustrate: suppose for each of the points (1, 1), (-1, 1), (-1, -1), and (1, -1) you know f(x, y), f'(x), f''(x), f'(y), and f''(y) — and you want interpolated values at (0, 0) for f(x, y), f'(x), f''(x), f'(y), and f''(y).
First of all the problem as posed does not make sense. In multi-variable calculus we don't have derivatives, we have partial derivatives. Lots of them. Suppose you have the value, first partial derivatives and second partial derivatives at the corners. So at each corner we know the value, the partial by x, the partial by y, the second partial by x by x, the second partial by x by y, and the second partial by y by y. We have 6 pieces of data per corner, for 24 pieces of data total. Next what we do is try to fit this to an appropriate polynomial. 24 terms, that would be, a0 + a1 x + a2 y + a3 x^2 + a4 x y + a5 y^2 + a6 x^3 + a7 x^2 y + a8 x y^2 + a9 y^3 + a10 x^4 + a11 x^3 y + a12 x^2 y^2 + a13 x y^3 + a14 y^4 + a15 x^5 + a16 x^4 y + a17 x^3 y^2 + a18 x^2 y^3 + a18 x y^4 + a19 y^5 + a20 x^6 + a21 x^4 y^2 + a22 x^2 y^4 + a23 y^6. (I had to leave out some 6th power terms because I was hitting that 24 limit.) If you calculate that out, matching up all of those values against all of those points you get 24 equations in 24 variables. Solve and you get all of the coefficients to use. Plug in the value (0, 0) and you have your interpolation. Straightforward, tedious, and not for the faint of heart.