
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();
}
}