Adjusting an image to any given quadrilateral - java

I have a cube which can be rotated in x,y and z direction.I figured out how to draw its wireframe and how to fill the sides with one colour per side.But my attempts to texture the cube failed.All possibilities to adapt an image to non-cubic shapes I have found use an external library but I want to do it in pure java.
Here is what i tried:
Polygon polygon = new Polygon();
polygon.addPoint((int)p[1][x]+200, (int)p[1][y]+200);
polygon.addPoint((int)p[2][x]+200, (int)p[2][y]+200);
polygon.addPoint((int)p[6][x]+200, (int)p[6][y]+200);
polygon.addPoint((int)p[5][x]+200, (int)p[5][y]+200);
g.setClip(polygon);
g.drawImage(tex, (int)p[1][x]+200, (int)p[1][y]+200, null);
g.setClip(new Rectangle(0, 0, this.getWidth(), this.getHeight()));

you have to transform the image, you can shear, rotate, translate etc on your image...
to do so you need an Affine-matrix to transform the image...
once you know how to use the matrix you can also use it to transform your points, it's a very comfortable way
see also the a question on how to shear a bitmap:
btw: nice work, there doing it in pure java!
sorry, when i'm only responding in sending links, but maybe you can be a bit more specific on your ptoblem =)

Related

Drawing images to 4 different points

I have a quadrilateral drawn in Path2D, and I would like for there to be an image on it. More specifically, I am trying to draw an image of my choice to 4 different points on a quadrilateral. In my case, it is a parallelogram. I do not want the image to go over the paralellogram. A better way to see what I am trying to say is to see the screenshot below.
I would like the image to be transformed to fit the green area. Not clipped.
I want the image to be pinned over the green paralellogram. However. I do not want the image to go over into the blue paralellogram, or the white space foe that matter.
So far I have tried
Researching for a way to place images directly onto Path2D.Double() objects. No answer
Rotating the image to fit the paralellogram. Didnt work.
Using AffineTransform in java. Dont get it ;-;
Thanks. I am new to java so do try to be lenient?
One way is to:
create a separate BufferedImage.
Apply a transform to the new image.
Draw your image to that new image.
Use the Shape object for the green area as a clip on the main drawing area
Draw the transformed image onto the main drawing area.
It's been a while since I have done transformations. You may have to set the transformation first and then draw the image after. Transformation has to come first.
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.transform(AffineTransform.getShearInstance(1.0, 0));
g2.drawImage(image, 0, 0, this);
}
Here is a simple example of how transforms work. You will have to spend some time on figuring out what values you need to make it work or if you might need to manually create a transformation matrix yourself.

Draw a single sprite to Pixmap - LibGDX

I am currently working on a game in which i need pixel perfect collision with objects. The only obstacle i had gotten to however, is with actually getting a mask of the object. I thought about rendering a sprite of an object (which is properly scaled and transformed) to FrameBuffer, which then i'd convert to a pixmap, but i had no luck doing it (tried many methods, including this)
So, my question is: Is there a way of rendering a single sprite to a pixmap in LibGDX?
Sounds like putting the horse behind the cart. A Sprite is a region of a Texture, which in turn is an image loaded from file aka Pixmap. If you just want to load the image from file then you can do: new Pixmap(Gdx.files.internal("yourfile.png"));. You can also scale and transform your coordinates without rendering to a FBO first.
That said; getting the Pixmap of a FrameBuffer is as "simple" as taking a screenshot while the FBO is bound, because it is exactly that.
fbo.begin();
Gdx.gl.glClear(...);
... //render to the FBO
Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, fbo.getWidth(), fbo.getHeight());
fbo.end();
Note that this will look like it is up-side-down.
But you are probably only interested in the pixel data, so you might as well skip the Pixmap step in that case and use the ScreenUtils.getFrameBufferPixels method.
However, that said; using the pixel data for collision detection is most likely not the best solution for whatever it is you are trying to achieve. Instead I'd advise to look into other options, for example have a look at this tool which can be used to convert your images into a collision shape.

Optimizing performance of GrabCut in opencv-java

