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 cannot use any Java data structure except Arrays (not even ArrayList) or I can use my own defined data structure.
I am new in this area and am trying to solve it. What steps must I follow to solve this problem?
My main issue is, how do I represent the images as graphs in Java code (for instance with arrays or my own data structure)?
You can apply a varying opacity level at boundary to the center of image.So the edges cannot be identified.
see http://sreejithvs999.wordpress.com/2013/06/12/transparent-image-composition-in-java-fixing-an-image-over-another-with-changing-opacity-or-alpha-of-pixels/
where one image is fixed over another with changing transparency.
Here is what can be an answer to your "Main issue" part of the question.
You have to represent the images pixels as graph and also you have a restriction to use Java array only. Well if you look at a 2 dimensional array which you will need to use represent the pixels of the image, it can be used as an graph as well just that each item in the array will only have data value (pixel color) and the attached node to the current node can be calculated using the below formula:
Current pixel : [X,Y]
Top pixel : [X,Y-1]
Bottom pixel : [X,Y+1]
Left pixel : [X-1,Y]
Right pixel : [X+1,Y]
NOTE: X and Y are index in the 2D array. Also, when incrementing/decrementing X or Y to calculate neighbor pixel you need to make sure that you dont't overflow/underflow the boundary of the image i.e decrementing should not cause the value of X/Y to be < 0 and increment should not cause the X to go beyond width of image and Y to go beyond height of image.
Refer: http://docs.oracle.com/javase/tutorial/2d/images/index.html
Related
I have one BufferedImage image1 and BufferedImage image2, and I want to know if they are equal.
image1 is made before-hand and stored into an image file, where I convert using ImageIO. However, image2 is made on the spot, so it is pretty much guaranteed that they have different sizes. What I do know is that image2 will equal one of 9 different image1's.
So, what I want to do is check if they are the same image's, but ignoring all the white pixels on the edge because they are different size, so if I compare all the pixels they would be different no matter what. If you're wondering why there is the color white on the edge, the images are numbers so the remaining space will be white.
If you want to make it simpler, the color of the real image will always be black, but I would like it better if you make it a generic solution (meaning taking in account all colors) so I could use the concepts later.
private boolean equals(BufferedImage image1, BufferedImage image2) {
// This is what I want to fill out.
}
What I first tried to do was to find the first non-white pixel of image1, and the first non-whiten pixel of image2, and then check the rows after that to see if everthing is equal. However, the images are pretty big, and this approach takes more than O(n ^ 2). I need a faster way.
What I first tried to do was to find the first non-white pixel of image1, and the first non-whiten pixel of image2, and then check the rows after that to see if everthing is equal. However, the images are pretty big, and this approach takes more than O(n ^ 2). I need a faster way.
Most probably there is no very faster way using this approach. You can use edge detection, but the algorithms for that aren't really faster too.
I would try to work with bounding boxes for each image (number).
If it is possible to save image1 the size the number is, this were the way to go. Just shrink the image to the real size of the number and save that image to disk. You then can shrink image2 to its bounding box too and the comparison is quite simple and fast.
If shrinking is no option, calculation of the bounding box is an option. Go through the image array and detect the top most and the left most pixel in both images. You then get at least the bounding edges for the top and left side, which is all you need to compare the images. (If images can differ in size, you need the whole bounding box)
By the way, you don't need to run in O(n^2). If you detect the top most or left most pixel in both images, you can set an offset to work from. You only need to find a difference to state that these numbers are different. You can work with logic to determine, which number it must be based on simple tests. For example take numbers one (1) and zero (0). Whereas zero has white pixels in the middle part, the one must have black pixels there and vice versa. So detecting areas where the numbers definitely are black or white can help you estimate the number in the image by testing up to 9 areas.
I am about to write a java program which can smooth an image (2D Array) by a 3 by 3 mask and hesitate about which of the following strategies is right for application of the mask to the image:
1- Apply the mask to a portion of the image and immediately change the target pixel in the original image and move the mask to calculate the value of the next target pixel and so on.
2- Copy the original image into another backup image, then apply the mask to a portion of the original image and then change the target pixel in the copy image instead of original image.
In the second way, the original image would not change during the application of mask; only the new values are inserted into the backup image during smoothing. So the backup image will contain the smoothed image. Thanks.
Does not feel so good to answer my own question but in the spirit of helping others that have an image processing course and work with binary images, my experience might be helpful. After doing some trial-and-error experiments, I found that actually the second way is the right way and the first one is Wrong. Because changing the original values of a matrix while you are scanning it (at the same time) will lead to an inconsistency. I mean you will have a messed matrix at the end which won't maintain the original shape and instead of smoothing (removing noise pixels) it is just scrambling and ruining the original image. So, first I had to copy the original matrix and in each step of applying the mask, I just changed the target value in the copy matrix. Finally, the copied matrix would be your smoothed binary image.
I have a screenshot taken from java.awt.Robot as a java.awt.image.BufferedImage and know there will be a unique 10x10 solid red (same RGB) coloured square somewhere in that screenshot (more likely closer to the middle).
What's an efficient approach to finding its coordinates? Is JavaCV even the right library to use? I found a brute force approach in .net here: Bitmap Detection but I'm wondering if there's a better way.
The first question is, what does it take to recognize the color - is it an exact RGB value, where either the color is an exact match, or it isn't? And will that still be the case if the image is lossy-compressed, for example as a JPEG?
Assuming you can do that, probably you want to do a search that tries to minimize time spent searching areas which won't be fruitful: On an imaginary line between two opposite corners, test the value at each corner and the midpoint; if no match, try at the midpoint between the midpoints and the corners; if no match, divide the space in half vertically or horizontally and try again; once you find a pixel of the right color, have some code that walks the pixels in each direction to determine if it's really 10x10.
Really any sort of search pattern will work; what you probably don't want is a situation where you just start at 0,0 and go 0,1 0,2 ... 1,0 1,2 since that will make matching in the upper left fast and bottom right slow (assuming a coordinate space that starts at the top left).
I have an app where the user draws pictures and then these pictures are converted to pdf. I need to be able to crop out the whitespace before conversion. Originally I kept track of the highest and lowest x and y values (http://stackoverflow.com/questions/13462088/cropping-out-whitespace-from-a-user-drawn-image). This worked for a while, but now I want to give the user the ability to erase. This is a problem because if for example the user erases the topmost point the bounding box would change, but I wouldn't the new dimensions of the box.
Right now I'm going through the entire image, pixel by pixel, to determine the bounding box. This isn't bad for one image, but I'm going to have ~70, it's way too slow for 70. I also thought about keeping every pixel in an arraylist, but I don't feel like that would work well at all.
Is there an algorithm that would help me solve this? Perhaps something already built in? Speed is more important to me than accuracy. If there is some whitespace left on each side it won't be a tragedy.
Thank you so much.
You mentioned that you are keeping track of the min and max values for X and Y co-ordinates (that also seems the solution you have chosen in the earlier question).
In similar way to this, you should be able to find the min and max X & Y co-ordinates for the erased area, from the erase event...
When the user erases part of the image, you can simply compare the co-ordinates of the erased part with the actual image to find the final co-ordinates.
There is a related problem of trying to see if 2 rectangles overlap:
Determine if two rectangles overlap each other?
You can use similar logic (though slightly different) and figure out the final min/max X & Y values.
I have an image which is not a square (m x n dimension). Also its dimensions are not to the base 2 (i.e m not = 2^k & n not = 2^k). I have dealt with this by placing the image in a larger square (the next power of two) using the following:
int width = (int)Math.ceil(Math.pow(2, Math.log(img.width)/Math.log(2)));
int height = (int)Math.ceil(Math.pow(2, Math.log(img.height)/Math.log(2)));
Depending on which yields the biggest dimension, I set the square to be drawn at the max dimension, that is:
if (img.width > img.height) {
// draw width * width square
}
if (img.height > img.width) {
// draw height * height square
}
Issue:
The quadtree now looks completely different as it is storing all the non-image nodes in the tree. This obviously affects the supposed image data (i.e. min/max depths) and the entire tree shape itself. My question is, am I doing this in an efficient way and if so, how do I not store the data that doesn't belong to the image? If it isn't the best way to draw a non-square image could someone point me in the right direction? All articles on google seem to be far too in depth for my purposes.
The nice thing about quadtrees is they will store large chunks of identical data. Your extra blank image data should only be adding a little to your overall storage size. I suggest, you add an extra bit of information with your data structure that stores the actual original dimensions of the image. When deserializing your quadtree, you can "cut" off the extra part based on the actual dimensions to produce your original.
Perhaps instead of having your tree terminate in (notional) individual pixels, it could store small blocks of p pixels by o pixels, for some p x o which would make the number of blocks per side a power of two. That would make your tree behave nicely, at the expense of introducing another concept into the structure.