我的问题是,我有一个带有小透视图的矩形,我想将其向后拉伸,以再次显示为矩形。
为了直观地表示它,我目前在我的图像中有类似红色形状的东西,我有4个Points
(这个形状的每个角)。因此,我希望拥有类似于蓝色形状的东西,并且我已经有了它的Rectangle
对象。
我想知道是否有一种方法可以复制一个多边形,并将其绘制为另一个拉伸的多边形。我找到了适用于Android (setPolyToPoly)的东西,但我找不到适用于java的类似这样的东西。
有没有一些参考或代码样本来执行这个操作,或者可能有一些想法可以解决这个问题?
发布于 2013-05-28 16:49:27
我想我知道你需要什么:一种可以应用于图像的所谓透视变换。Java有内置的AffineTransform,但是仿射转换总是保留行的“并行度”,所以您不能使用它。
现在,如果你在网络上搜索"java透视图转换“,你会发现很多选项,比如JavaFX PerspectiveTransform,JAI PerspectiveTransform。如果您只需要拉伸图像,您也可以使用JHLabs PerspectiveFilter,还有其他选项。
发布于 2013-05-25 18:11:20
下面是一些代码,可以将一个有四个点的多边形拉伸成一个矩形。
public static Rectangle2D polyToRect(Polygon polygon) {
if (polygon.xpoints.length != 4 || polygon.ypoints.length != 4)
throw new IllegalArgumentException(
"More than four points, this cannot be fitted to a rectangle");
Rectangle2D rect = new Rectangle2D.Double();
for (int i = 0; i < 4; i++) {
Point2D point = new Point2D.Double(polygon.xpoints[i],
polygon.ypoints[i]);
rect.add(point);
}
return rect;
}
public static Polygon rectangleToPolygon(Rectangle2D rect) {
Polygon poly = new Polygon();
poly.addPoint((int) rect.getX(), (int) rect.getY());
poly.addPoint((int) (rect.getX() + rect.getWidth()), (int) rect.getY());
poly.addPoint((int) (rect.getX() + rect.getWidth()),
(int) (rect.getY() + rect.getHeight()));
poly.addPoint((int) rect.getX(), (int) (rect.getY() + rect.getHeight()));
return poly;
}
public static class drawPolyAndRect extends JPanel {
Polygon poly = new Polygon();
public drawPolyAndRect() {
poly.addPoint(0, 0);
poly.addPoint(400, 40);
poly.addPoint(400, 250);
poly.addPoint(0, 400);
}
@Override
@Transient
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.green);
g2d.fill(poly);
Composite c = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
0.5f);
g2d.setColor(Color.blue);
g2d.setComposite(c);
Rectangle2D polyToRect = polyToRect(poly);
g2d.fill(polyToRect);
// displace for drawing
polyToRect.setFrame(polyToRect.getX() + 100,
polyToRect.getY() + 100, polyToRect.getWidth(),
polyToRect.getHeight());
Polygon polyToRectToPoly = rectangleToPolygon(polyToRect);
g2d.fill(polyToRectToPoly);
g2d.dispose();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Poly to rect");
frame.getContentPane().add(new drawPolyAndRect());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
本质上,这使用了将点添加到空rectangle2d的工作方式,它构建了包含所有四个点的最小矩形,拉伸了多边形。如果希望将返回的矩形作为多边形,请选中第二个静态方法。图片:
发布于 2013-05-28 22:42:35
根据@lbalazscs answer的建议,使用PerspectiveTransform的基于JavaFX的解决方案。
Toggle Perspective
在content.Morph Perspective
上打开和关闭透视效果,平滑地在透视转换和非透视转换内容之间进行动画转换。
import javafx.animation.*;
import javafx.application.*;
import javafx.beans.value.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.ToggleButton;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.*;
import javafx.stage.Stage;
import javafx.util.Duration;
public class PerspectiveMovement extends Application {
// perspective transformed group width and height.
private final int W = 280;
private final int H = 96;
// upper right and lower right co-ordinates of perspective transformed group.
private final int URY = 35;
private final int LRY = 65;
@Override public void start(Stage stage) {
final PerspectiveTransform perspectiveTransform = createPerspectiveTransform();
final Group group = new Group();
group.setCache(true);
setContent(group);
final ToggleButton perspectiveToggle = createToggle(
group,
perspectiveTransform
);
VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().setAll(
perspectiveToggle,
createMorph(perspectiveToggle, group, perspectiveTransform),
group
);
layout.setStyle("-fx-padding: 10px; -fx-background-color: rgb(17, 20, 25);");
stage.setScene(new Scene(layout));
stage.show();
}
private void setContent(Group group) {
Rectangle rect = new Rectangle(0, 5, W, 80);
rect.setFill(Color.web("0x3b596d"));
Text text = new Text();
text.setX(4.0);
text.setY(60.0);
text.setText("A long time ago");
text.setFill(Color.ALICEBLUE);
text.setFont(Font.font(null, FontWeight.BOLD, 36));
Image image = new Image(
"http://icons.iconarchive.com/icons/danrabbit/elementary/96/Star-icon.png"
);
ImageView imageView = new ImageView(image);
imageView.setX(50);
group.getChildren().addAll(rect, imageView, text);
}
private PerspectiveTransform createPerspectiveTransform() {
PerspectiveTransform perspectiveTransform = new PerspectiveTransform();
perspectiveTransform.setUlx(0.0);
perspectiveTransform.setUly(0.0);
perspectiveTransform.setUrx(W);
perspectiveTransform.setUry(URY);
perspectiveTransform.setLrx(W);
perspectiveTransform.setLry(LRY);
perspectiveTransform.setLlx(0.0);
perspectiveTransform.setLly(H);
return perspectiveTransform;
}
private ToggleButton createToggle(final Group group, final PerspectiveTransform perspectiveTransform) {
final ToggleButton toggle = new ToggleButton("Toggle Perspective");
toggle.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override public void changed(ObservableValue<? extends Boolean> observable, Boolean wasSelected, Boolean selected) {
if (selected) {
perspectiveTransform.setUry(URY);
perspectiveTransform.setLry(LRY);
group.setEffect(perspectiveTransform);
} else {
group.setEffect(null);
}
}
});
return toggle;
}
private ToggleButton createMorph(final ToggleButton perspectiveToggle, final Group group, final PerspectiveTransform perspectiveTransform) {
final Timeline distorter = new Timeline(
new KeyFrame(
Duration.seconds(0),
new KeyValue(perspectiveTransform.uryProperty(), 0, Interpolator.LINEAR),
new KeyValue(perspectiveTransform.lryProperty(), H, Interpolator.LINEAR)
),
new KeyFrame(
Duration.seconds(3),
new KeyValue(perspectiveTransform.uryProperty(), URY, Interpolator.LINEAR),
new KeyValue(perspectiveTransform.lryProperty(), LRY, Interpolator.LINEAR)
)
);
final ToggleButton morphToggle = new ToggleButton("Morph Perspective");
morphToggle.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override public void changed(ObservableValue<? extends Boolean> observable, Boolean wasSelected, Boolean selected) {
if (!perspectiveToggle.isSelected()) {
perspectiveToggle.fire();
}
if (selected) {
distorter.setRate(1);
distorter.play();
} else {
distorter.setRate(-1);
distorter.play();
}
}
});
return morphToggle;
}
}
https://stackoverflow.com/questions/16747951
复制