Finding size of perfect quad tree - c++

I need to find the size of a perfect quad tree.
This means I have 1 root node that splits into 4 nodes that splits into 4 nodes etc.
so a quad tree of height 1 would be size 1
height 2 = size 5 (1 + 4)
height 3 = size 21 (1 + 4 + 16)
height 4 = size 85 (1 + 4 + 16 + 64)
etc..
I know that the size of a perfect binary tree can be found with: size = 2^(height+1)-1
So I believe that a similar equation exists for quad tree.
So what is it?

This is a geometric series. So the relevant formula is:
S = a * (1 - r^n) / (1 - r)
where a is the first value, r is the common ratio, n is the number of terms, and ^ denotes "to-the-power-of".

For a quad tree the algorithm is
((4^depth)-1)/3
For example with depth 3 you get
(64-1)/3 = 21
and if you count three layers you get
1 + 4 + 16 = 21
In my implementation I have even divided it into two arrays
where the size for all nodes that arent leave nodes is
((4^(depth-1))-1)/3
and leave nodes is
4^(depth-1)
I do these calculations at compile time with meta programming for pow, and a template argument for the depth. So i just allocate my nodes in two arrays.

Just in case anyone will need a code sample (in swift3)
public func tileCount(forLevelRange levelRange: Range<UInt>) -> UInt64 {
var tileCount: UInt64 = 0
for level in levelRange.lowerBound ..< levelRange.upperBound {
tileCount += UInt64(pow(Double(1 << level), 2) )
}
return tileCount
}

Related

What is the O complexity of the number of "empty" nodes in an AVL tree?

We know that an AVL tree is usually very close to being balanced. Let's say we take an AVL tree and put it into an array (very similar to a heap, where the parent is index i, left child is 2i, and right child is 2i+1), how many empty indices would you get in terms of big O complexity?
So I know that the minimum number of nodes in a tree of height h = Fibonacci(h+2) - 1. So number of empty indices = 2^h - 1 - (Fibonacci(h+2) - 1) = 2^h - Fibonacci(h+2). But I don't know what to do next to prove it's complexity. I think it's O(log(n)), but I'm not sure.
If h is 0-based (as is the usual convention), the minimum number of nodes in an AVL tree with height h is F(h+3) - 1.
Let n = F(h+3) - 1 and let's try to solve for h to find the maximum height of an AVL tree with n nodes.
The closed form for F(x) is given by Binet's formula (see here for details):
F(x) = (phi^n - psi^n)/sqrt(5)
Therefore,
n = (phi^(h+3) - psi^(h+3))/sqrt(5) - 1
>= (phi^(h+3) - 1)/sqrt(5) - 1 since |psi| < 1
Solving for h yields
h <= log_phi(sqrt(5)(n + 1) + 1) - 3
<= 1.4405 log2(n)
A full tree with height h has 2^(h+1) - 1 nodes. Or in terms of n:
2^(h+1) - 1
<= 2^(1.4405 log2(n) + 1) - 1
= 2 * (2^log(n))^1.4405 - 1
= 2n^1.4405 - 1
Hence the number of empty nodes is bounded by
2n^1.4405 - 1 - n = O(n^1.4405)

Full recovery data using reed solomon

