Java 图像处理教程(人脸检测,添加水印,图像颜色转换)

Java 图像处理教程(人脸检测,添加水印,图像颜色转换)

1:图片的读和写

BufferedImage 是处理图片的缓冲器,用于处理图片的长度,修改图片的大小,颜色转换以及对图片的其他修改。

public class Test {
    static BufferedImage image = null;
    public static void main(String[] args)
    {
        try {

            File input_file = new File("C:\\Users\\Administrator\\Desktop\\beautiful.jpg");
            image = new BufferedImage(600,600,BufferedImage.TYPE_INT_RGB);
            image = ImageIO.read(input_file);
            System.out.println("图片已读取");

            File out_file = new File("C:\\Users\\Administrator\\Desktop\\out_beautiful4.jpg");
            ImageIO.write(image,"jpg",out_file);
            System.out.println("图片已输出");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2:彩色图像转换成灰度图像

像素是图像的最小单位,由四个分量Alpha(透明度度量),红色,绿色,蓝色和简称(ARGB)组成。
所有组件的值都在0到255之间(包括0和255)。零表示该组件不存在,而255表示该组件已完全存在。
由于 2 8 = 256 2^{8} = 256 28=256并且像素分量的值在0到255之间,因此我们只需要8位即可存储这些值。
因此,存储ARGB值所需的总位数为8 * 4 = 32位或4个字节。
当顺序表示Alpha获取最左边的8位时,Blue获取最右边的8位。

因此位的位置:
蓝色分量为7-0,
绿色分量为15-8,
红色分量为23-16,
alpha分量为31-24,

在这里插入图片描述
在灰度图像中,图像的Alpha分量将与原始图像相同,但是RGB将被更改,即,所有三个RGB分量对于每个像素将具有相同的值。

算法:

  1. 获取像素的RGB值。
  2. 求出RGB的平均值,即Avg =(R + G + B)/ 3。
  3. 将像素的R,G和B值替换为在步骤2中计算的平均值(Avg)。
  4. 对图像的每个像素重复步骤1到步骤3。
public class Test {
    static BufferedImage image = null;
    static File input_file = null;
    public static void main(String[] args)
    {
        try {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\beautiful.jpg");
            image = ImageIO.read(input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取图片的长度和宽度
        int width = image.getWidth();
        int height = image.getHeight();

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // (x,y)表示图像的坐标
                int p = image.getRGB(x,y);

                int a = (p>>24)&0xff;
                int r = (p>>16)&0xff;
                int g = (p>>8)&0xff;
                int b = p&0xff;

                // 计算平均值
                int avg = (r+g+b)/3;

                // 替换 RGB 值
                p = (a<<24) | (avg<<16) | (avg<<8) | avg;

                image.setRGB(x, y, p);
            }
        }

        // 输出图片
        try
        {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\out.jpg");
            ImageIO.write(image, "jpg", input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述

3:彩色图像转换成负图像

在负片图像中,图像的Alpha分量将与原始图像相同,但是RGB将被更改,即所有三个RGB分量的值将均为255-原始分量值。

算法:

  1. 获取像素的RGB值
  2. 计算新的RGB值。
  3. 将像素的R,G和B值替换为在步骤2中计算出的值
  4. 对图像的每个像素重复步骤1到步骤3。
public class Test {
    static BufferedImage image = null;
    static File input_file = null;
    public static void main(String[] args)
    {
        try {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\beautiful.jpg");
            image = ImageIO.read(input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取图片的长度和宽度
        int width = image.getWidth();
        int height = image.getHeight();

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // (x,y)表示图像的坐标
                int p = image.getRGB(x,y);

                int a = (p>>24)&0xff;
                int r = (p>>16)&0xff;
                int g = (p>>8)&0xff;
                int b = p&0xff;

                // 从255减去RGB
                r = 255 - r;
                g = 255 - g;
                b = 255 - b;

                // 替换 RGB 值
                p = (a<<24) | (r<<16) | (g<<8) | b;

                image.setRGB(x, y, p);
            }
        }

        // 输出图片
        try
        {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\out.jpg");
            ImageIO.write(image, "jpg", input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述

4:彩色图像转换成红色,绿色,蓝色图像

获取每个坐标的像素值,然后保持所需的结果彩色像素值相同,并将其他两个像素值设置为零。

转换成红色:

  1. 获取像素的RGB值。
  2. 设置RGB值:R:不变 ,G:设为0, B:设为0
  3. 将像素的R,G和B值替换为在步骤2中计算出的值。
  4. 对图像的每个像素重复步骤1到步骤3。
public class Test {
    static BufferedImage image = null;
    static File input_file = null;
    public static void main(String[] args)
    {
        try {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\beautiful.jpg");
            image = ImageIO.read(input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取图片的长度和宽度
        int width = image.getWidth();
        int height = image.getHeight();

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // (x,y)表示图像的坐标
                int p = image.getRGB(x,y);

                int a = (p>>24)&0xff;
                int r = (p>>16)&0xff;
                int g = (p>>8)&0xff;
                int b = p&0xff;

                // G:设为 0 
                // B:设为 0
                g = 0;
                b = 0;

                // 替换 RGB 值
                p = (a<<24) | (r<<16) | (g<<8) | b;

                image.setRGB(x, y, p);
            }
        }

        // 输出图片
        try
        {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\out.jpg");
            ImageIO.write(image, "jpg", input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述
设为蓝色,绿色,原理相同。

比如设为蓝色

  • R:设为 0
  • G:设为 0
  • B:不变

5:彩色图像转换成棕褐色图像

在棕褐色图像中,图像的Alpha分量将与原始图像相同(因为Alpha分量表示透明度),但是RGB将更改。

棕褐色计算公式(微软推荐):

newRed = 0.393 * R + 0.769 * G + 0.189 * B
newGreen = 0.349 * R + 0.686 * G + 0.168 * B
newBlue = 0.272 * R + 0.534 * G + 0.131 * B

注意:如果这些输出值中的任何一个大于255, 只需将其设置为255。

public class Test {
    static BufferedImage image = null;
    static File input_file = null;
    public static void main(String[] args)
    {
        try {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\beautiful.jpg");
            image = ImageIO.read(input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取图片的长度和宽度
        int width = image.getWidth();
        int height = image.getHeight();

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // (x,y)表示图像的坐标
                int p = image.getRGB(x,y);

                int a = (p>>24)&0xff;
                int r = (p>>16)&0xff;
                int g = (p>>8)&0xff;
                int b = p&0xff;

                // 计算 红色,绿色,蓝色
                int newRed = (int)(0.393*r + 0.769*g + 0.189*b);
                int newGreen = (int)(0.349*r + 0.686*g + 0.168*b);
                int newBlue = (int)(0.272*r + 0.534*g + 0.131*b);

                //check condition
                if (newRed > 255)
                    r = 255;
                else
                    r = newRed;

                if (newGreen > 255)
                    g = 255;
                else
                    g = newGreen;

                if (newBlue > 255)
                    b = 255;
                else
                    b = newBlue;

                // 替换 RGB 值
                p = (a<<24) | (r<<16) | (g<<8) | b;

                image.setRGB(x, y, p);
            }
        }

        // 输出图片
        try
        {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\out.jpg");
            ImageIO.write(image, "jpg", input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述

6:旋转图像

将左侧的颜色值放到右侧,将右侧的颜色值放到左侧。

算法:

  1. 获取左侧像素的RGB值。
  2. 获取右侧像素的RGB值。
  3. 将左侧像素的RGB值赋值到右侧。
  4. 将右侧像素的RGB值赋值到左侧。
  5. 循环到图像长度的一半结束。
  6. 对图像的每个像素重复步骤1到步骤4。
public class Test {
    static BufferedImage image = null;
    static File input_file = null;
    public static void main(String[] args)
    {
        try {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\beautiful.jpg");
            image = ImageIO.read(input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取图片的长度和宽度
        int width = image.getWidth();
        int height = image.getHeight();

        for (int y = 0; y < height; y++)
        {
            for (int x = 0, rx = (width - 1); x < width/2; x++, rx--)
            {
                // (x,y)表示图像的坐标
                int p = image.getRGB(x,y);
                int p2 = image.getRGB(rx,y);

                image.setRGB(rx, y, p);
                image.setRGB(x, y, p2);
            }
        }

        // 输出图片
        try
        {
            input_file = new File("C:\\Users\\Administrator\\Desktop\\out.jpg");
            ImageIO.write(image, "jpg", input_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述

您可以在此基础上下旋转。

另外,您可以创建另一个BufferedImage对象并添加颜色值以实现镜像。

7:人脸检测

首先,我们需要为Java设置OpenCV。

OpenCV在线安装教程太多了,我们只介绍一个很容易在这里出现的问题,NO opencv_java300 in java.library.path [duplicate],这是因为缺少opencv_java430.dll,请将其从opencv / build / java / x64目录复制到jdk安装目录的 bin 目录中。

public class Test {
    // 加载Core.NATIVE_LIBRARY_NAME
    static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
    public static void main(String[] args)
    {
        //通过加载源级联xml文件来创建人脸检测器
        CascadeClassifier faceDetector = new CascadeClassifier();
        File directory = new File("");//设定为当前文件夹
        String path = directory.getAbsolutePath()+"\\src\\haarcascade_frontalface_alt.xml";
        faceDetector.load(path);

        Mat image = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\aobama.jpg");

        // 侦测人脸
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(image, faceDetections);

        // 创建一个显示检测到的面部的矩形框
        for (Rect rect : faceDetections.toArray())
        {
            Imgproc.rectangle(image, new Point(rect.x, rect.y),
                    new Point(rect.x + rect.width, rect.y + rect.height),
                    new Scalar(0, 255, 0));
        }

        // 输出图像
        Imgcodecs.imwrite("C:\\Users\\Administrator\\Desktop\\out2.jpg", image);
    }
}

在这里插入图片描述
在这里插入图片描述

8:为图像增加水印

这里使用三个包:

  1. java.awt.Graphics:将生成文本应用于图像
  2. java.awt.Color:文本的字体
  3. java.awt.Font:文本的颜色

使用的一些方法:

  1. getGraphics():在BufferedImage类中找到此方法,它从图像文件中返回2DGraphics对象。
  2. drawImage(Image img, int x, int y, ImageObserver observer):x,y位置指定图像左上角的位置。该观察器参数通知应用程序对异步加载的映像的更新。observer并不经常直接使用,并且对于BufferedImage类而言并不需要,因此通常为null。
  3. setFont(Font f):在awt包的Font类中找到此方法,构造函数将(FONT_TYPE,FONT_STYLE,FONT_SIZE)作为参数。
  4. setColor(Color c):该方法位于awt包的Color类中,构造函数将(R,G,B,A)作为参数。
  5. drawString(String str, int x, int y): Graphics类中的Fond将字符串文本和位置坐标分别作为x和y作为参数。
public class Test {
    static BufferedImage img = null;
    static File f = null;
    public static void main(String[] args)
    {

        try {
            // 读取图片
            f = new File("C:\\Users\\Administrator\\Desktop\\beautiful.jpg");
            img = ImageIO.read(f);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 创建相同宽度的BufferedImage对象,并从输入图片开始的高度
        BufferedImage temp = new BufferedImage(img.getWidth(),
                img.getHeight(), BufferedImage.TYPE_INT_RGB);

        //创建图形对象并添加原始图片
        Graphics graphics = temp.getGraphics();
        graphics.drawImage(img, 0, 0, null);

        // 设置水印文本的字体和颜色
        graphics.setFont(new Font("Arial", Font.PLAIN, 20));
        graphics.setColor(new Color(0, 122, 255, 40));

        // 设置水印文本内容
        String watermark = "hello world";

        // 设置水印位置
        graphics.drawString(watermark, 30, 30);

        // 释放该方法正在使用的所有系统资源
        graphics.dispose();

        try {
            // 输出图像
            ImageIO.write(temp, "png", new File("C:\\Users\\Administrator\\Desktop\\out.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
JavaCV是Java平台上的计算机视觉库,它提供了一系列处理图像和视频的工具和算法,包括图像处理、特征提取、目标检测、人脸识别等。下面是JavaCV图像处理的一些基本教程: 1. 安装JavaCV 首先需要安装JavaCV,可以在官网下载最新版本的JavaCV,并将其添加Java项目的classpath中。具体安装步骤可以参考官网的说明。 2. 加载和显示图像 JavaCV提供了一些方法来加载和显示图像。下面是一个简单的例子: ``` import org.bytedeco.opencv.opencv_core.Mat; import org.bytedeco.opencv.opencv_core.CvScalar; import org.bytedeco.opencv.global.opencv_imgcodecs; import org.bytedeco.javacv.Java2DFrameUtils; import org.bytedeco.javacv.JavaFXFrameConverter; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class LoadAndShowImage extends Application { @Override public void start(Stage primaryStage) throws Exception { // 加载图像 Mat image = opencv_imgcodecs.imread("test.jpg"); // 转换JavaFX Image JavaFXFrameConverter fxConverter = new JavaFXFrameConverter(); ImageView imageView = new ImageView(fxConverter.convert(Java2DFrameUtils.toBufferedImage(image))); // 显示图像 BorderPane root = new BorderPane(); root.setCenter(imageView); Scene scene = new Scene(root, 640, 480); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } ``` 这个例子加载了一张名为test.jpg的图像,并将其显示在JavaFX的窗口中。 3. 图像处理 JavaCV提供了一系列图像处理的方法,可以对图像进行滤波、边缘检测、二值化等操作。下面是一个简单的例子,将图像进行二值化处理: ``` import org.bytedeco.opencv.opencv_core.Mat; import org.bytedeco.opencv.global.opencv_imgcodecs; import org.bytedeco.opencv.global.opencv_imgproc; import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacv.Java2DFrameUtils; import org.bytedeco.javacv.JavaFXFrameConverter; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class ImageProcessing extends Application { @Override public void start(Stage primaryStage) throws Exception { // 加载图像 Mat image = opencv_imgcodecs.imread("test.jpg"); // 转为灰度图像 Mat gray = new Mat(); opencv_imgproc.cvtColor(image, gray, opencv_imgproc.COLOR_BGR2GRAY); // 二值化处理 Mat binary = new Mat(); opencv_imgproc.threshold(gray, binary, 0, 255, opencv_imgproc.THRESH_BINARY | opencv_imgproc.THRESH_OTSU); // 转换JavaFX Image JavaFXFrameConverter fxConverter = new JavaFXFrameConverter(); ImageView imageView = new ImageView(fxConverter.convert(Java2DFrameUtils.toBufferedImage(binary))); // 显示图像 BorderPane root = new BorderPane(); root.setCenter(imageView); Scene scene = new Scene(root, 640, 480); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } ``` 这个例子将图像转为灰度图像,并进行二值化处理。可以通过修改threshold方法中的参数来调整二值化的阈值。 4. 特征提取和目标检测 JavaCV还提供了一些特征提取和目标检测的方法,例如SIFT、SURF、HOG等。下面是一个简单的例子,使用SIFT算法提取图像的关键点和描述符: ``` import org.bytedeco.opencv.opencv_core.Mat; import org.bytedeco.opencv.opencv_features2d.KeyPointVector; import org.bytedeco.opencv.global.opencv_features2d; import org.bytedeco.opencv.global.opencv_imgcodecs; import org.bytedeco.javacpp.BytePointer; public class FeatureExtraction { public static void main(String[] args) { // 加载图像 Mat image = opencv_imgcodecs.imread("test.jpg"); // 使用SIFT算法提取关键点和描述符 opencv_features2d.SIFT sift = opencv_features2d.SIFT.create(); KeyPointVector keypoints = new KeyPointVector(); Mat descriptors = new Mat(); sift.detectAndCompute(image, new Mat(), keypoints, descriptors); // 输出关键点和描述符 System.out.println("keypoints:"); for (int i = 0; i < keypoints.size(); i++) { System.out.println(keypoints.get(i).pt().x() + "," + keypoints.get(i).pt().y()); } System.out.println("descriptors:"); BytePointer ptr = descriptors.createIndexer(); for (int i = 0; i < descriptors.rows(); i++) { for (int j = 0; j < descriptors.cols(); j++) { System.out.print(ptr.get(i, j) + " "); } System.out.println(); } } } ``` 这个例子使用SIFT算法提取了图像的关键点和描述符,并输出了结果。可以使用同样的方法提取其他特征,并进行目标检测等操作。 以上是JavaCV图像处理的一些基本教程,希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一拖再拖 一拖再拖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值