Skip to content
鼓励作者:欢迎打赏犒劳

openCV初体验

windows环境安装openCV

官网地址:https://opencv.org/

官网下载速度很慢,给一个备用下载地址:https://download.csdn.net/download/lzh657083979/90854889

下载地址:https://opencv.org/releases/ ,找到windows安装包,下载安装即可。

注意:安装路径,不需要专门建opencv文件夹,它会自己创建一个。 安装路径

java整合opencv

这里我们使用opencv安装之后自带的jar包,没有用maven依赖,我找了好几个依赖,都不行。

下面是安装之后的目录,特别注意的是我们需要将dll文件和jar包给复制到java项目中。并且右键设置成库安装路径

安装路径

别忘了将opencv给设置成环境变量 D:\devtool\opencv\build\x64\vc16\bin安装路径

jdk 建议 11 或者 21

我的opencv的jar包是 opencv-4110 , 下载的版本是 opencv-4.11.0-windows.exe

java
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;

public class OpenCVTest {
    public static void main( String[] args )
    {
        System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
        Mat mat = Mat.eye( 3, 3, CvType.CV_8UC1 );
        System.out.println( "mat = " + mat.dump() );
    }
}

创建一个图片

其实图片就是一个矩阵,类似于一个数组,大小为,宽*高*通道数

java
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;

/**
 * 公众号:干货食堂
 */
public class Test {

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        //创建像素大小为3x3的黑色正方形图像
        Mat img = new Mat(3, 3, CvType.CV_8UC3);//3通道图像
        img.setTo(new org.opencv.core.Scalar(0));//填充为黑色

        System.out.println(img.dump());
    }
}

结果

js
-- 三通道矩阵
[  0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0]


-- 单通道矩阵
[  0,   0,   0;
0,   0,   0;
0,   0,   0]

opencv读取保存图片

java
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

public class OpenCVTest {
    public static void main( String[] args )
    {
        // 方式一加载OpenCV库
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        // 方式二加载OpenCV库
        // OpenCVNativeLoader openCVNativeLoader = new OpenCVNativeLoader();
        // openCVNativeLoader.init();

        // 图片文件路径
        String imagePath = "C:\\Users\\Think\\Desktop\\3.jpg";
        // 使用OpenCV加载图片,可以加第二个参数,是读取的类型,比如读取灰色图像
        Mat image = Imgcodecs.imread(imagePath);
        
        
        //将读取的图像信息写入本地文件
        Imgcodecs.imwrite("C:\\Users\\Think\\Desktop\\3-1.jpg",image);

        // 检查是否成功加载图片
        if (image.empty()) {
            System.err.println("无法加载图片: " + imagePath);
            System.exit(1);
        }

        // 获取图片的尺寸
        int width = image.width();
        int height = image.height();

        // 打印尺寸信息
        System.out.println("图片宽度: " + width);
        System.out.println("图片高度: " + height);

        // 显示图片
        HighGui.imshow("Loaded Image", image);

        // 等待用户按下任意键后关闭窗口
        HighGui.waitKey(0);
        // 关闭窗口
        HighGui.destroyAllWindows();
    }
}

读取图像矩阵

注意:读取图片矩阵的时候有坑,因为java的byte类型是有符号的 范围是 -128~127,但是RGB的范围是0-255,所以如果值是255的话,取出的值就是 -1,所以我们要将byte转换成无符号 int 类型,

  • 彩色图像:使用 Imgcodecs.IMREAD_COLOR(默认值),强制加载为 3 通道 BGR 图像。
  • 灰度图像:使用 Imgcodecs.IMREAD_GRAYSCALE,强制加载为 1 通道灰度图像。
  • CvType.CV_8UC3 是 Mat 的数据类型标志,而不是图像读取标志
java
String imagePath = "C:\\Users\\Think\\Desktop\\11.jpg";
Mat image = Imgcodecs.imread(imagePath);
byte[] pixel = new byte[3];
image.get(0, 0, pixel);
System.out.println(Arrays.toString(pixel));
System.out.println("BGR 像素值:");
for (byte b : pixel) {
    int unsignedByte = b & 0xFF; // 转换为无符号 int
    System.out.print(unsignedByte + " ");
}

通道拆分

注意: Core.split函数拆分通道的效率不如数组索引,所以在处理较大图像时应优先考虑使用数组索引来拆分通道。

java
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

import java.util.ArrayList;
import java.util.List;

/**
 * 公众号:干货食堂
 */
public class Test {

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        //读取图像
        Mat img = Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\fish.png");
        //显示原图像
        HighGui.imshow("fish", img);
        HighGui.waitKey(0);
        //拆分通道
        List<Mat> channels = new ArrayList<>();
        //将图像通道拆分到List中
        Core.split(img, channels);
        //获取B、G、R通道
        Mat b = channels.get(0);//B通道
        Mat g = channels.get(1);//G通道
        Mat r= channels.get(2);//R通道
        //显示各个通道的图像
        HighGui.imshow("lena_B", b);
        HighGui.waitKey(0);
        HighGui.imshow("lena_G",g);
        HighGui.waitKey(0);
        HighGui.imshow("lena_R",r);

        HighGui.waitKey(0);
        System.exit(0);
    }
}

图像转灰度

