How to find small cubes within a bigger cube in MATLAB? - image

Given an NxNxN cube (image), how can I find all the 2x2x2 boxes within the NxNxN cube? of course if N is even, we can find 2x2x2 boxes without overlapping, but when the N is odd, there is overlapping between some of the 2x2x2 boxes found in the bigger cube.
So,
1- How can I find all the non-overlapped 2x2x2 boxes in a bigger NxNxN cube where N is even?
input: NxNxN cube
output: all the possible non-overlapped 2x2x2 cubes.
2- How can I find all the overlapped 2x2x2 boxes in a bigger NxNxN cube where N is odd? This time, the overlapped areas in the 2x2x2 boxes should be zero in second (or more) visits; i.e. each overlapped area should be visited (counted) once not more.
input: NxNxN cube
output: all the possible overlapped 2x2x2 cubes with zero values for the overlapped voxels in 2nd or more visits.

I will give you an answer for the part where N is even. The rest can be easily adapted, I hope you can do this yourself :-) Or at least try it - if you've got problems, just come back to us.
I don't have MATLAB installed anymore, so I hope this is free of typo errors. But the idea should be clear:
%
N = 10;
% First create all possible starting coordinates of 2x2x2 cubes within the big cube:
coords = 1:2:(N-1); % could easily be adapted to other small-cube sizes like 3x3x3 if you want to...
% Now create all possible combinations of starting-coordinates in every direction (as it is a cube, the starting points in x, y, z directions are the same):
sets = {coords, coords, coords};
[x y z] = ndgrid(sets{:});
cartProd = [x(:) y(:) z(:)]; % taken from here: http://stackoverflow.com/a/4169488/701049 --> you could instead also use this function: https://www.mathworks.com/matlabcentral/fileexchange/10064-allcomb-varargin- which generates all possible combinations
% Now cartProd contains all possible start-points of small cubes as row-vectors. If you want, you can easily calculate the corresponding vectors of end-points by simply adding +1 to every entry which will effectively yield a small-cube size of 2. If you want to further modify it to support e.g. 3x3x3 cubes, simply add +2 to every dimension.
endPoints = cartProd+1;
% E.g.: the first small cube starts at [x,y,z] = cartProd(1,:) and ends at [x_e, y_e, z_e] = endPoints(1,:).
Have fun :-)
Hint: for the odd big cube -> Simply treat it as evenly-sized cube, e.g. treat a 9x9x9 cube as 10x10x10, take my algorithm from above, and then move the most outer small-cubes one step to the center. That means, take the small cubes with the biggest x, y or z coordinate and substract 1 in that direction. So that the starting coordinate for all small cubes with x_max=9 will be changed to x=8. Then the same for y_max=9 and z_max=9.

Related

How to check if a box fits into another box (any rotations allowed)

