图像处理技术笔记:基于像素数组的操作

本笔记将详细解释提供的Java代码,这些代码实现了多种图像处理功能。代码的核心是操作一个二维像素数组 pixelArr,其中每个元素是一个整数,代表RGB颜色值(如 0xRRGGBB 格式)。通过 BufferedImageGraphics 对象,代码将像素数据渲染成图像。我会逐一解释每个方法,贴出关键代码行,并详细说明其工作原理,确保小白也能理解。

1. drawPixel 方法:绘制像素图像

这个方法将像素数组直接绘制成图像,每个像素对应一个点。

public void drawPixel(int[][] pixelArr) {
    BufferedImage bufferedImage = new BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
    Graphics buffG = bufferedImage.getGraphics();
    for (int i = 0; i < pixelArr.length; i++) {
        for (int j = 0; j < pixelArr[0].length; j++) {
            int rgb = pixelArr[i][j];
            int red = rgb >> 16 & 0xFF;   // 提取红色分量
            int green = rgb >> 8 & 0xFF;  // 提取绿色分量
            int blue = rgb & 0xFF;        // 提取蓝色分量
            Color color = new Color(red, green, blue); // 创建颜色对象
            buffG.setColor(color);        // 设置绘图颜色
            buffG.drawLine(j, i, j, i);   // 绘制单个像素点(起点和终点相同)
        }
    }
    g.drawImage(bufferedImage, 0, 0, pixelsize + bufferedImage.getWidth(), pixelsize + bufferedImage.getHeight(), null);
}

详细解释:

  • 创建 BufferedImage 对象BufferedImage bufferedImage = new BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
    这里创建了一个图像对象,宽度是 pixelArr[0].length(列数),高度是 pixelArr.length(行数),类型为 TYPE_INT_RGB,表示使用RGB颜色模型。

  • 获取绘图对象Graphics buffG = bufferedImage.getGraphics();
    通过 getGraphics() 方法获取一个 Graphics 对象,用于在图像上绘图。

  • 双层循环遍历像素for (int i = 0; i < pixelArr.length; i++) { for (int j = 0; j < pixelArr[0].length; j++) { ... } }
    外层循环遍历行(i 坐标),内层循环遍历列(j 坐标),逐个处理每个像素。

  • 提取RGB分量

    • int red = rgb >> 16 & 0xFF;:右移16位并掩码 0xFF 提取红色分量(值范围0-255)。
    • int green = rgb >> 8 & 0xFF;:右移8位提取绿色分量。
    • int blue = rgb & 0xFF;:直接掩码提取蓝色分量。
      这些操作将整数RGB值分解为三个颜色通道。
  • 设置颜色并绘制点

    • Color color = new Color(red, green, blue);:用提取的RGB值创建颜色对象。
    • buffG.setColor(color);:设置绘图颜色。
    • buffG.drawLine(j, i, j, i);:绘制一条从 (j,i)(j,i) 的线段,实际上只绘制一个点(因为起点和终点相同)。
  • 绘制最终图像g.drawImage(...);
    假设 g 是上下文中的 Graphics 对象,用于在屏幕上绘制图像。参数包括图像位置和尺寸,其中 pixelsize 可能是一个偏移量(如边框大小),null 表示无额外观察者。

这个方法将像素数组渲染成原始图像,适合显示或进一步处理。

2. Mosaic 方法:创建马赛克效果

这个方法通过采样像素块来创建马赛克效果,每10x10像素块使用一个颜色。

public void Mosaic(int[][] pixelArr) {
    BufferedImage bufferedImage = new BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
    Graphics buffG = bufferedImage.getGraphics();
    for (int i = 0; i < pixelArr.length; i += 10) {
        for (int j = 0; j < pixelArr[0].length; j += 10) {
            int rgb = pixelArr[i][j];
            int red = rgb >> 16 & 0xFF;   // 提取红色分量
            int green = rgb >> 8 & 0xFF;  // 提取绿色分量
            int blue = rgb & 0xFF;        // 提取蓝色分量
            Color color = new Color(red, green, blue); // 创建颜色对象
            buffG.setColor(color);        // 设置绘图颜色
            buffG.fillRect(j, i, 10, 10); // 填充10x10矩形区域
        }
    }
    g.drawImage(bufferedImage, 0, 0, pixelsize + bufferedImage.getWidth(), pixelsize + bufferedImage.getHeight(), null);
}

详细解释:

  • 创建图像和绘图对象:与 drawPixel 类似,创建一个 BufferedImage 并获取 Graphics

  • 跳跃遍历像素for (int i = 0; i < pixelArr.length; i += 10) { for (int j = 0; j < pixelArr[0].length; j += 10) { ... } }
    循环以步长10遍历行和列,而不是逐像素处理。这意味着只采样每个10x10块的左上角像素。

  • 提取颜色和填充矩形

    • 采样当前块左上角像素的RGB值(pixelArr[i][j]),提取颜色分量。
    • buffG.fillRect(j, i, 10, 10);:用采样颜色填充一个10x10像素的矩形区域。
      这实现了马赛克效果:每个块使用单一颜色,减少细节。
  • 绘制图像:同样使用 g.drawImage 输出结果。

马赛克效果通过减少图像分辨率来模糊细节,常用于隐私保护或艺术处理。

3. rotate 方法:旋转像素数组

这个方法将像素数组顺时针旋转90度,返回一个新的数组。

