You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java中实现Matlab imrotate功能,旋转二维像素数组表示的图像

Java实现Matlab imrotate功能的问题修复与方案

核心问题原因

  • 你提供的代码返回全0像素的直接原因是:g2d.drawImage(img, 0, 0, this); 核心像素拷贝行被注释,新创建的BufferedImage未写入任何源图像数据。
  • 对Graphics2D的功能存在误解:Graphics2D的绘制操作本质是修改目标BufferedImage的光栅像素数据,和前端可视化渲染没有绑定关系,处理完成的BufferedImage可以直接提取像素数组使用,不需要实际输出到显示设备。

修复方案1:调整原有BufferedImage实现

这个方案和Matlab imrotate的默认行为对齐,支持插值设置,性能也经过优化:

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

public static BufferedImage rotateImage(BufferedImage img, double angle) {
    double rads = Math.toRadians(angle);
    double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads));
    int w = img.getWidth();
    int h = img.getHeight();
    // 计算旋转后图像的尺寸
    int newWidth = (int) Math.floor(w * cos + h * sin);
    int newHeight = (int) Math.floor(h * cos + w * sin);

    // 指纹图像为灰度图可改用TYPE_BYTE_GRAY,减少内存占用
    BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = rotated.createGraphics();
    // 设置插值模式,对应Matlab imrotate的插值参数:
    // VALUE_INTERPOLATION_NEAREST_NEIGHBOR 对应最近邻插值
    // VALUE_INTERPOLATION_BILINEAR 对应双线性插值
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    
    AffineTransform at = new AffineTransform();
    // 平移使旋转后的图像居中
    at.translate((newWidth - w) / 2.0, (newHeight - h) / 2.0);
    // 绕原图像中心旋转
    at.rotate(rads, w / 2.0, h / 2.0);
    
    g2d.setTransform(at);
    // 已加载完成的BufferedImage传入null作为ImageObserver即可
    g2d.drawImage(img, 0, 0, null);
    g2d.dispose();

    return rotated;
}

处理完成后你可以通过以下代码将BufferedImage转为二维int数组:

public static int[][] bufferedImageToArray(BufferedImage img) {
    int w = img.getWidth();
    int h = img.getHeight();
    int[][] arr = new int[h][w];
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            arr[y][x] = img.getRGB(x, y);
            // 灰度图可直接提取灰度值:arr[y][x] = (img.getRGB(x,y) >> 16) & 0xff;
        }
    }
    return arr;
}

修复方案2:直接操作二维数组实现旋转

如果你不想依赖BufferedImage接口,可以直接通过坐标反向映射实现旋转,避免空像素孔洞:

/**
 * 二维数组图像旋转
 * @param src 原图像数组,维度为[height][width]
 * @param angle 旋转角度(角度制)
 * @param fillValue 超出原图像范围的填充值,对应Matlab imrotate的填充参数
 * @return 旋转后的图像数组
 */
public static int[][] rotateArray(int[][] src, double angle, int fillValue) {
    int h = src.length;
    int w = src[0].length;
    double rads = Math.toRadians(angle);
    double sin = Math.sin(rads);
    double cos = Math.cos(rads);
    // 计算新尺寸
    int newW = (int) Math.floor(Math.abs(w * cos) + Math.abs(h * sin));
    int newH = (int) Math.floor(Math.abs(h * cos) + Math.abs(w * sin));
    int[][] dst = new int[newH][newW];
    // 原图像中心坐标
    double cx = w / 2.0;
    double cy = h / 2.0;
    // 新图像中心坐标
    double ncx = newW / 2.0;
    double ncy = newH / 2.0;

    for (int y = 0; y < newH; y++) {
        for (int x = 0; x < newW; x++) {
            // 反向映射:计算新坐标对应原图像的坐标
            double ox = (x - ncx) * cos + (y - ncy) * sin + cx;
            double oy = -(x - ncx) * sin + (y - ncy) * cos + cy;
            // 坐标在原图像范围内则赋值,否则用填充值
            if (ox >= 0 && ox < w && oy >=0 && oy < h) {
                // 最近邻插值直接取整,需要双线性可自行补充插值逻辑
                dst[y][x] = src[(int) Math.round(oy)][(int) Math.round(ox)];
            } else {
                dst[y][x] = fillValue;
            }
        }
    }
    return dst;
}

这个方案完全不需要依赖Java的图形接口,直接操作像素数组,更贴合你直接处理子图数组的需求。

内容的提问来源于stack exchange,提问作者quangtrank9

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 15:09:05