Suppose I have two boxes (each of them is a rectangular cuboid, aka rectangular parallelepiped). I need to write a function that decides if the box with dimensions (a, b, c) can fit into the box with dimensions (A, B, C), assuming any rotations by any angles are allowed (not only by 90°).
The tricky part is the edges of the inner box may be not parallel to corresponding edges of the outer one. For example, a box that is very thin in the dimensions (a, b) but with length 1 < c < √3 can fit into a unit cube (1, 1, 1) if placed along its main diagonal.
I've seen questions [1], [2] but they seem to cover only rotations by 90°.
Not a complete answer, but a good start is to determine the maximum diameter that fits inside the larger box (inscribe the box in a circle) and the minimum diameter needed for the smaller box. That gives a first filter for possibility. This also tells you how to orient the smaller box within the larger one.
If one box can fit inside the other than it can fit also if boxes have same center. So only rotation is enough to check, translation is not needed to check.
2D case: For boxes X=(2A,2B) and x=(2a,2b) positioned around (0,0). That means corners of X are (+-A, +-B).
---------(A,B)
|
-----------(a,b)
(0,0) |
-----------(a,-b)
|
---------(A,-B)
Be rotating x around (0,0), corners are always on circle C with radius sqrt(a^2+b^2). If part of circle lie inside box X, and if part inside X has enough arc length to place 2 points on distance 2a or 2b, than x can fit inside X. For that we need to calculate intersection of C with lines x=A and y=B, and calculate distance between these intersection. If distance is equal or grater than 2a or 2b, than x can fit inside X.
3D case: Similar. For boxes X=(2A,2B,2C) and x=(2a,2b,2c) positioned around (0,0,0). Rotating x around (0,0,0), all corners move on sphere with radius sqrt(a^2+b^2+c^2). To see is there enough space on sphere-box intersection part, find intersection of sphere with planes x=A, y=B and z=C, and check is there enough space to fit any of quads (2a,2b), (2a,2c) or (2b,2c) on that sphere part. It is enough to check are points on part border on sufficient distance. For this part I'm not sure about efficient approach, maybe finding 'center' of intersection part and checking it's distance to border can help.
You basically have to check several cases, some trivial and some needing minimization searches.
First, there are 4 3-parallel-axis cases. If any of them passes (with #jean's test), you fit. Otherwise, continue to the next test cases:
Next, there are 18 2d diagonal cases, where one axis is parallel and the other two are diagonal, with one angle degree of freedom. Discard a case if the parallel axis doesn't fit; otherwise find the minimum of some "impingement" metric function of the single rotation angle. Then check for any actual impingement at that angle. The impingement metric has to be some continuous measure of how the inner box (4 corners) are staying inside the 2 faces of the outer box, allowing that sometimes they may go outside during the search for the minimum impingement angle. Hopefully a) there are a predictable maximum number of minima, and hopefully b) if there is a possible fit, then a fit is guaranteed at the angle of one of these minima.
If none of those cases passes without impingement, then move on to the larger number of 3d no-parallel-axes cases, where the rotation parameter is now three angles instead of one, and you have to search for a (hopefully limited number of) minima of the impingement metric, and test there for actual impingement.
Not really elegant, I think. This is similar to another thread asking how long of a line of given width can fit inside a 2d box of given dimensions. I didn't consider the parallel-axis case there, but the diagonal case requires solving a quartic equation (much worse than a quadratic equation). You may have a similar problem for your one-parallel-axis cases, if you want to go analytic instead of searching for minima of an impingement metric. The analytic solution for the no-parallel-axis 3d diagonal cases probably involves solving (for the correct root of) an even higher order equation.
In fact, any box A with dimensions (a1, a2, a3) can fit in an other box B with dimensions (b1, b2, b3), in the following conditions:
i) Every ai is less than or equal to every bi with i = 1. 2. 3;
ii) Any ai has to be less than or equal to sqrt(b1^2+b2^2+b3^2), the main diagonal of B (diagB). Any box A with one of its dimensions equal to diagB, has the other two dimensions equal to 0, since any plane orthogonal to it would extend outside the box B.
iii) The sum of a1, a2 and a3 must be less than or equal to diagB.
From these, we can see that the greatest dimension ai of a box A for it to fit box B, given ai > bi, should lie in the interval (bi, diagB).
Thus, any box with one dimension bigger than any dimension of a box containing it will necessarily placed along the latter's main diagonal.
Put it simply:
A(a1, a2, a3) fits in B(b1, b2, b3) iff a1+a2+a3 <= diagB.
Can you get box dimensions? Say a0,a1,a2 are the dimensions of box A ordered by size and b0,b1,b2 are the dimensions of box B ordered by size.
A fits inside B if (a0 <= b0 AND a1 <= b1 AND a2 <= b2)

Calculate Median Image in Matlab

