How does a QuadTree work for non-square areas? - java

I understand how quad trees work on square images (by splitting the image until the section is a single colour, which is stored in the leaf node).
What happens if the image has one dimension longer that the other, you may end up with a 2x1 pixel area as the smallest sub unit, making it difficult to use quadtree division methods to store a single colour. How would you solve this issue?

You could pad the image until it is an equal and power of two size. While it may add some extra memory requirements, the increase shouldn't be that large.
The 2x1 example would be padded to a standard 2x2 and store the real size or use a special value for padded nodes so you can restore the original size.

Why don't you allow empty leafes in your tree?
Edit:
Maybe i don't understand the question^^. Your problem is that you end up with a non square images like 2x1 and want to represent them as a quadtreenode?
When you have a 2x2 square like
1 2
3 4
you would create a Quadnode with something like "new QuadNode(1,2,3,4)"
I would suggest to handel a 2x1 square like
1 2
with something like "new QuadNode(1,2,null,null)"
When you have bigger missing pieces you can use the same system. When you have a 4x2 picture like
1 2 3 4
5 6 7 8
you would get a "new QuadNode(new QuadNode(1,2,3,4),null,new QuadNode(5,6,7,8),null)"
This should also work with pieces with equal color instead of pixels.
Did i understand your problem and made myself clear?

A square is a special rectangle, Quad trees work on rectangles, too.
You just need a split method which gives 4 rectangles for a given one.
In case the top most root quad cell is an rectangle, just divide the width and height by 2.
In case of pixels, it makes only sense if the root cell widthand height are both a power of 2.
So if root cell = 2048 * 1024
The split just divides both width and height by 2.

Related

Issues with simple algorithm for automatic assembly of jigsaw puzzles (with rectangular tiles) in Swing

I needed to design solver for puzzle, that is splitted in rectangular tiles (several rows and columns) with:
BufferedImage subImage =
image.getSubimage(y, x, dWidth, dHeight)
then resized with some ratio < 1.0:
BufferedImage resized = new BufferedImage(newWidth, newHeight, original.getType());
The idea behind my algorithm is to sum the difference between every appropriate pixels of current tile side and all other opposite tiles sides -
for example for right edge - I define such code:
for(Side s:reverseSides) { ...
{for(int i=0;i<height;i++) //checking current tile's right side
int rgbValue1=image.getRGB(width-1,i); //right side rgb values of current tile
int rgbValue2=imageN.getRGB(0,i); //left side rgb values of other tiles
....
int diff=|rgbValue1-rgbValue2|;
sum+=diff;
}
}
According to some algorithm, I start with some side whose sum of
rgbvalues is in the very midth of the whole range of such sums of all
sides (sortinglistBySum/2). Then I find minimal sum for with all
opposites sides, and traverse all other 3 sides of this Tile, then go
for Tiles, that has at least one already processed side, stored in
queue untill all sides are processed in consecutive fashion.
But first big issue, not expected, is in that this minimal sum for
about 80 pixels (in width or height) is around 50-70 000 000
units(RGB), when maximal could be more over 1000 000 000. So this
minimal sum, and even one difference for example first/second/Npixel
getRGB(width-1,1) - getRGB(0,1) -- is big enough. Indeed before splitting -
the difference between pixel position in adjacent edges
should be just 1 pixel??
So, in this case if left tile "right edge index" width-1=80, then 0
index in matching left side of right tile should be 81. Or at least
difference could be 2- if one vertical pixel line is lost when image
is splitted, and division of image width by number of columns does
not produce integer value (I suppose that it is not real image so no
pixels should be lost technically, just mathematically).
But when I calculate sum of diff. of two adjacent vertical (or
horizontal) lines of pixels in one tile - getRGB(width-2,i) -
getRGB(width-1,i) - it produce far lower values - some about 5-7 000
000. getRGB(width-3,i) - getRGB(width-1,i) - 30-40 000 000. So I do not undestand why such big difference between adjacent pixels sets of
original image?
The another issue is that when I found reverse side with minimal
difference I check minimal sum of difference for this opposite side
with reverse sides for it - and only if there is mutual match of sum
of diff. I define these sides as adjacent, also restricted if this
common minimal sum are less then some threshhold value defined
empirically by myself - in my case I suppose it about 150 000 000
(RGB diff.), but it is just approximation.
But there is third, probably most difficult issue - how check if this
matched side(s) is not edge side of the whole image, even there is
mutual match of sums, and less then threshold but in practice these
sides should not be matched as they are not adjacent in original
picture?!
This approach works relatively fine, except a lot of aspects to take
into account, as well as difficulties of moving and changing grid
cells in Java Swing layout.For example matching of the "single edge"
issue happened in my third testing image, in one of the last
iteration, but it could happened also at the start.Threshold value is
in some infrequent cases above for no-mathcing sides (that indeed
mutually matched with minimal sums), or under the really matching
sides.
So what are suggestions and references for simple assured
algorithms, what more reliable edges checking and patterns to use? Why so big sum of difference of rgb values of adjacent sides??
I have read even before, that it should sum difference of square rgb values, but what it changes? Also read suggestions to have some statistically based algorithm so probably check all combinations - checking combination of edge traversing from every present edge (not just one) and then choose optimal combination.

