OpenCV-Java版学习(2.图像入门)

前言

上一篇博客我们讲了如何在IDEA中使用OpenCV来进行一些简单的图像操作,这节我们来学习图像的一些基本的入门级操作。

图像入门

一.在Java中使用OpenCV注意事项

1.解决awt报错问题

先给大家贴个错误,如下图:
OpenCV-Java版学习(2.图像入门)_第1张图片
我们在使用awt处理图像的时候报了这个异常,HeadlessException 异常是在环境中不支持键盘、显示器或鼠标的环境中调用与键盘、显示器或鼠标有关的代码时,被抛出的异常。
网上有几种解决方法,比较方便的一种解决方法如下:

System.setProperty("java.awt.headless", "false");

这段代码激活了Headless模式,Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标。
这段代码相当于告诉程序,现在你要工作在Headless模式下,就不要指望硬件帮忙了,你得自力更生,依靠系统的计算能力模拟出这些特性来。

2.加载动态库

这里我们在Java中调用一下dll就行了,如下:

 URL url = ClassLoader.getSystemResource("lib/opencv/opencv_java451.dll");//这里的dll根据你自己的实际情况写
 System.load(url.getPath());

二.读取图像和显示图像

在OpenCV中我们可以使用imread()函数来进行图像的读取。图像的工作目录或图像的完整路径应给出。
该函数的定义如下:

static Mat imread(String filename)
static Mat imread(String filename, int flags)

flags是一个标志,它表示以何种方式来读取图像,它有常用的3个值,如下:

  • IMREAD_COLOR = 1:加载彩色图像。任何图像的透明度都会被忽视。它是默认标志;
  • IMREAD_GRAYSCALE = 0:以灰度模式加载图像;
  • IMREAD_UNCHANGED = -1:加载图像,包括alpha通道。

当然我们也可以在源码中查看其他的值,如下:
OpenCV-Java版学习(2.图像入门)_第2张图片
在OpenCV中我们可以使用imshow()函数来在窗口中显示图像,窗口自动适应图像的尺寸,该函数使用如下:

public static void imshow(String winname, Mat img);

第一个参数是窗口名称,它是一个字符串。第二个参数是我们读取图片的对象。

图像读取和显示的代码如下:

import org.junit.jupiter.api.Test;
import org.opencv.core.Mat;
import org.springframework.boot.test.context.SpringBootTest;

import java.net.URL;

import static org.opencv.highgui.HighGui.*;
import static org.opencv.imgcodecs.Imgcodecs.imread;

@SpringBootTest
class DemoApplicationTests {
     

    @Test
    public void testOpencv1() throws Exception {
     
        // 解决awt报错问题
        System.setProperty("java.awt.headless", "false");
        // 加载动态库
        URL url = ClassLoader.getSystemResource("lib/opencv/opencv_java451.dll");
        System.load(url.getPath());
        // 读取图像,以彩色模式(1)显示,0是灰度模式,-1是加载图像,包括alpha通道
        Mat src = imread("D:\\OpenCV_Study\\demo1\\src\\main\\resources\\image\\test1.jpg",1);
        if (src.empty()) {
     
            throw new Exception("image is empty");
        }
        imshow("image",src);
        waitKey(0);
        destroyAllWindows();
    }
}

读取彩色图像:

灰度模式读取图像:

加载图像,包括alpha通道:

上面的那段代码中有两个函数大家这里还需要讲一下:

  • waitKey()函数:
    该函数是一个键盘绑定函数。其参数是以毫秒为单位的时间。该函数等待任何键盘事件指定的毫秒。如果您在这段时间内按下任何键,程序将继续运行。如果0被传递,它将无限期地等待一次敲击键。它也可以设置为检测特定的按键。
    该函数的定义如下:
public static void waitKey();
public static int waitKey(int delay);

从源码中我们可以看到waitKey()函数还有一个重载函数,其默认值为0,如下图:
OpenCV-Java版学习(2.图像入门)_第3张图片
所以我们写不写0都无所谓…吧

  • destroyAllWindows()函数
    从该函数的字面意思我们就可以知道,该函数会破坏我们创建的所有窗口

关于窗口
我们可以创建一个空窗口,然后再将图像加载到该窗口。在这种情况下,我们可以指定窗口是否可调整大小。这是通过函数namedWindow()来完成的。
该函数的定义:

public static void namedWindow(String winname);
public static void namedWindow(String winname, int flag);

flag默认情况下是WINDOW_AUTOSIZE,此时不能调整窗口的大小,但是,如果指定为WINDOW_NORMAL,则
可以调整窗口大小

代码如下:

import org.junit.jupiter.api.Test;
import org.opencv.core.Mat;
import org.springframework.boot.test.context.SpringBootTest;

import java.net.URL;

import static org.opencv.highgui.HighGui.*;
import static org.opencv.imgcodecs.Imgcodecs.imread;

@SpringBootTest
class DemoApplicationTests {
     

    @Test
    public void testOpencv2() throws Exception{
     
        System.setProperty("java.awt.headless","false");
        URL url = ClassLoader.getSystemResource("lib/opencv/opencv_java451.dll");
        System.load(url.getPath());
        Mat image = imread("D:\\OpenCV_Study\\demo1\\src\\main\\resources\\image\\test1.jpg",1);
        if (image.empty()){
     
            throw new Exception("image is empty");
        }
        //这里我们创建了两个窗口,一个叫imag1,一个叫imag2,他们分别是可以调整窗口大小和不可以调整窗口大小
        namedWindow("imag1",WINDOW_NORMAL);		//可以调整窗口大小
        namedWindow("imag2",WINDOW_AUTOSIZE);	//不可以调整窗口大小
        //将图像加载进窗口,分别显示这两个窗口
        imshow("imag1",image);
        imshow("imag2",image);
        waitKey();
        destroyAllWindows();
    }
}

三.保存图像

我们可以使用函数imwrite()来保存图像,该函数定义如下:

public static boolean imwrite(String filename, Mat img);

第一个参数是文件名(得包含文件路径),第二个参数是要保存的图像。
代码示例如下:

import org.junit.jupiter.api.Test;
import org.opencv.core.Mat;
import org.springframework.boot.test.context.SpringBootTest;

import java.net.URL;

import static org.opencv.highgui.HighGui.*;
import static org.opencv.imgcodecs.Imgcodecs.imread;
import static org.opencv.imgcodecs.Imgcodecs.imwrite;

@SpringBootTest
class DemoApplicationTests {
     

    @Test
    public void testOpencv3() throws Exception{
     
        System.setProperty("java.awt.headless","false");
        URL url = ClassLoader.getSystemResource("lib/opencv/opencv_java451.dll");
        System.load(url.getPath());
        Mat image = imread("D:\\OpenCV_Study\\demo1\\src\\main\\resources\\image\\test1.jpg",0);
        if (image.empty()){
     
            throw new Exception("image is empty");
        }
        imshow("image",image);
        //此处设置为检测特定的按键
        int flag = waitKey(0);
        if (flag==27){
     
            destroyAllWindows();
        }else if (flag==83){
     
            imwrite("D:\\OpenCV_Study\\demo1\\src\\main\\resources\\image\\test2.jpg",image);
            destroyAllWindows();
        }
    }
}

上面这段代码中我们将结束事件设置为检测特定的按键,即按了Esc键(值为23)就直接销毁窗口退出程序,按了"s"键(值为83)就保存灰度模式的图片。
结果:

可以看到,我们在键盘上按了"s"之后灰度模式的图像就被保存到相对应路径下了。

你可能感兴趣的:(OpenCV,opencv,java)