I am new to matlab, so forgive me if i am asking for the obvious here: what i have is a collection of color photographic images (all the same dimensions). What i want to do is calculate the median color value for each pixel.
I know there is a median filter in matlab, but as far as i know it does not do exactly what i want. Because i want to calculate the median value between the entire collection of images, for each separate pixel.
So for example, if i have three images, i want matlab to calculate (for each pixel) which colorvalue out of those three images is the median value. How would i go about doing this, does anyone know?
Edit: From what i can come up with, i would have to load all the images into a single matrix. The matrix would have to have 4 dimensions (height, width, rgb, images), and for each pixel and each color find the median in the 4th dimension (between the images).
Is that correct (and possible)? And how can i do this?
Your intuition is correct. If you have images image_1, image_2, image_3, for example, you can assign them to a 4 dimensional matrix:
X(:,:,:,1) = image_1;
X(:,:,:,2) = image_2;
X(:,:,:,3) = image_3;
Then use:
Y=median(X,4);
To get the median.
Expanding my comments into a full answer;
#prototoast's answer is elegant, but since medians for the R, G and B values of each pixel are calculated separately, the output image will look very strange.
To get a well-defined median that makes visual sense, the easiest thing to do is cast the images to black-and-white before you try to take the median.
rgb2gray() from the Image Processing toolbox will do this in a way that preserves the luminance of each pixel while discarding the hue and saturation.
EDIT:
If you want to define the "RGB median" as "the middle value in cartesian coordinates" this is easy enough to do for three images.
Consider a single pixel with three possible choices for the median colour, C1=(r1,g1,b1), C2=(r2,g2,b2), C3=(r3,g3,b3). Generally these form a triangle in 3D space.
Take the Pythagorean distance between the three colours: D1_2=abs(C2-C1), D2_3=abs(C3-C2), D1_3=abs(C3-C1).
Pick the "median" to be the colour that has lowest distance to the other two. Defining D1=D1_2+D1_3, etc. and taking min(D1,D2,D3) should work, courtesy of the Triangle Inequality. Note the degenerate cases: equilateral triangle (C1, C2, C3 equidistant), line (C1, C2, C3 linear with each other), or point (C1=C2=C3).
Note that this simple way of thinking about a 3D median is hard to extend to more than three images, because "the median" of a set of four or more 3D points is a bit harder to define.
Edit 2
For defining the "median" of N points as the centre of the smallest sphere that encloses them in 3D space, you could try:
Find the two points N1 and N2 in {N} that are furthest apart. The distance between N1 and N2 is the diameter of the smallest sphere that encloses all the points. (Proof: Any smaller and the sphere would not be able to enclose both N1 and N2 at the same time.)
The median is then halfway between N1 and N2: M = (N1+N2)/2.
Edit 3: The above only works if no three points are equidistant. Maybe you need to ask math.stackexchange.com?
Edit 4: Wikipedia delivers again! Smallest circle problem, Bounding sphere.

Drawing a circle on an array for CCD integration purposes