I'm testing a Reed Solomon algorithm from this repository in order to recover info in case something is externally changed.
Assuming:
m = bits per symbol
k = data
r = redundance
n = bits per block = r + k = 2^m - 1
t = error correction = (n - k) / 2
I can codify and recover info using the following parameters:
m = 8
n = 255
r = 135
k = 120
t = 67
And works perfectly, I can recover 67 errors.
My assumtions are:
Only data will be corrupted, no redundancy.
To get full recovery n = 3 * k --> r = 2 * k.
Then n = 255 so r in this case shall be 170.
So I must have GF(2^m) and RS [n, k, n - k + 1] for use is GF(2^8) and RS [255, 85, 171]
With these parameters I get the error:
Error - Failed to create sequential root generator!
This means that library function make_sequential_root_generator_polynomial:
const std::size_t field_descriptor = 8; /* m = bit per symbol */
const std::size_t generator_polynomial_index = 120;
const std::size_t generator_polynomial_root_count = 170; /* root shall be equal to redundance */
const schifra::galois::field field(field_descriptor,
schifra::galois::primitive_polynomial_size06,
schifra::galois::primitive_polynomial06);
if (
!schifra::make_sequential_root_generator_polynomial(field,
generator_polynomial_index,
generator_polynomial_root_count,
generator_polynomial)
)
{
std::cout << "Error - Failed to create sequential root generator!" << std::endl;
return false;
}
My problem is that I don't know why the algorithm fails. I think I have a concept problem, bug after read about the topic here and here, I don't get why is not possible.
Is it possible to use according assumtions or theory say that this is not possible?
The current code in the question is failing because it sets
generator_polynomial_index = 120;
and 120 (index) + 170 (root count) is > 255 (field size), which is checked for in
make_sequential_root_generator_polynomial()
generator_polynomial_index is normally set to 0 (first consecutive root = 1) or 1 (first consecutive root = field primitive = 2), unless the goal is to use a self-reciprocal generator polynomial.
Even in the case of a self-reciprocal poly, for 170 roots, generator_polynomial_index = 128 - (170/2) = 43. Setting it to 120 is unusually high.
It could be possible for this to work as the roots are sequential powers modulo 255, so they could just wrap around, 2^120, 2^121, ... , 2^253, 2^254, 2^255=2^0, 2^256 = 2^1, ..., as this is done for self-reciprocal polynomials for an odd number of roots generator_polynomial_index = (255 - (number of roots / 2)), but perhaps the rest of the code has an issue with this.

Most efficient way to calculate a lower triangular matrix row index?

I am working with a lower triangular matrix, the function below calculates a row index of such matrix. How can I optimize it in terms of execution time?
The triangular matrix can hold at most N (N + 1) / 2 nonzero elements (where N is the matrix dimension - N x N).
I have a set of numbers 0, 1, 2, ..., N (N + 1) / 2 - 1 and from those, I have to calculate the matrix row index.
My current solution:
inline
unsigned int calc_row(unsigned int i)
{
return static_cast<unsigned int>(floor(sqrt(static_cast<double>(0.25 + 2 * i)) - 0.5));
}
// example:
calc_row(0) == 0;
calc_row(1) == 1;
calc_row(2) == 1;
calc_row(3) == 2;
calc_row(4) == 2;
calc_row(5) == 2;
Question:
1) Do you think my current solution is performance friendly?
2) If not how can I optimize it (in terms of the function execution time)?
If You believe an alternate method to calculate the row index would perform better, I am fine with it. Unfortunately the lookup table is not an option in my case.
EDIT #1:
I just had an idea: Is there a way to make a template metaprogramming version of the lookup table? A way to generate the row number at a compile time could prove to be a significant optimization. The biggest unsigned int i would be around 10 million in my case.
EDIT #2:
I edited the entire question because it caused a major confusion. I am sorry about that.
EDIT #3:
calc_row() calculates the formula: (sqrt(1 + 8 * i) - 1) / 2 which is the solution for the quadratic equation x(x + 1) / 2 = i. Where i is row index.
The main idea for this solution lies in the fact that the linear index for a triangular matrix with diagonal can be calculated as: i (i + 1) / 2 + j. Where i is row index and j is column index.

OpenCv: FilterEngine() explanation / Create custom nonlinear filter