Get rectangle bounds for each letter in a image

So I'm trying to fill an ArrayList<Rectangle> with the bounds of each letter of an image file.
For example, given this .png image:
I want to fill an ArrayList<Rectangle> with 14 Rectangle(one rectangle for each letter)
We can assume that the image will contain only 2 colors, one for the background and one for the letters, in this case, pixels will be either white or red.
At first, I thought I could search for white columns in between the letters, then if I found a completely white column I could get for example the width by getting the lowest red pixel value and the highest red pixel value and width = maxX-minX and so on:
x = minX;
y = minY;
w = maxX-minX;
h = maxY-minY;
letterBounds.add(new Rectangle(x,y,w,h));
The problem is that there's no space in between the letters, not even 1 pixel:
My next idea was for each red pixel I find, look for a neighbor that hasn't been seen yet, then if I can't find a neighbor I have all the pixels to get the bounds of that letter. But with this approach, I will get 2 rectangles for letters like "i" I could then write some algorithm to merge those rectangles but I don't know how that will turn out with other multi part letters, and before I try that I wanted to ask here for more ideas
So do you guys have any ideas?
You can use the OpenCV cv2.findContours() function. Instead of using the cv2.drawcontours() function for drawing the contours, which will highlight the outline of the letter, you could instead draw a rectangle on the image by using the cv2.rectangle and by extracting the coordinates from cv2.findContours() function.
I think two step algorithm is enough to solve the problem if not using library like OpenCV.
histogram
seam calculation
1. histogram
C.....C..C...
.C.C.C...C...
. C.C....CCCC
1111111003111
dot(.) means background color(white)
C means any colors except background color(in your case, red)
accumulating the number of vertical pixels with non-background color generates histogram.
*
*
******..****
0123456789AB
It is clear the boundary exists at 6 and 7
2. seam calculation
Some cases like We, cannot be solved by histogram because there is no empty vertical lines at all.
Seam Carving algorithm gives us some hints
https://en.wikipedia.org/wiki/Seam_carving
More detail implementation is found at
princeton.edu - seamCarving.html
Energy calcuation for a pixel
The red numbers are not color values for pixels, but energy values calculated from adjacent pixels.
The vertical pathes with minimal energy give us the boundary of each characters.
3. On more...
Statistical data is required to determine whether to apply the seam carving or not.
Max and min width of characters
Even if histogram give us vertical boundaries, it is not clear there are two or more characters in a group.

How to Render text to bitmap and draw it

I am new to android, and my group is currently creating a graphing application using a GlSurfaceView using opengl es 2.0.
We have recently displayed the grid and tickmarks on the plot and now I have been assigned the task to implement a numeric scale and labeling the x and y axis as "X" and "Y".
After doing a lot of research I have determined to accomplish this by rendering a string of characters to a bitmap. I have encountered many problems in achieving this. I understand the basic concept. I know I will need the alphanumeric characters "0123456789" and "XY"and"-"(for the -x and -y scale). I have seen many different examples and have tried extensively to follow JVitella's example here here
I am beginning to grasp the concept but as far as the my string goes I know I have 13 characters so how large should my bitmap be?
Also in Jvitelas example I am dumbfounded by the code:
Drawable background = context.getResources().getDrawable(R.drawable.background);
I dont understand what exactly is going on and when I code this I recieve a syntax error on context.
For my application I understand I would need to save the string into a bit map much like this. I would create a bitmap but how big should it be? Then I create a canvas from the bitmap and canvas.drawText into the bitmap.
[ 0 1 2 3 4 ]
| 5 6 7 8 9 |
[ X Y Z ]
Basically I am asking:
How to achieve the following bit map above?
How would I draw single digit numbers from the bit map?
How would I draw numbers with more than one digit?
You're asking a lot of questions, but I'll try to answer a few:
so how large should my bitmap be?
It's really up to you, depending on how crisp you want the text to be. You could allocate a huge bitmap with hundreds of pixels for each character that would zoom very well, or a very small bitmap with limited resolution. I'd say whatever "font size" you want to have, allocate at least that many pixels in height for each character. So if you want to draw something with a font size of "20", then maybe you need a bitmap 5x20 by 3x20 or 100x60.
How would I draw single digit numbers from the bit map?
You'll draw a quad with opengl in the place where you want to draw a letter, and you use the texture coordinates of that quad to pick a letter.
For example if I want to draw an X, then you draw a quad on the screen, and assign it's texcoords from (0,0) to (0.2, 0.33), which selects the left 1/5th of the texture, and the bottom 1/3rd of the texture. You'll see how a box like this lines up with the position of the "X" in your texture.
How would I draw numbers with more than one digit?
You just draw two independent single digits right next to each other.
If your only goal here is to draw text in Android, it might be easier to just use a FrameLayout, and layer TextViews overtop of your GLSurfaceView. OpenGL isn't designed for text which makes it somewhat cumbersome.

