使用Java将彩色图像转换为3D Surf图

时间:2014-06-17 15:06:55

标签: java plot

我的图像使用较暖和较冷的颜色来表示2D空间中的深度。我希望能够将它绘制为3D表面图,就像在Matlab中一样。我一直在玩jzy3d,但我是java的新手,所以我很难做到这一点。理想情况下,就像在Matlab中一样,最好的方法是将其转换为灰度,然后绘制它,但我不知道如何提供任何帮助。

提前谢谢。

1 个答案:

答案 0 :(得分:1)

您应该更详细地描述实际的困难。

然而,我很好奇(并且无论如何想要尝试jzy3d)。因此,我修改了SurfaceDemo.java示例以加载图像并绘制单个像素的Hue值。

enter image description here

它基本上归结为什么"温暖"和#34;冷却器"确切的意思是(没有双关语),但应该可以从色调值中得出它。 (注意:图像中的颜色只是图表的颜色,与图像中的颜色无关。图像中的颜色仅决定图像的高度每个点的情节。)

import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

import org.jzy3d.analysis.AbstractAnalysis;
import org.jzy3d.analysis.AnalysisLauncher;
import org.jzy3d.chart.factories.AWTChartComponentFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
import org.jzy3d.colors.colormaps.ColorMapRainbow;
import org.jzy3d.maths.Range;
import org.jzy3d.plot3d.builder.Builder;
import org.jzy3d.plot3d.builder.Mapper;
import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid;
import org.jzy3d.plot3d.primitives.Shape;
import org.jzy3d.plot3d.rendering.canvas.Quality;

public class BasicJzy3D extends AbstractAnalysis
{
    public static void main(String[] args) throws Exception
    {
        BufferedImage image = ImageIO.read(new File("lena512color.png"));
        AnalysisLauncher.open(new BasicJzy3D(image));
    }

    private final BufferedImage image;

    BasicJzy3D(BufferedImage image)
    {
        this.image = image;
    }


    /**
     * Returns the RGB value in the given image at the specified location,
     * which is given in relative coordinates (between 0.0 and 1.0).
     * Invalid coordinates will be clamped to the border
     * 
     * @param image The image
     * @param x The x coordinate
     * @param y The y coordinate
     * @return The RGB value
     */
    private static int getRGB(BufferedImage image, double x, double y)
    {
        int w = image.getWidth();
        int h = image.getHeight();
        int ix = (int)(x * w);
        int iy = (int)(y * h);
        ix = Math.max(0, Math.min(w-1, ix));
        iy = Math.max(0, Math.min(h-1, iy));
        int rgb = image.getRGB(ix, iy);
        return rgb;
    }

    /**
     * Returns the hue for the given RGB color
     * @param rgb The RGB color
     * @return The hue
     */
    private static float getHue(int rgb)
    {
        int r = (rgb >> 16) & 0xFF;
        int g = (rgb >>  8) & 0xFF;
        int b = (rgb >>  0) & 0xFF;
        float hsb[] = new float[3];
        java.awt.Color.RGBtoHSB(r, g, b, hsb);
        float hue = hsb[0];
        return hue;
    }

    static class ImageToValueMapper extends Mapper
    {
        private final BufferedImage image;

        ImageToValueMapper(BufferedImage image)
        {
            this.image = image;
        }

        @Override
        public double f(double x, double y)
        {
            int rgb = getRGB(image, x, y);
            float hue = getHue(rgb);
            return hue;
        }
    }


    @Override
    public void init()
    {
        Mapper mapper = new ImageToValueMapper(image);

        // Define range and precision for the function to plot
        Range range = new Range(0, 1);
        int steps = 80;

        // Create the object to represent the function over the given range.
        final Shape surface = Builder.buildOrthonormal(
            new OrthonormalGrid(range, steps, range, steps), mapper);
        surface.setColorMapper(
            new ColorMapper(new ColorMapRainbow(), 
                surface.getBounds().getZmin(), 
                surface.getBounds().getZmax(), 
                new Color(1, 1, 1, 1.0f)));
        surface.setFaceDisplayed(true);
        surface.setWireframeDisplayed(false);

        // Create a chart
        chart = AWTChartComponentFactory.chart(
            Quality.Advanced, getCanvasType());
        chart.getScene().getGraph().add(surface);
    }
}