I would like to create my own nonlinear filter in OpenCV using C++, and if I see it correctly, I can use the FilterEngine class to do so. Unfortunately, I'm not really able to follow the documentation of this class. (Link: http://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html#filterengine).
Could someone be so kind to explain the class to me in a little bit more detail?
I'm grateful for every input and every example you can provide me with :-)
.
My specific needs:
1) I would like learn how to create my own nonlinear filters in general.
2) I would like to apply a rank-transform filter to my images:
Meaning: I have a kernel/region and I would like to flag every pixel inside that region with a one if the intensity-value of that (neighbourhood-) pixel is lower than the intensity of the center-pixel. Next, I want to use a simple convolution to save the sum of the transformed region, and store the value at the center-pixel. Let's look at a simple example:
100 120 200 rank-trans. 1 0 0 convolution
110 120 220 --> 1 0 0 --> 2
180 200 200 0 0 0
P.S: I know that I can archive the result of 2) by combining 255 threshold-operations with 255 box-filter operations, and then looping over every pixel and selecting the correct value. However, that seems quite inefficient to me ...
.
Code-Snipped [Edit]:
As I still struggle to understand the FilterEngine(), I started to write my own function for the above-descripted usecase. I would also be happy if you could comment on it to improve its efficiency, as it is quite slow at the moment. (~2sec. for a 1080x1920 image on one CPU-core).
void rankTransform(Mat& out, Mat in, int kernal_size, int borderType) {
// Issue warning if neccessary:
if (kernal_size >= 17) {
std::cout << "Warning, need to change Mat-type. Unsigned short only supports kernels up-to the size of 15x15" << std::endl << std::endl;
};
// First: Get borders around the image:
int border_size = (kernal_size - 1) / 2;
Mat in_incl_border = Mat(1080 + 2 * border_size, 1920 + 2 * border_size, in.depth());
copyMakeBorder(in, in_incl_border, border_size, border_size, border_size, border_size, borderType);
// Second: Loop through the image, conduct a rank transform and
// then sum over the kernel-size:
int start_pixel = 0 + (border_size + 1);
int end_pixel_width = 1920 + border_size;
int end_pixel_height = 1080 + border_size;
int i, j;
int x_1, x_2, y_1;
for (i = start_pixel; i < end_pixel_height; ++i) {
x_1 = i - border_size;
x_2 = i + border_size + 1;
for (j = start_pixel; j < end_pixel_width; ++j) {
y_1 = j - border_size;
out.at<unsigned short>(x_1-1, y_1-1) = static_cast<unsigned short>( (sum( in_incl_border(Range(x_1, x_2), Range(y_1, j + border_size + 1)) < in_incl_border.at<unsigned short>(i, j) )[0])/255 );
};
};

How to filter given width of lines in a image?

I need to filter given width of lines in a image.
I am coding a program which will detect lines of road image. And I found something like that but can't understand logic of it. My function has to do that:
I will send image and width of line in terms of pixel size(e.g 30 pixel width), the function will filter just these lines in image.
I found that code:
void filterWidth(Mat image, int tau) // tau=width of line I want to filter
int aux = 0;
for (int j = 0; j < quad.rows; ++j)
{
unsigned char *ptRowSrc = quad.ptr<uchar>(j);
unsigned char *ptRowDst = quadDst.ptr<uchar>(j);
for (int i = tau; i < quad.cols - tau; ++i)
{
if (ptRowSrc[i] != 0)
{
aux = 2 * ptRowSrc[i];
aux += -ptRowSrc[i - tau];
aux += -ptRowSrc[i + tau];
aux += -abs((int)(ptRowSrc[i - tau] - ptRowSrc[i + tau]));
aux = (aux < 0) ? (0) : (aux);
aux = (aux > 255) ? (255) : (aux);
ptRowDst[i] = (unsigned char)aux;
}
}
}
What is the mathematical explanation of that code? And how does that work?
Read up about convolution filters. This code is a particular case of a 1 dimensional convolution filter (it only convolves with other pixels on the currently processed line).
The value of aux is started with 2 * the current pixel value, then pixels on either side of it at distance tau are being subtracted from that value. Next the absolute difference of those two pixels is also subtracted from it. Finally it is capped to the range 0...255 before being stored in the output image.
If you have an image:
0011100
This convolution will cause the centre 1 to gain the value:
2 * 1
- 0
- 0
- abs(0 - 0)
= 2
The first '1' will become:
2 * 1
- 0
- 1
- abs(0 - 1)
= 0
And so will the third '1' (it's a mirror image).
And of course the 0 values will always stay zero or become negative, which will be capped back to 0.
This is a rather weird filter. It takes the pixel values three by three on the same line, with a tau spacing. Let these values by Vl, V and Vr.
The filter computes - Vl + 2 V - Vr, which can be seen as a second derivative, and deducts |Vl - Vr|, which can be seen as a first derivative (also called gradient). The second derivative gives a maximum response in case of a maximum configuration (Vl < V > Vr); the first derivative gives a minimum response in case of a symmetric configuration (Vl = Vr).
So the global filter will give a maximum response for a symmetric maximum (like with a light road on a dark background, vertical, with a width less than 2.tau).
By rearranging the terms, you can see that the filter also yields the smallest of the left and right gradients, V - Vm and V - Vp (clamped to zero).