java
import org.junit.Test;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class CvTest {
    @Test
    public void test2()  throws Exception{
        // 加载OpenCV库
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        String path = "C:\\Users\\Think\\Desktop\\1.jpg";
        Mat image = Imgcodecs.imread(path);
        if (image.empty()) {
            throw new Exception("image is empty");
        }
        //展示原图
        HighGui.imshow("Original Image", image);
        // 创建输出单通道图像
        Mat grayImage = new Mat(image.rows(), image.cols(), CvType.CV_8SC1);
        // 进行图像色彩空间转换
        Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_RGB2GRAY);
        HighGui.imshow("Processed Image", grayImage);
        HighGui.waitKey(0);
    }
}

高斯模糊

java
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class OpenCVTest {
    public static void main( String[] args )
    {
        // 方式一加载OpenCV库
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        // 图片文件路径
        String imagePath = "C:\\Users\\Think\\Desktop\\3.jpg";
        // 使用OpenCV加载图片,可以加第二个参数,是读取的类型,比如读取灰色图像
        Mat image = Imgcodecs.imread(imagePath);

        // 使用高斯模糊进行图像平滑
        Mat smoothedImage = new Mat();
        Imgproc.GaussianBlur(image, smoothedImage, new Size(5, 5), 0);

        // 显示平滑后的图像
        HighGui.imshow("Smoothed Image", smoothedImage);



        HighGui.waitKey(0);
        HighGui.destroyAllWindows();
    }
}

轮廓检测

java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;
import java.util.List;

public class OpenCVTest {
    public static void main( String[] args )
    {
        // 方式一加载OpenCV库
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        // 图片文件路径
        String imagePath = "C:\\Users\\Think\\Desktop\\3.jpg";
        // 使用OpenCV加载图片,可以加第二个参数,是读取的类型,比如读取灰色图像
        Mat image = Imgcodecs.imread(imagePath);

        // 转换为灰度图像
        Mat grayImage = new Mat();
        Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);

        // 使用Canny算法进行边缘检测
        Mat edges = new Mat();
        Imgproc.Canny(grayImage, edges, 50, 150);

        // 查找轮廓
        List<MatOfPoint> contours = new ArrayList<>();
        Mat hierarchy = new Mat();
        Imgproc.findContours(edges, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

        // 绘制轮廓
        Mat contourImage = Mat.zeros(image.size(), CvType.CV_8UC3);
        Imgproc.drawContours(contourImage, contours, -1, new Scalar(0, 255, 0));

        // 显示轮廓图像
        HighGui.imshow("Contours", contourImage);



        HighGui.waitKey(0);
        HighGui.destroyAllWindows();
    }
}

抠图

其实类似于ps的遮罩。主要是用hsv图像来实现的。

java
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;


/**
 * HSV是一种颜色空间,它使用三个分量来描述颜色
 * H(Hue):色调 表示颜色的类型(如红色、绿色、蓝色等)。取值范围通常是0°到360°(在OpenCV中,为了用一个字节(0-255)表示,通常会被缩放到0-180)
 * S(Saturation):饱和度,表示颜色的纯度或鲜艳程度(0%表示灰色,100%表示完全饱和)。在OpenCV中,通常用0-255表示。
 * V(Value):亮度,表示颜色的明亮程度(0%为黑色,100%为白色)。在OpenCV中,通常用0-255表示
 *
 *
 */

public class QRCodeDetectorDemo2 {

    public static void main(String[] args) throws InterruptedException {
        // 加载动态库
        System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
        //读取图像文件并在屏幕上显示
        Mat src= Imgcodecs.imread("C:\\Users\\Think\\Desktop\\TestCV\\blind.png");
        // 转换为 HSV
        Mat hsv = new Mat();
        Imgproc.cvtColor(src, hsv, Imgproc.COLOR_BGR2HSV);

        // 定义绿色范围(Hue:45~80, 饱和度和明度适当放宽)
        Scalar lowerGreen = new Scalar(45, 50, 50);
        Scalar upperGreen = new Scalar(80, 255, 255);

        // 生成掩膜 这时候mask会保存符合条件的像素为白色,其他为黑色
        Mat mask = new Mat();
        Core.inRange(hsv, lowerGreen, upperGreen, mask);
        HighGui.imshow("遮罩图", mask);
        HighGui.waitKey(0);
        // 创建黑白结果图:绿色区域为黑,其他为白
        Mat dst = new Mat(src.size(), CvType.CV_8UC3, new Scalar(255, 255, 255)); // 初始化为全白
        //src 赋值到dst中,但是多了第二个参数,那么就是只赋值遮罩的内容,参考ps,很好理解
        src.copyTo(dst, mask); // 将绿色区域(mask=255)从原图复制到dst,其他区域保持白色

        HighGui.imshow("Result", dst);
        HighGui.waitKey(0);

        // 关闭窗口
        HighGui.destroyAllWindows();
        System.exit(0);
    }
}

人脸检测

注意:人脸检测模型是在opencv自带的模型,位置在 opencv\build\etc\haarcascades\haarcascade_frontalface_default.xml

java
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

public class OpenCVTest {
    public static void main( String[] args )
    {
        // 方式一加载OpenCV库
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        // 加载人脸检测模型
        String xmlFile = "D:\\devtool\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml";
        CascadeClassifier faceDetector = new CascadeClassifier(xmlFile);

        // 图片文件路径
        String imagePath = "C:\\Users\\Think\\Desktop\\11.jpg";
        Mat image = Imgcodecs.imread(imagePath);
        if (image.empty()) {
            System.out.println("图像读取失败!");
            return;
        }

        // 检测人脸
        Mat grayImage = new Mat();
        Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(grayImage, 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));
        }

        // 显示检测结果
        HighGui.imshow("Face Detection", image);



        HighGui.waitKey(0);
        HighGui.destroyAllWindows();
    }
}

如有转载或 CV 的请标注本站原文地址