public int[][] rotate(int[][] pixelArr) {
    int[][] nArr = new int[pixelArr[0].length][pixelArr.length]; // 新数组,行列互换
    for (int i = 0; i < pixelArr.length; i++) {
        for (int j = 0; j < pixelArr[0].length; j++) {
            nArr[j][pixelArr.length - i - 1] = pixelArr[i][j]; // 索引映射实现旋转
        }
    }
    return nArr;
}

详细解释:

  • 创建新数组int[][] nArr = new int[pixelArr[0].length][pixelArr.length];
    新数组的宽度是原数组的高度(pixelArr.length),高度是原数组的宽度(pixelArr[0].length),实现行列互换。

  • 双层循环遍历原数组for (int i = 0; i < pixelArr.length; i++) { for (int j = 0; j < pixelArr[0].length; j++) { ... } }
    遍历原数组的每个像素。

  • 索引映射实现旋转nArr[j][pixelArr.length - i - 1] = pixelArr[i][j];

    • 原数组的像素 (i,j) 映射到新数组的 (j, pixelArr.length - i - 1)
    • 例如,原数组左上角 (0,0) 会映射到新数组右上角 (0, pixelArr.length - 1)
    • pixelArr.length - i - 1 确保行索引从下到上翻转,实现90度顺时针旋转。
  • 返回新数组return nArr;
    返回旋转后的像素数组,可以直接用于其他方法(如 drawPixel)。

这个方法不直接绘制图像,而是处理像素数据,适合在显示前调整图像方向。

4. Grey 方法:转换为灰度图像

这个方法将彩色图像转换为灰度图像,通过计算每个像素的灰度值。

public void Grey(int[][] pixelArr) {
    BufferedImage bufferedImage = new BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
    Graphics buffG = bufferedImage.getGraphics();
    for (int i = 0; i < pixelArr.length; i += 1) {
        for (int j = 0; j < pixelArr[0].length; j += 1) {
            int rgb = pixelArr[i][j];
            int red = rgb >> 16 & 0xFF;   // 提取红色分量
            int green = rgb >> 8 & 0xFF;  // 提取绿色分量
            int blue = rgb & 0xFF;        // 提取蓝色分量
            int grey = (red + green + blue) / 3; // 计算灰度值
            Color color = new Color(grey, grey, grey); // 灰度颜色(RGB相同)
            buffG.setColor(color);        // 设置绘图颜色
            buffG.fillRect(j, i, 1, 1);   // 填充单个像素
        }
    }
    g.drawImage(bufferedImage, 0, 0, pixelsize + bufferedImage.getWidth(), pixelsize + bufferedImage.getHeight(), null);
}

详细解释:

  • 创建图像和绘图对象:与之前方法相同。

  • 逐像素遍历for (int i = 0; i < pixelArr.length; i += 1) { for (int j = 0; j < pixelArr[0].length; j += 1) { ... } }
    步长为1,处理每个像素。

  • 计算灰度值int grey = (red + green + blue) / 3;
    将RGB三个分量求平均值,得到灰度值(0-255),代表亮度。这是一种简单的灰度化方法。

  • 设置灰度颜色Color color = new Color(grey, grey, grey);
    用相同的灰度值设置RGB,创建灰色调。

  • 填充像素buffG.fillRect(j, i, 1, 1);
    用灰度颜色填充一个1x1像素的矩形,相当于绘制一个点。

  • 绘制图像:输出灰度图像。

灰度化常用于简化图像处理或创建黑白效果。

5. invert 方法:反色图像

这个方法将图像颜色反转,创建负片效果。

public void invert(int[][] pixelArr) {
    BufferedImage bufferedImage = new BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
    Graphics buffG = bufferedImage.getGraphics();
    for (int i = 0; i < pixelArr.length; i += 1) {
        for (int j = 0; j < pixelArr[0].length; j += 1) {
            int rgb = pixelArr[i][j];
            int red = rgb >> 16 & 0xFF;   // 提取红色分量
            int green = rgb >> 8 & 0xFF;  // 提取绿色分量
            int blue = rgb & 0xFF;        // 提取蓝色分量
            Color color = new Color(255 - red, 255 - green, 255 - blue); // 反色计算
            buffG.setColor(color);        // 设置绘图颜色
            buffG.fillRect(j, i, 1, 1);   // 填充单个像素
        }
    }
    g.drawImage(bufferedImage, 0, 0, pixelsize + bufferedImage.getWidth(), pixelsize + bufferedImage.getHeight(), null);
}

详细解释:

  • 创建图像和绘图对象:标准步骤。

  • 逐像素遍历:处理每个像素。

  • 反色计算Color color = new Color(255 - red, 255 - green, 255 - blue);
    对每个RGB分量取反:用255减去原值。例如,红色255变为0(黑色),红色0变为255(红色)。这实现颜色反转。

  • 填充像素buffG.fillRect(j, i, 1, 1); 绘制反色点。

  • 绘制图像:输出反色图像。

反色效果常用于艺术处理或增强对比度。

总结

这些代码展示了基本的图像处理技术,使用Java的 BufferedImageGraphics 类操作像素数组。关键点包括:

  • 像素数组结构:二维数组 int[][] pixelArr,行索引 i 对应Y坐标,列索引 j 对应X坐标。
  • RGB处理:通过位操作提取和设置颜色分量。
  • 绘图方法:使用 drawLinefillRect 绘制点或块。
  • 通用输出g.drawImage 负责最终显示,假设 gpixelsize 在上下文中定义。

通过这些方法,小白可以学习如何实现图像绘制、马赛克、旋转、灰度化和反色等常见效果。代码结构清晰,易于扩展,但需注意性能优化(如循环效率)和边界处理。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