Recently I have been given a project, where I have to extract face (face+hair) from a given image.
I am solving this problem in the following ways.
I am extracting face locations from given image. [I am getting a rectangle]
I am extracting that rectangle and placing it in another image of same dimensions as input image.[face_image]
I am applying grabCut algorithm on the face_image of step 2.
When the face_image contains smooth background then the algorithm grabCut it working well but when the background of face_image is complex then the algorithm grabCut extracts some part of background too in the processed image.
Here is a snapshot of the results that I am getting.
Here is my code of grabCut:
public void extractFace(Mat image, String fileNameWithCompletePath,
int xOne, int xTwo, int yOne, int yTwo) throws CvException {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Rect rectangle = new Rect(xOne, yOne, xTwo, yTwo);
Mat result = new Mat();
Mat bgdModel = new Mat();
Mat fgdModel = new Mat();
Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3));
Imgproc.grabCut(image, result, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_RECT);
Core.compare(result, source, result, Core.CMP_EQ);
Mat foreground = new Mat(image.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
image.copyTo(foreground, result);
Imgcodecs.imwrite(fileNameWithCompletePath, foreground);
}
How can I improve performance of grabCut algorithm so that it will detect only face and hair from given image?
You should be able to do this by "helping" grabCut know a little about the foreground and background. There is a python tutorial that shows how this is done manually by selecting the foreground and background.
To do this automatically, you will need to find programmatic ways to detect the foreground and background. The foreground consists mostly of hair and skin so you will need to detect them.
Skin - There are several papers and blogs on how to do this. Some of them are pretty simple and this OpenCV tutorial may also help. I've found plain hue/saturation to get me pretty far.
Hair - This is trickier but is definitely still doable. You may be able to hair and just use skin and background if this turns out to be too much work.
Background - You should be able to use range() to find things in the image that are purple, green, and blue. You know for sure that these things are not skin or hair and are therefore part of the background.
Use thresholding to create a mask of the areas that are most likely skin, hair, and background. You can then use them as bgdModel and fgdModel (or the skin and hair masks) instead of Mat().
Sorry this is so high-level. I hope it helps!
Another approach, since you have already detected the face, is to simply choose a better initial mask for initialising GrabCut - e.g. by using an oval instead of a rectangle.
Detect face rectangle (as you are already doing)
Create a mask:
a) Create a new black image of the same size as your input image
b) Draw a white-filled ellipse with the same height, width, top and left positions as the face rectangle
Call GrabCut with GC_INIT_WITH_MASK instead of GC_INIT_WITH_RECT:
Imgproc.grabCut(image, mask, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_MASK);
This initializes the foreground with a better model because faces are more oval-shaped than rectangle-shaped, so it should include less of the background to begin with.
I would suggest to "play" with the rectangle coordinates (int xOne, int xTwo, int yOne, int yTwo). Using your code and these coordinates 1, 400, 30, 400 I was able to avoid the background. (I tried to post the images I successfully cropped but I need at least 10 reputation to do so)
The best optimization that can be done to any Java routine is conversion to a native language.

Java - drawing a scaled up shape with line thickness of 1

When you use Graphics2D.scale(); and draw a shape, the outline thickness is also scaled.
Is there a way to draw it without the line thickness being scaled? Perhaps there's another efficient way to scale it other than using the above function?
This question is similar. It looks like you have to mess around with a Stroke object to set the right line width.
You're going to have to save your drawing as a list of line vectors, and scale and render the drawing at various sizes to maintain the line thickness you want.
I've just found a solution to my own question. I've no idea how efficient it is but it works as intended:
Area area = new Area(myShape); //myShape is the shape I want to scale
AffineTransform at = new AffineTransform();
at.scale(2,2);
area = area.createTransformedArea(at);
graphics2d.draw(area); //graphics2d is the Graphics2D instance to do the drawing
Perhaps someone could enlighten me as to whether or not this is a good approach to take?

Simple image rotation

I am making a game in Java. I made a planet seen from outer space and I want to make it appear like the planet is slowly rotating. But I don't know how to rotate a image. I need a simple command that rotates my image 1 degree around its own center once. Any help?
This is what I want to do:
Image
Take a look at these tutorials:
Java2D: Have Fun With Affine Transform
Coordinate Translations and Rotations: Example Code
Transforming Shapes, Text, and Images
What you are describing is not rotating an image, but changing an image to represent a 3D rotation of the object in the image.
Ideally you wouldn't be working with this as an image but rather as a 3D object with a different camera angle. Then you would simply rotate the camera around the object and display the resulting image to the user.
However if you're set on doing this as an image, then you need to create a different images representing various states of rotation of your planet and have a separate thread that would replace the displayed image with the next one in sequence, at repeated intervals. Search the web for "java image animation" - there are plenty of tutorials on how to do this.
If you want to rotate an image in 2d space, you can use something like this:
Image image = ...
Graphics2D g2d = ...; //
g2d.translate(170, 0); // If needed
g2d.rotate(1); // Rotate the image by 1 radian
//or g2d.rotate(180.0/3.14); to rotate by 1 degree
g2d.drawImage(image, 0, 0, 200, 200, observer);

Categories