Packing algorithm for packing rectangles into irregular space - packing

I have n rectangles each height 1 and various (integer) widths. So the rectangles are equivalent to an n-length vector of positive integers.
I have c containers each width (integer) w but whose height varies. Each container is equivalent to w rectangles of width 1 and height some non-negative integer.
So each container is equivalent to a w-length vector of non-negative integers and all c containers are equivalent to a c x w matrix M of non-negative integers.
I value the packing of each rectangle in proportion to its width. I may only pack rectangles horizontally.
So I need for each rectangle a position for its left end in some container i.e. I need (i,j) such that when summing over all the packed rectangles the total height in container i at each position is no greater than M(i,j).
I tried using solver in Excel but it only gave a local optimum.
Am thinking something like try to place rectangles in descending length. If there is ever more than one possible position, pick the one that leaves the most options for the next size down.

Related

Fill Grid With Random Pixels

I have a grid of pixels 64x8. The aim is to to activate the pixels on this grid in a random manner till the whole grid is activated.
Logically I can generate random numbers in 0-63 and 0-7 range and then activate this pixel. Assuming I run this for long enough, the grid should be completely activated.
However, I am wondering if there is any algorithm that can minimize / avoid altogether collision (returning already activated pixel coordinate) and guarantee complete grid activation in a finite amount of time?
Fill an array of length 512 with numbers increasing from from 0 to 511 (64x8 = 512), so the array will contain {0,1,2,3,..., 511}).
Then shuffle that array, for example like explained here: Shuffle array in C.
Then define a function that maps a number to a coordinate, that would be:
y = n / 8
x = n % 8
n being one of the numbers of the array.
If the array is well shuffled this guarantees that all pixels will be activatged in a random order.
You could implement a pseudo random generator (PRG # Wikipedia) with a period of 64 * 8. Use 3 bits for the axis with 8, and the remaining 6 bits for the axis with 64.

how to Write in MATLAB one function, Its inputs are : • Array of only 4 elements (4 pixels)

How to write in MATLAB one function, its inputs are:
Array of only 4 elements (4 pixels)
The location (x,y) of the
interpolated pixel relatively to the pixel (0,0)
Its out put is the new intensity of the interpolated pixel.
Bilinear interpolation.

How would you convert X,Y points to Rho,Theta for hough transform in C?

So I am trying to code Hough Transform on C. I have a binary image and have extracted the binary values from the image. Now to do hough transform I have to convert the [X,Y] values from the image into [rho,theta] to do a parametric transform of the form
rho=xcos(theta)+ysin(theta)
I don't quite understand how it's actually transformed, looking at other online codes. Any help explaining the algorithm and how the accumulator for [rho,theta] values should be done based on [X,Y] would be appreciated.Thanks in advance. :)
Your question hints at the fact that you think that you need to map each (X,Y) point of interest in the image to ONE (rho, theta) vector in the Hough space.
The fact of the matter is that each point in the image is mapped to a curve, i.e. SEVERAL vectors in the Hough space. The number of vectors for each input point depends on some "arbitrary" resolution that you decide upon. For example, for 1 degree resolution, you'd get 360 vectors in Hough space.
There are two possible conventions, for the (rho, theta) vectors: either you use [0, 359] degrees range for theta, and in that case rho is always positive, or you use [0,179] degrees for theta and allow rho to be either positive or negative. The latter is typically used in many implementation.
Once you understand this, the Accumulator is little more than a two dimension array, which covers the range of the (rho, theta) space, and where each cell is initialized with 0. It is used to count the number of vectors that are common to various curves for different points in the input.
The algorithm therefore compute all 360 vectors (assuming 1 degree resolution for theta) for each point of interest in the input image. For each of the these vectors, after rounding rho to the nearest integral value (depends on precision in the rho dimension, e.g. 0.5 if we have 2 points per unit) it finds the corresponding cell in the accumulator, and increment the value in this cell.
when this has been done for all points of interest, the algorithm searches for all cells in the accumulator which have a value above a chosen threshold. The (rho, theta) "address" of these cells are the polar coordinates values for the lines (in the input image) that the Hough algorithm has identified.
Now, note that this gives you line equations, one is typically left with figure out the segment of these lines that effectively belong in the input image.
A very rough pseudo-code "implementation" of the above
Accumulator_rho_size = Sqrt(2) * max(width_of_image, height_of_image)
* precision_factor // e.g. 2 if we want 0.5 precision
Accumulator_theta_size = 180 // going with rho positive or negative convention
Accumulator = newly allocated array of integers
with dimension [Accumulator_rho_size, Accumulator_theta_size]
Fill all cells of Accumulator with 0 value.
For each (x,y) point of interest in the input image
For theta = 0 to 179
rho = round(x * cos(theta) + y * sin(theta),
value_based_on_precision_factor)
Accumulator[rho, theta]++
Search in Accumulator the cells with the biggest counter value
(or with a value above a given threshold) // picking threshold can be tricky
The corresponding (rho, theta) "address" of these cells with a high values are
the polar coordinates of the lines discovered in the the original image, defined
by their angle relative to the x axis, and their distance to the origin.
Simple math can be used to compute various points on this line, in particular
the axis intercepts to produce a y = ax + b equation if so desired.
Overall this is a rather simple algorithm. The complexity lies mostly in being consistent with the units, for e.g. for the conversion between degrees and radians (most math libraries' trig functions are radian-based), and also regarding the coordinates system used for the input image.

Algorithms for downscaling bitmapped fonts

This is a follow-up to this question.
I am working on a low level C app where I have to draw text. I have decided to store the font I want to use as an array (black and white, each char 128x256, perhaps), then I'd downscale it to the sizes I need with some algorithm (as grayscale, so I can have some crude font smoothing).
Note: this is a toy project, please disregard stuff like doing calculations at runtime or not.
Question is, which algorithm?
I looked up 2xSaI, but it's rather complicated. I'd like something I can read the description for and work out the code myself (I am a beginner and have been coding in C/C++ for just under a year).
Suggestions, anyone?
Thanks for your time!
Edit: Please note, the input is B&W, the output should be smoothed grayscale
Figure out the rectangle in the source image that will correspond to a destination pixel. For example if your source image is 50x100 and your destination is 20x40, the upper left pixel in the destination corresponds to the rectangle from (0,0) to (2.2,2.2) in the source image. Now, do an area-average over those pixels:
Area is 2.2 * 2.2 = 4.84. You'll scale the result by 1/4.84.
Pixels at (0,0), (0,1), (1,0), and (1,1) each weigh in at 1 unit.
Pixels at (0,2), (1,2), (2,0), and (2,1) each weigh in at 0.2 unit (because the rectangle only covers 20% of them).
The pixel at (2,2) weighs in at 0.04 (because the rectangle only covers 4% of it).
The total weight is of course 4*1 + 4*0.2 + 0.04 = 4.84.
This one was easy because you started with source and destination pixels lined up evenly at the edge of the image. In general, you'll have partial coverage at all 4 sides/4 corners of the sliding rectangle.
Don't bother with algorithms other than area-averaging for downscaling. Most of them are plain wrong (they result in horrible aliasing, at least with a factor smaller than 1/2) and the ones that aren't plain wrong are a good bit more painful to implement and probably won't give you better results.
Consider that your image is a N*M BW bitmap. For simplicity we'll consider it char Letter[N][M], when allowable values are 0 and 1. Now consider that you want to downscale it to the unsigned char letter[n][m]. This will mean that each greyscale pixel from letter will be computed as number of white pixels in the big bitmap:
char Letter[N][M];
unsigned char letter[n][m];
int rect_sz_X = N / n; // the size of rectangle that will map to a single pixel
int rect_sz_Y = M / m; // in the downscaled image
int i, j, x, y;
for (i = 0; i < n; i++) for (j = 0; j < m; j++){
int sum = 0;
for (x = 0; x < rect_sz_X; x++) for (y = 0; y < rect_sz_Y; y++)
sum += Letter[i*rect_sz_X + x][j*rect_sz_Y + y];
letter[n][m] = ( sum * 255) / (rect_sz_X * rect_sz_Y);
};
Note that the rectangles that creates pixels could overlap (in case when sizes aren't divisible). The larger is your original bitmap, the better.
Scaling a bitmapped font is the same problem as scaling any other bitmap. The general class of algorithm that you're after is interpolation. There's quite a few ways to do this - in general, the more visually accurate the result, the more complicated the algorithm. You could start by looking at (in increasing order of complexity):
Nearest-neighbour
Bilinear interpolation
Bicubic interpolation
It's pretty simple. If all you've got is a bitmapped font instead of an outline font then you have very limited choices in picking an anti-aliasing pixel color. For example, if the bitmapped font point size is exactly four times as large as the desired display point size then you can only ever get 16 distinct choices. The number of 'lit' pixels in the 4x4 mapping rectangle.
Having to deal with fractional mapping is a programming exercise but not one that improves the quality.
If it is acceptable to constrain the downscaling to multiples of 2 (50%, 25%, 12.5%, etc.), then a very simple and fairly good algorithm is to create each downscaled pixel as the majority vote of all the source pixels. For example, at 50%, a square of four pixels are forming the one downscaled pixel: if zero or one of them is on, then the output is off; if three or four are on, then the output is on. The artistic case (for two pixels on), either always choose on or off, or look at other surrounding pixels for tiebreaking.

Simple circular gesture detection

I'm looking at a simple, programmatic way of detecting whether or not the user has drawn a circular shape. I'm working in C, but am happy to work from pseudo-code. A bit of Googling brings up a number of (hopefully) overly-complex methods.
I'm tracking the mouse coordinates as floats, and have created an array of vectors to track the mouse movement over time. Essentially I'm looking to detect when a circle has been drawn and then disgard all movement data not associated with that circle.
I have a basic idea of how this might be accomplished:
Track all movements using a polling function. Each time the function is polled the current mouse position is stored. Here, we loop through the historic position data and do a rough 'snap to position' to compare the two locations. If the new location is within a close enough distance to an old position, we remove all historic data before the old location.
While this works in theory, it's a mess in practice. Does anyone have any suggestions? Bonus points if the method suggested can detect whether it's been drawn clockwise or counter-clockwise.
Based on your tracking/polling function, which pushes float pairs on a stack. This must be done on a regular timing interval.
Do a threshold-based search for two equal entries in the list. Now you have two indexes in your stack; the first and the second equal entries. Consider this as a line.
Get the absolute difference in indices. Then divide by two and get the coordinates of this point. (Center of the line.)
You've got two points: thus you can get the radius of the circle, by getting the distance between the two points divided by two.
Divide the number of step 2 by 2, now you've got the quarters.
If the line at step 1 is vertical and the first point of the line is at the top: If the first quarter is left of the center-point, the circle was drawn counter-clockwise. If the first quarter is right of the center-point, the circle was drawn clockwise. If the first point of the line is at the bottom, reverse (i.e. ccw => cw and cw => ccw)
If the line at step 1 is horizontal and the first point of the list is at the left: If the first quarter is above the center-point, the circle was drawn counter-clockwise. If the first quarter is below of the center-point, the circle was drawn clockwise. If the first point of the line is at the right, reverse.
Check if it was a circle: iterate over all pairs of coordinates and calculate the distance to the center-point. Tweak the threshold of allowed distances from the calculated distance and the actual distance to the center-point.
In step 2 and 4 you can tweak this algorithm further by taking the average of several indices if the timing interval is very low (fast polling). For instance: there are 30 pairs in the array, then you average pairs at 0, 1 and 28, 29 to get the upper point. Do the same for all other points.
I hope this is easy enough.
You are definitely on the right track IMHO. Basically you need to compare each mouse point with the previous mouse point and calculate the angle between them (as envisioned on a unit circle where the first point is at the origin). For this you can use the formula:
double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;
if (angle < 0)
angle += 360;
What you end up with is that for clockwise movement, the angle will cycle in a positive direction, whereas for counterclockwise movement the angle will cycle in a negative direction. You can figure out if the current angle is greater or less than the previous one with the following logic:
if (angle2 > 270 && angle1 < 90)
{
angle1 += 360
}
else if (angle1 > 270 && angle2 < 90)
{
angle2 += 360
}
bool isPositive = (angle2-angle1 > 0);
If you get a certain number of vectors all with angles that are increasing (isPositive is true, let's say, 10 times), you can assume a clockwise circle is being drawn; if the tendency is negative (isPositive is false 10 times) it's a counterclockwise circle. :)
Here's an algorithm to see if an array of points fits a circle:
calculate the centroid of the points (average of all the x and y coordinates)
calculate the distance of all points to the centroid
find the maximum and minimum distances
if maximum - minimum < tolerance, circular section detected
NB This will detect a section of a circle as well so you will need to determine that enough of an angle is swept through for it to be a full circle.
To do this:
calculate centroid as above
calculate angle between centroid and each point (use atan2 function)
map angles to segments (I find 12 30 degree segments works for me; just divide angle by 30 and round down to integer - assuming you are working in degrees here)
if all segments contain at least 1 point, then it is a circle (i.e. your mapped segments array contains all values between 0 and 11)
bonus: increasing angle is anti-clockwise; decreasing is clockwise
Haven't tried this, but the idea came to mind reading your question, so might as well share it with you:
I'm assuming the circle has to be drawn within a reasonable amount of time, given a steady "sample-rate" of the mouse that would leave a known-size array of 2D vectors (points). Add them all and divide by the count of 2D vectors to get an estimate of the "center" point in the array. Then form vectors from this center-point to the points in the array and do dot-products (normalizing by vector length), making sure the sign of the dot-products remain identical for a range of points means those points all move in the same direction, a positive sign will indicate counter-clockwise movement, negative is just the opposite. If the accumulated angle exceeds 2 PI, a circular movement was drawn..
Good luck.
1 - Pick any 3 of the points
2 - If the points are collinear +/- 'some buffer' then it isn't a circle.
3 - Use the method described on Wikipedia for finding the circumscribed circle for a triangle to find the midpoint and radius of your candidate circle
The circumcenter of a triangle can be constructed by drawing any two
of the three perpendicular bisectors. For three non-collinear points,
these two lines cannot be parallel, and the circumcenter is the point
where they cross. Any point on the bisector is equidistant from the
two points that it bisects, from which it follows that this point, on
both bisectors, is equidistant from all three triangle vertices. The
circumradius is the distance from it to any of the three vertices.
4 - Check the distance to the remaining points. If those points are within the 'candidate circle radius' +/- 'some buffer allowance' then it is a circle.
5 - To determine direction, simply calculate the angle between the first and 2nd points from the midpoint. A negative angle is right. A positive angle is left. (Could be reversed depending on the coordinate system you are using)

Resources