【Java版本OpenCV】无敌OpenCV越学越爽Java版代码持续更新(环境搭建|核心代码)
特别说明
- 本文为B站李超老师的无敌Opencv越学越爽Java版代码(个人学习笔记),原视频为python语言讲解的,纯理论知识可直接看视频,实战代码为对应的Java版本,已经跟完B站所有章节,代码后续找时间补到章节名称下
- 个人感觉有些章节可以忽略的在章节下面做了备注,比如各种环境的安装,java可以直接用免安装的方式运行,所以这几节可以不看,节省点时间
- 个人感觉最用有的时区域找图,截图桌面图片,再桌面图片里寻找目标图片,拿到目标点的中心坐标,然后就可以利用Robot来实现各种鼠标键盘操作了,另外还有人脸识别,在桌面区域里面找人脸,就是不知道能不能识别出穿越火线里面的人脸,只要能识别到是不是可以用Robot控制鼠标移动到脑袋中间位置,在然后实现爆头▄︻┻┳═一…… ☆(>○
public static void main(String[] args) {
// 加载Opencv库 不一定要在项目里面,需要绝对路径
System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath());
// 读取图片
Mat img = Imgcodecs.imread("src/main/resources/img/lenna1.png");
// 在hello窗口中显示图片
HighGui.imshow("hello", img);
// 等待按键 不设置设计会一直等待
HighGui.waitKey();
// 销毁所有窗口
HighGui.destroyAllWindows();
// 退出系统
System.exit(0);
}
}
public static void main(String[] args) {
// 加载Opencv库 不一定要在项目里面,需要绝对路径
System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath());
// 读取图片
Mat img = Imgcodecs.imread("src/main/resources/img/lenna1.png");
// 保存图片 图片格式可以和原图片一致,也可以不一致
String fileName = "src/main/resources/tmp/lenna1.jpg";
Imgcodecs.imwrite(fileName, img);
}
}
public static void main(String[] args) {
// 加载动态库
System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath());
// 打开默认摄像头(索引为0)
VideoCapture capture = new VideoCapture(0);
// 检查摄像头是否成功打开
if (!capture.isOpened()) {
System.out.println("无法打开摄像头。");
return;
}
// 从摄像头读取并显示每一帧
Mat frame = new Mat();
while (capture.read(frame)) {
// 显示图片 HighGui用户界面相关
HighGui.imshow("Camera", frame);
// 等待3毫秒 也就是每3毫秒从摄像头读取一帧
int key = HighGui.waitKey(3);
// 如果输入q 则释放资源
if (key == 'q' || key == 'Q') {
// 销毁所有窗口
HighGui.destroyAllWindows();
// 释放 VideoCapture 对象
capture.release();
System.exit(0);
break;
}
}
// 销毁所有窗口
HighGui.destroyAllWindows();
// 释放 VideoCapture 对象
capture.release();
System.exit(0);
}
}
public static void main(String[] args) {
// 加载动态库
System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath());
// 读取本地视频
VideoCapture capture = new VideoCapture("src/main/resources/video/video.mp4");
// 获取视频的宽度、高度和帧数
double width = capture.get(Videoio.CAP_PROP_FRAME_WIDTH);
double height = capture.get(Videoio.CAP_PROP_FRAME_HEIGHT);
double frameCount = capture.get(Videoio.CAP_PROP_FRAME_COUNT);
// 获取视频的帧数和总时长
double totalSeconds = frameCount / capture.get(Videoio.CAP_PROP_FPS);
// 计算平均帧率
double fps = frameCount / totalSeconds;
// 输出视频信息
System.out.println("视频宽度: " + width);
System.out.println("视频高度: " + height);
System.out.println("视频帧数: " + frameCount);
System.out.println("总时长: " + totalSeconds);
System.out.println("平均帧率: " + fps);
// 定义输出视频文件路径
String outputFilePath = "src/main/resources/tmp/output_video.mp4";
// 定义视频属性 width 和 height 不对写不进去
Size frameSize = new Size(width, height);
// 创建 VideoWriter 对象
VideoWriter videoWriter = new VideoWriter(outputFilePath, VideoWriter.fourcc('H', '2', '6', '4'), fps, frameSize, true);
// 检查视频是否成功打开
if (!capture.isOpened()) {
System.out.println("无法打开视频");
return;
}
// 检查 VideoWriter 对象是否成功初始化
if (!videoWriter.isOpened()) {
System.out.println("错误:无法打开视频文件以进行写入。");
return;
}
// 从视频读取并显示每一帧
Mat frame = new Mat();
while (capture.read(frame)) {
if (!frame.empty()) {
videoWriter.write(frame);
}
// 显示图片 HighGui用户界面相关
HighGui.imshow("Video", frame);
// 输入一次就中断了
int key = HighGui.waitKey(30);
System.out.println("key = " + key+"\t" + (char)key);
if (key == 'q' || key == 'Q') {
HighGui.destroyAllWindows();
capture.release();
videoWriter.release();
System.exit(0);
break;
}
}
HighGui.destroyAllWindows();
capture.release();
videoWriter.release();
System.exit(0);
}
}
// 获取默认工具包
Toolkit toolkit = Toolkit.getDefaultToolkit();
// 获取屏幕的尺寸
Dimension screenSize = toolkit.getScreenSize();
// 输出屏幕宽度和高度
int i = 0;
int x = 0;
int y = 0;
int xSpacing = 10;
int ySpacing = 40;
for (Map.Entry
Mat mat = entry.getValue();
String winName = entry.getKey();
System.out.println("winName = " + winName);
HighGui.imshow(winName, mat);
if (i 0) {
x += (mat.cols() + xSpacing);
if (x + mat.cols() > screenSize.width) {
x = 0;
y += (mat.rows() + ySpacing);
}
}
HighGui.moveWindow(winName, x, y);
i++;
}
HighGui.waitKey();
}
public class P490MatCopyStudy { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 读取图片 Mat image = Imgcodecs.imread("src/main/resources/img/lenna1.png"); // 是深拷贝 Mat clone = image.clone(); // 深拷贝 Mat copyTo = new Mat(); image.copyTo(copyTo); // 在image上上绘制文本 // 文本的位置 Point textPosition = new Point(50, 50); String text = "Hello, OpenCV!"; // 白色,字体大小为 1.0,线宽为 2 Imgproc.putText(image, text, textPosition, Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(255, 255, 255), 2); LinkedHashMap images = new LinkedHashMap(); images.put("原图", image); images.put("clone", clone); images.put("copyTo", copyTo); OpenCVUtil.show(images); HighGui.destroyAllWindows(); } }说明:通过以上代码可以看出,在Java中clone和copyTo均为深拷贝
4-11 图像的多种属性
4-12 通道的分割与合并
public class P412MatSplitAndMerge { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 读取原图 Mat image = Imgcodecs.imread("src/main/resources/img/lenna1.png"); // 显示图片 HighGui.imshow("原图", image); // 分离通道 List channels = new ArrayList(); Core.split(image, channels); for (int i = 0; i绘制基本图形
5-1 OpenCV绘制直线
5-2 OpenCV椭圆的绘制
5-3 OpenCV椭圆的绘制
5-4 OpenCV绘制多边形
5-5 OpenCV绘制文本5-6 OpenCV大作业-实现鼠标绘制基本图形
5-7 OpenCV基本图形绘制小结
代码实战
public class P500BasicShapeDrawingExample { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 创建一个黑色背景的图像 Mat image = new Mat(400, 600, CvType.CV_8UC3, new Scalar(0, 0, 0)); // 400x600 大小,3 通道的黑色图像 // 在图像上绘制基本图形 Point center = new Point(300, 200); // 圆心坐标 Scalar color = new Scalar(0, 255, 0); // 颜色 (BGR 格式) // 绘制圆 Imgproc.circle(image, center, 100, color, 2); // 中心为 (300, 200),半径为 100,边界宽度为 2,绿色 // 绘制矩形 Point topLeft = new Point(100, 100); // 左上角坐标 Point bottomRight = new Point(500, 300); // 右下角坐标 Imgproc.rectangle(image, topLeft, bottomRight, new Scalar(0, 0, 255), 3); // 左上角 (100, 100),右下角 (500, 300),红色,边界宽度为 3 // 绘制直线 Point start = new Point(50, 50); // 起始点坐标 Point end = new Point(550, 350); // 结束点坐标 Imgproc.line(image, start, end, new Scalar(255, 0, 0), 1); // 蓝色,线宽为 1 // 在图像上绘制文本 Point textPosition = new Point(50, 50); // 文本的位置 String text = "Hello, OpenCV!"; // 要绘制的文本 Imgproc.putText(image, text, textPosition, Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(255, 255, 255), 2); // 白色,字体大小为 1.0,线宽为 2 HighGui.imshow("基本图形的绘制", image); HighGui.waitKey(0); HighGui.destroyAllWindows(); System.exit(0); } }效果
6-1 图像的加法运算
6-2 图像的减法运算
public class P620ImageArithmeticExample { public static void main(String[] args) { // // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 加载两个图像 String imagePath1 = "src/main/resources/img/lenna1.png"; Mat image1 = Imgcodecs.imread(imagePath1); // 检查图像是否成功加载 if (image1.empty()) { System.out.println("Error: Couldn't load images."); return; } HighGui.imshow("原图", image1); // 创建与图像1尺寸相同的图像2,每个像素值为100 Mat image2 = new Mat(image1.size(), image1.type(), new Scalar(100)); // 创建一个与图像1尺寸和类型相同的空白图像,用于存储结果 Mat result4add = new Mat(image1.size(), image1.type()); Mat result4subtract = new Mat(image1.size(), image1.type()); // 加法运算 Core.add(image1, image2, result4add); HighGui.imshow("图像相加", result4add); // 减法运算 Core.subtract(image1, image2, result4subtract); HighGui.imshow("图像相减", result4subtract); HighGui.waitKey(0); HighGui.destroyAllWindows(); System.exit(0); } }图像的明暗变化(图像加减乘除混合运算)
public class P621DarknessAdjustmentExample { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 加载两个图像 Mat image1 = Imgcodecs.imread("src/main/resources/img/lenna1.png"); // 检查图像是否成功加载 if (image1.empty()) { System.out.println("Error: Couldn't load images."); return; } HighGui.imshow("原图像", image1); // 定义暗度调整系数(在 0 到 1 之间) double darknessFactor = 0.5; // 减少 50% // 将图像1的每个像素值乘以暗度调整系数 // rtype:转换后的目标数据类型。如果值为 -1,则表示使用与源 Mat 对象相同的数据类型。 // 原像素值*alpha+beta Mat clone = image1.clone(); clone.convertTo(clone, -1, darknessFactor, 0); HighGui.imshow("明暗变化后", clone); HighGui.waitKey(0); HighGui.destroyAllWindows(); System.exit(0); } }6-3 图像的溶合
public class P630ImageFusionExample { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 读取图像1和图像2 Mat image1 = Imgcodecs.imread("src/main/resources/img/dog.jpg"); Mat image2 = Imgcodecs.imread("src/main/resources/img/background.jpg"); // 融合要求两张图片具有相同尺寸 Size size = getSize(image1, image2); // 图像融合 Mat blendedImage = blendImages(resizeImages(image1, size), resizeImages(image2, size)); // 显示融合后的图像 HighGui.imshow("Blended Image", blendedImage); HighGui.waitKey(0); HighGui.destroyAllWindows(); System.exit(0); } private static Size getSize(Mat image1, Mat image2) { int minWidth = Math.min(image1.width(), image2.width()); int minHeight = Math.min(image1.height(), image2.height()); return new Size(minWidth, minHeight); } // 将图像调整为size大小 private static Mat resizeImages(Mat image, Size size) { Mat mat = new Mat(size, image.type()); Imgproc.resize(image, mat, size); return mat; } // 图像融合 private static Mat blendImages(Mat image1, Mat image2) { double alpha = 0.9; // 调整融合的权重 Mat blendedImage = new Mat(); Core.addWeighted(image1, alpha, image2, 1 - alpha, 0, blendedImage); return blendedImage; } }原图1
原图2
融合效果
6-4 OpenCV位运算-非操作
public class P640ImageNegationExample { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 读取图像 Mat image = Imgcodecs.imread("src/main/resources/img/lenna1.png"); HighGui.imshow("原图", image); Mat mat = new Mat(); Core.bitwise_not(image, mat); // 显示融合后的图像 HighGui.imshow("图像的非运算", mat); HighGui.waitKey(0); HighGui.destroyAllWindows(); System.exit(0); } }6-5 OpenCV位操作-与运算
6-6 OpenCV位操作-或与异或
6-7 大作业-为图像添加水印
public class P670AddLogo { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 1. 引入图片 Mat background = Imgcodecs.imread("src/main/resources/img/background.jpg"); // 2. 制作logo Mat logo = new Mat(200, 200, CvType.CV_8UC3, new Scalar(0, 0, 0)); Mat mask = new Mat(200, 200, CvType.CV_8UC1, new Scalar(0, 0, 0)); Point topLeft = new Point(20, 20); Point bottomRight = new Point(120, 120); Imgproc.rectangle(logo, topLeft, bottomRight, new Scalar(0, 0, 255), 2); Imgproc.rectangle(mask, topLeft, bottomRight, new Scalar(255, 255, 255), 2); topLeft = new Point(80, 80); bottomRight = new Point(180, 180); Imgproc.rectangle(logo, topLeft, bottomRight, new Scalar(0, 255, 0), 2); Imgproc.rectangle(mask, topLeft, bottomRight, new Scalar(255, 255, 255), 2); Mat m = new Mat(); Core.bitwise_not(mask, m); HighGui.imshow("logo", logo); HighGui.imshow("mask", mask); HighGui.imshow("m", m); // 3. 计算添加位置,将添加位置变黑 Mat roi = new Mat(background, new Rect(0, 0, 200, 200)); HighGui.imshow("roi", roi); Mat tmp = new Mat(); Core.bitwise_and(roi, roi, tmp, m); HighGui.imshow("tmp", tmp); Mat dst = new Mat(); Core.add(tmp, logo, dst); HighGui.imshow("dst", dst); // 4.利用add,将图片和logo叠加到一起 Mat submat = background.submat(new Rect(0, 0, 200, 200)); dst.copyTo(submat); HighGui.imshow("background", background); HighGui.waitKey(0); HighGui.destroyAllWindows(); System.exit(0); } }7-1 图像的放大与缩小
public class P710Scale { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 读取图像 Mat originalImage = Imgcodecs.imread("src/main/resources/img/idea.png"); // 定义缩放后的图像大小 Size newSize = new Size(originalImage.width() * 5, originalImage.height() * 5); // 缩放图像(使用双立方插值) Mat resizedImage = new Mat(); Imgproc.resize(originalImage, resizedImage, newSize, 0, 0, Imgproc.INTER_AREA); // 显示原始图像和缩放后的图像 HighGui.imshow("Original Image", originalImage); HighGui.imshow("Resized Image", resizedImage); HighGui.waitKey(0); HighGui.destroyAllWindows(); System.exit(0); } }说明:第一张是原图,第二张是放大5倍的图,放大之后图像会模糊
7-2 图像的翻转
7-3 图像的旋转
/** * 图像的反转 * 0:沿X轴翻转(垂直翻转) * 1:沿Y轴翻转(水平翻转) * -1:同时沿X轴和Y轴翻转 */ public class P730ImageFlipExample { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 读取图像 Mat originalImage = Imgcodecs.imread("src/main/resources/img/lenna1.png"); // 沿X轴翻转(垂直翻转) Mat dstX = new Mat(); Core.flip(originalImage, dstX, 0); // 沿Y轴翻转(水平翻转) Mat dstY = new Mat(); Core.flip(originalImage, dstY, 1); Mat dstXY = new Mat(); Core.flip(originalImage, dstXY, -1); LinkedHashMap images = new LinkedHashMap(); images.put("原图", originalImage); images.put("沿着X轴翻转", dstX); images.put("沿着Y轴翻转", dstY); images.put("同时沿着XY轴翻转", dstXY); OpenCVUtil.show(images); HighGui.destroyAllWindows(); System.exit(0); } }效果图
7-4 仿射变换之图像平移
7-5 仿射变换之获取变换矩阵
7-6 仿射变换之变换矩阵之二
/** * 仿射变幻 */ public class P760ImageRotateExample { public static void main(String[] args) { // 加载动态库 System.load(new File("src/main/resources/lib/opencv/opencv_java490.dll").getAbsolutePath()); // 读取图像 Mat originalImage = Imgcodecs.imread("src/main/resources/img/lenna1.png"); // 定义旋转角度(逆时针) double angle = 45.0; // 获取图像中心点 Point center = new Point(originalImage.cols() / 2, originalImage.rows() / 2); // 计算旋转矩阵 Mat rotationMatrix = Imgproc.getRotationMatrix2D(center, angle, 1.0); // 执行旋转变换 Mat rotatedImage = new Mat(); Imgproc.warpAffine(originalImage, rotatedImage, rotationMatrix, new Size(originalImage.cols(), originalImage.rows())); // 显示原始图像和旋转后的图像 LinkedHashMap images = new LinkedHashMap(); images.put("原图", originalImage); images.put("逆时针旋转45°", rotatedImage); OpenCVUtil.show(images); HighGui.destroyAllWindows(); System.exit(0); } }7-7 OpenCV透视变换
8-1 图像滤波
OpenCV提供了许多不同类型的滤波器,可以用于图像处理的各种任务。以下是一些常用的滤波器类型:
-
低通滤波:去噪
- 均值滤波器(Mean Filter):用于平滑图像并减少噪声。它计算像素周围区域的平均值,并用该平均值替换中心像素的值。
- 高斯滤波器(Gaussian Filter):也用于平滑图像并减少噪声,但相比均值滤波器,它更加平滑。它计算像素周围区域的加权平均值,权重由高斯函数确定。
- 中值滤波器(Median Filter):用于去除椒盐噪声等斑点噪声。它将像素周围区域的值排序,并用中值替换中心像素的值。
- 双边滤波器(Bilateral Filter):用于平滑图像并保持边缘清晰。它考虑了像素之间的空间距离和像素值之间的相似性,以确定滤波器的权重。
-
高通滤波:检测边缘
- Sobel(索贝尔)滤波器:用于边缘检测。它使用两个3x3的卷积核,分别计算图像的水平和垂直方向的梯度。
- Laplacian(拉普拉斯)滤波器:也用于边缘检测。它计算图像的二阶导数,并可以提取出图像中的边缘。
8-2 卷积相关概念
8-3 实战图像卷积
8-4 方盒滤波与均值滤波
8-5 高斯滤波
8-6 中值滤波
8-7 双边滤波
8-8 高通滤波-索贝尔算子
8-9 高通滤波-沙尔算子
8-10 高通滤波-拉普拉斯算子
8-11 边缘检测Canny
9-1 形态学概述
9-2 图像全局二值化
9-3 阈值类型
9-4 自适应阈值二值化
9-5 OpenCV腐蚀
9-6 获取形态学卷积核
9-7 OpenCV膨胀
9-8 开运算
9-9 闭运算
9-10 形态学梯度
9-11 顶帽运算
9-12 黑帽操作
10-1 什么是图像轮廓
10-2 查找轮廓
10-3 绘制轮廓
10-4 轮廓的面积与周长
10-5 多边形逼近与凸包
10-6 外接矩形
10-7 项目总览【车辆统计】
10-8 视频加载【车辆统计】
10-9 形态学处理【车辆统计】
10-10 去背景【车辆统计】
10-11 逻辑处理【车辆统计】
10-12 显示信息【车辆统计】
11-1 特征检测的基本概念
11-2 Harris角点检测
11-3 Shi-Tomasi角点检测
11-4 SIFT关键点检测
11-5 SIFT计算描述子
11-6 SURF特征检测
11-7 OBR特征检测
11-8 暴力特征匹配
11-9 FLANN特征匹配
11-10 实战flann特征匹配
11-11 图像查找
11-12 大作业-图像拼接基础知识
11-13 大作业-图像拼接(一)
-
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!