I am writing a function to draw an approximate circle on a square array (in Matlab, but the problem is mainly algorithmic).
The goal is to produce a mask for integrating light that falls on a portion of a CCD sensor from a diffraction-limited point source (whose diameter corresponds to a few pixels on the CCD array). In summary, the CCD sensor sees a pattern with revolution-symmetry, that has of course no obligation to be centered on one particular pixel of the CCD (see example image below).
Here is the algorithm that I currently use to produce my discretized circular mask, and which works partially (Matlab/Octave code):
xt = linspace(-xmax, xmax, npixels_cam); % in physical coordinates (meters)
[X Y] = meshgrid(xt-center(1), xt-center(2)); % shifted coordinate matrices
[Theta R] = cart2pol(X,Y);
R = R'; % cart2pol uses a different convention for lines/columns
mask = (R<=radius);
As you can see, my algorithm selects (sets to 1) all the pixels whose physical distance (in meters) is smaller or equal to a radius, which doesn't need to be an integer.
I feel like my algorithm may not be the best solution to this problem. In particular, I would like it to include the pixel in which the center is present, even when the radius is very small.
Any ideas ?
(See http://i.stack.imgur.com/3mZ5X.png for an example image of a diffraction-limited spot on a CCD camera).
if you like to select pixels if and only if they contain any part of the circle C:
in each pixel place a small circle A with the radius = halv size of the pixel, and another one around it with R=sqrt(2)*half size of the circle (a circumscribed circle)
To test if two circles touch each other you just calculate the center to center distances and subtract the sum of the two radii.
If the test circle C is within A then you select the pixel. If it's within B but not C you need to test all four pixel sides for overlap like this Circle line-segment collision detection algorithm?
A brute force approximate method is to make a much finer grid within each pixel and test each center point in that grid.
This is a well-studied problem. Several levels of optimization are possible:
You can brute-force check if every pixel is inside the circle. (r^2 >= (x-x0)^2 + (y-y0)^2)
You can brute-force check if every pixel in a square bounding the circle is inside the circle. (r^2 >= (x-x0)^2 + (y-y0)^2 where |x-x0| < r and |y-y0| < r)
You can go line-by-line (where |y-y0| < r) and calculate the starting x ending x and fill all the lines in between. (Although square roots aren't cheap.)
There's an infinite possibility of more sophisticated algorithms. Here's a common one: http://en.wikipedia.org/wiki/Midpoint_circle_algorithm (filling in the circle is left as an exercise)
It really depends on how sophisticated you want to be based on how imperative good performance is.

Efficient algorithm to find a point not touched by a set of rectangles

Input: a set of rectangles within the area (0, 0) to (1600, 1200).
Output: a point which none of the rectangles contains.
What's an efficient algorithm for this? The only two I can currently think of are:
Create a 1600x1200 array of booleans. Iterate through the area of each rectangle, marking those bits as True. Iterate at the end and find a False bit. Problem is that it wastes memory and can be slow.
Iterate randomly through points. For each point, iterate through the rectangles and see if any of them contain the point. Return the first point that none of the rectangles contain. Problem is that it is really slow for densely populated problem instances.
Why am I doing this? It's not for homework or for a programming competition, although I think that a more complicated version of this question was asked at one (each rectangle had a 'color', and you had to output the color of a few points they gave you). I'm just trying to programmatically disable the second monitor on Windows, and I'm running into problems with a more sane approach. So my goal is to find an unoccupied spot on the desktop, then simulate a right-click, then simulate all the clicks necessary to disable it from the display properties window.
For each rectangle, create a list of runs along the horizontal direction. For example a rectangle of 100x50 will generate 50 runs of 100. Write these with their left-most X coordinate and Y coordinate to a list or map.
Sort the list, Y first then X.
Go through the list. Overlapping runs should be adjacent, so you can merge them.
When you find the first run that doesn't stretch across the whole screen, you're done.
I would allocate an image with my favorite graphics library, and let it do rectangle drawing.
You can try a low res version first (scale down a factor 8), that will work if there is at least a 15x15 area. If it fails, you can try a high res.
Use Windows HRGNs (Region in .net). They were kind of invented for this. But that's not language agnostic no.
Finally you can do rectangle subtraction. Only problem is that you can get up to 4 rectangles each time you subtract one rect from another. If there are lots of small ones, this can get out of hand.
P.S.: Consider optimizing for maximized windows. Then you can tell there are no pixels visible without hit testing.
Sort all X-coordinates (start and ends of rectangles), plus 0 & 1600, remove duplicates. Denote this Xi (0 <= i <= n).
Sort all Y-coordinates (start and ends of rectangles), plus 0 & 1200, remove duplicates. Denote this Yj (0 <= j <= m).
Make a n * m grid with the given Xi and Yj from the previous points, this should be much smaller than the original 1600x1200 one (unless you have a thousand rectangles, in which case this idea doesn't apply). Each point in this grid maps to a rectangle in the original 1600 x 1200 image.
Paint rectangles in this grid: find the coordinates of the rectangles in the sets from the first steps, paint in the grid. Each rectangle will be on the form (Xi1, Yj1, Xi2, Yj2), so you paint in the small grid all points (x, y) such that i1 <= x < i2 && j1 <= y < j2.
Find the first unpainted cell in the grid, take any point from it, the center for example.
Note: Rectangles are assumed to be on the form: (x1, y1, x2, y2), representing all points (x, y) such that x1 <= x < x2 && y1 <= y < y2.
Nore2: The sets of Xi & Yj may be stored in a sorted array or tree for O(log n) access. If the number of rectangles is big.
If you know the minimum x and y dimensions of the rectangles, you can use the first approach (a 2D array of booleans) using fewer pixels.
Take into account that 1600x1200 is less than 2M pixels. Is that really so much memory? If you use a bitvector, you only need 235k.
You first idea is not so bad... you should just change the representation of the data.
You may be interessed in a sparse array of booleans.
A language dependant solution is to use the Area (Java).
If I had to do this myself, I'd probably go for the 2d array of booleans (particularly downscaled as jdv suggests, or using accelerated graphics routines) or the random point approach.
If you really wanted to do a more clever approach, though, you can just consider rectangles. Start with a rectangle with corners (0,0),(1600,1200) = (lx,ly),(rx,ry) and "subtract" the first window (wx1,wy1)(wx2,wy2).
This can generate at most 4 new "still available" rectangles if it is completely contained within the original free rectangle: (eg, all 4 corners of the new window are contained within the old one) they are (lx,ly)-(rx,wy1), (lx,wy1)-(wx1,wy2), (wx2,wy1)-(rx,wy2), and (lx,wy2)-(rx,ry). If just a corner of the window overlaps (only 1 corner is inside the free rectangle), it breaks it into two new rectangles; if a side (2 corners) juts in it breaks it into 3; and if there's no overlap, nothing changes. (If they're all axes aligned, you can't have 3 corners inside).
So then keep looping through the windows, testing for intersection and sub-dividing rectangles, until you have a list (if any) of all remaining free space in terms of rectangles.
This is probably going to be slower than any of the graphics-library powered approaches above, but it'd be more fun to write :)
Keep a list of rectangles that represent uncovered space. Initialize it to the entire area.
For each of the given rectangles
For each rectangle in uncovered space
If they intersect, divide the uncovered space into smaller rectangles around the covering rectangle, and add the smaller rectangles (if any) to your list of uncovered ones.
If your list of uncovered space still has any entries, they contain all points not covered by the given rectangles.
This doesn't depend on the number of pixels in your area, so it will work for large (or infinite) resolution. Each new rectangle in the uncovered list will have corners at unique intersections of pairs of other rectangles, so there will be at most O(n^2) in the list, giving a total runtime of O(n^3). You can make it more efficient by keeping your list of uncovered rectangles an a better structure to check each covering rectangle against.
This is a simple solution with a 1600+1200 space complexity only, it is similar in concept to creating a 1600x1200 matrix but without using a whole matrix:
Start with two boolean arrays W[1600] and H[1200] set to true.
Then for each visible window rectangle with coordinate ranges w1..w2 and h1..h2, mark W[w1..w2] and H[h1..h2] to false.
To check if a point with coordinates (w, h) falls in an empty space just check that
(W[w] && H[h]) == true

Equidistant points across a cube

I need to initialize some three dimensional points, and I want them to be equally spaced throughout a cube. Are there any creative ways to do this?
I am using an iterative Expectation Maximization algorithm and I want my initial vectors to "span" the space evenly.
For example, suppose I have eight points that I want to space equally in a cube sized 1x1x1. I would want the points at the corners of a cube with a side length of 0.333, centered within the larger cube.
A 2D example is below. Notice that the red points are equidistant from eachother and the edges. I want the same for 3D.
In cases where the number of points does not have an integer cube root, I am fine with leaving some "gaps" in the arrangement.
Currently I am taking the cube root of the number of points and using that to calculate the number of points and the desired distance between them. Then I iterate through the points and increment the X, Y and Z coordinates (staggered so that Y doesn't increment until X loops back to 0, same for Z with regard for Y).
If there's an easy way to do this in MATLAB, I'd gladly use it.
The sampling strategy you are proposing is known as a Sukharev grid, which is the optimal low dispersion sampling strategy, http://planning.cs.uiuc.edu/node204.html. In cases where the number of samples is not n^3, the selection of which points to omit from the grid is unimportant from a sampling standpoint.
In practice, it's possible to use low discrepancy (quasi-random) sampling techniques to achieve very good results in three dimensions, http://planning.cs.uiuc.edu/node210.html. You might want to look at using Halton and Hammersley sequences.
http://en.wikipedia.org/wiki/Halton_sequence
http://en.wikipedia.org/wiki/Constructions_of_low-discrepancy_sequences
You'll have to define the problem in more detail for the cases where the number of points isn't a perfect cube. Hovever, for the cases where the number of points is a cube, you can use:
l=linspace(0,1,n+2);
x=l(2:n+1); y=x; z=x;
[X, Y, Z] = meshgrid(x, y, z);
Then for each position in the matrices, the coordinates of that point are given by the corresponding elements of X, Y, and Z. If you want the points listed in a single matrix, such that each row represents a point, with the three columns for x, y, and z coordinates, then you can say:
points(:,1) = reshape(X, [], 1);
points(:,2) = reshape(Y, [], 1);
points(:,3) = reshape(Z, [], 1);
You now have a list of n^3 points on a grid throughout the unit cube, excluding the boundaries. As others have suggested, you can probably randomly remove some of the points if you want fewer points. This would be easy to do, by using randi([0 n^3], a, 1) to generate a indices of points to remove. (Don't forget to check for duplicates in the matrix returned by randi(), otherwise you might not delete enough points.)
This looks related to sphere packing.
Choose the points randomly within the cube, and then compute vectors to the nearest neighbor or wall. Then, extend the endpoints of the smallest vector by exponentially decaying step size. If you do this iteratively, the points should converge to the optimal solution. This even works if the number of points is not cubic.
a good random generator could be a first a usable first approximation. maybe with a later filter to reposition (again randomly) the worst offenders.

Resources