Image compositing of two Images

I am trying to solve a problem of compositing two images in Java. The program will take a part of the first image and past it on the second image. The goal is to make the boundary between the two images less visible. The boundary must be chosen in such a way that the difference between the two images at the boundary is small.
My Tasks:
To write a method to choose the boundary between the two images. The method will receive the overlapping parts of the input images. This must first be transformed so that the boundary always starts from the left-top corner to the right-bottom corner.
NOTE:
The returned image should not be the joined image but gives which parts of the two images were used.
The pixels of the boundary line can be marked with a constant(SEAM). Pixels of the first image can be marked with integer 0, pixels of the second image with integer 1. After choosing the boundary line, the floodfill algorithm can be used to fill the extra pixels with 0 or 1.
NOTE: The image can be represented as a graph whereby each pixel is connected with its left, right, top and bottom neighbor. So using the flood fill will be like depth-first search.
The shortest path algorithm must be used to choose the boundary in order to make it small.
NOTE: I can not use any java data structure except Arrays (not even ArrayList)
Guys, am new in this area and am trying to solve it. What steps must I follow to solve this problem? or a pointer to a tutorial
I would do it so:
Choose the width of the border checked. At your will.
1. find the maximal possible shift in pixels. That is D.
2. For all possible shifts in the square (+-D,+-D) find the k (correlation quocient) for the border. The border is taken in the middle of the shift.
3. The shift that has the largest k is the best. Let it be taken for granted.
4. Now begin to move the border, checking it by "k" the same way. Find the place of it. Done.
If D is large and the process is long, do it in 2(or more) stages. On the first stages the step of counting k is large, the last stage has step of 1. You could also use previous filtering.
If the border or relative images' position could be turned, the algorithm doesn't change principally - only add to it trying for the best k among different slightly turned positions and later - turned border, too.

"Zoom" text to be as big as possible within constraints/box

First problem: You have 400 pixels width to go on, and need to fit some text within that constraint as large as possible (thus, the text shall use that amount of space).
Throw in a new constraint: If the text is just "A", then it shall not zoom this above 100 pixels height (or some specific font size).
Then, a final situation: Linebreaks. Fit some text in the largest possible way within e.g. 400 x 150 pixels.
An obvious way is to simply start with point 1, and then increase until you can't fit it anymore. This would work for all three problems, but would be very crude. The fitting of a single line within bounds could be done by writing it with some fixed point size, check the resulting pixel bounds of the text, and then simply scale it with a transform (the text scales properly too then, check out TransformUI).
Any ideas of other ways to attack this would be greatly appreciated!
As what you are modelling is complex, especially with line breaks, then your initial proposal of trying all sizes is along the right lines, especially if it needs to be accurate.
However, rather than testing each value, you can use a binary search to find the appropriate font size. You know the size is somewhere between 1 and 100 (your upper range). using a binary search, each test sets the font size and checks the resulting layout. If the text is too large, then we search the lower half of the current range of possible values. If the font size fits, then we search the upper half. Your search will use at most 7 attempts (100 log base 2 rounded up), it will be exact, finding the largest size without going over, and it will be flexible if you need to add more requirements later, such as a mix of fonts or more stringent constraints on the layout.
I'm assuming you are using a text component that does line wrapping, and that you can set the maximum width to 400. So, you set the font size and it does the layout giving you back the required height, laying out text within the given width.
You can use hints to try to guide the algorithm to the result quicker, such as making your first guess close to the expected size, but text rendering is fast, that the performance increase may not be worth the implementation effort.
See Wikipedia - Binary Search Algorithm
I would do the following:
Assume you want W pixels wide text.
Pick an arbitrary size, say 10pt, and see what bounding box the text-string gets for that size. Lets say it gets N pixels wide.
Set the new size to 10pt * W/N, and repeat from step one, until you get within a reasonable threshold. (Hopefully it would work within one iteration.)
This relies on the fact that the width of the string, is roughly proportional to the size of the font.
I'd instantiate the Font at the largest desired size: say 72 for one inch glyphs at 72 dpi. Use TextLayout to get the bounds and scale using AffineTransform (direct) or AffineTransformOp (offscreen), while preserving the aspect ratio. Suitable RenderingHints help, too.

Categories

Resources