当前位置: 首页 > article >正文

Kotlin Bytedeco OpenCV 图像图像51.1 KNN背景消除

Kotlin Bytedeco OpenCV 图像图像51.1 KNN背景消除

  • 1 添加依赖
  • 2 测试代码
  • 3 测试结果

方法适用场景优点计算量
MOG2复杂背景可检测阴影中等
KNN动态背景适用于波动场景较高
Running Average静态背景计算简单
Frame Differencing低光照变化场景计算快
Optical Flow复杂运动场景精度高

如果你的场景是 一般的视频监控,推荐使用 MOG2 或 KNN。
如果你的场景是 背景变化缓慢,推荐 Running Average。

1 添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xu</groupId>
    <artifactId>KotlinOpenCV</artifactId>
    <version>1.0</version>

    <properties>
        <kotlin.version>2.0.0</kotlin.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <kotlin.code.style>official</kotlin.code.style>
        <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
    </properties>

    <repositories>
        <repository>
            <id>mavenCentral</id>
            <url>https://repo1.maven.org/maven2/</url>
        </repository>
    </repositories>

    <dependencies>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.29</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.27.0</version>
        </dependency>

        <dependency>
            <groupId>org.tukaani</groupId>
            <artifactId>xz</artifactId>
            <version>1.10</version>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlinx</groupId>
            <artifactId>kotlinx-coroutines-core</artifactId>
            <version>1.9.0-RC</version>
        </dependency>

        <!--        <dependency>-->
        <!--            <groupId>org.opencv</groupId>-->
        <!--            <artifactId>opencv</artifactId>-->
        <!--            <version>4100</version>-->
        <!--            <scope>system</scope>-->
        <!--            <systemPath>${project.basedir}/lib/opencv/opencv-4100.jar</systemPath>-->
        <!--        </dependency>-->

        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>opencv-platform</artifactId>
            <version>4.10.0-1.5.11</version>
        </dependency>

        <!--        <dependency>-->
        <!--            <groupId>org.bytedeco</groupId>-->
        <!--            <artifactId>ffmpeg-platform</artifactId>-->
        <!--            <version>6.1.1-1.5.10</version>-->
        <!--        </dependency>-->

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test-junit5</artifactId>
            <version>2.0.0</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.10.0</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>2.0.0</version>
        </dependency>

    </dependencies>

    <build>
        <sourceDirectory>src/main/kotlin</sourceDirectory>
        <testSourceDirectory>src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>2.0.0</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <configuration>
                    <mainClass>MainKt</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2 测试代码

package com.xu.com.xu.video

import org.bytedeco.javacpp.Loader
import org.bytedeco.opencv.global.opencv_core
import org.bytedeco.opencv.global.opencv_highgui
import org.bytedeco.opencv.global.opencv_imgproc
import org.bytedeco.opencv.global.opencv_video
import org.bytedeco.opencv.opencv_core.Mat
import org.bytedeco.opencv.opencv_core.MatVector
import org.bytedeco.opencv.opencv_core.Size
import org.bytedeco.opencv.opencv_videoio.VideoCapture

object BSM {

    init {
        Loader.load(opencv_core::class.java)
    }

    @JvmStatic
    fun main(args: Array<String>) {
        knn()
    }

    fun flow() {
        // 打开视频流
        val capture = VideoCapture("lib/video/video_003.avi")
        if (!capture.isOpened) {
            return
        }

        val prev = Mat()  // 存储上一帧灰度图像
        val gray = Mat()      // 当前帧灰度图像
        val flow = Mat()      // 存储光流结果

        val org = Mat()       // 存储当前原始帧
        val mask = Mat()      // 用于存储前景掩码

        while (true) {
            // 读取当前帧
            capture.read(org)
            if (org.empty()) break
            // 转换为灰度图
            opencv_imgproc.cvtColor(org, gray, opencv_imgproc.COLOR_BGR2GRAY)
            if (!prev.empty()) {
                // 计算光流
                opencv_video.calcOpticalFlowFarneback(
                    prev, gray, flow,
                    0.5, // `pyrScale` 适当降低(0.4-0.6),减少背景干扰
                    3,   // `levels` 适当增加(2-4),提高检测范围
                    1,   // `windowSize` 增大(3→5),增强检测
                    20,  // `iterations` 增加迭代次数,提高准确度
                    5,   // `polyN`(5-7),适当提高减少噪声
                    1.2, // `polySigma` 增大(1.2 → 1.5),平滑光流
                    0    // `flags` 默认为 0
                )
                // 计算光流的幅度
                val channels = MatVector()
                opencv_core.split(flow, channels) // 拆分 X / Y 分量
                val mag = Mat()
                opencv_core.magnitude(channels[0], channels[1], mag)
                // 归一化幅度(norm 的类型为 CV_32F)
                val norm = Mat()
                opencv_core.normalize(mag, norm, 0.0, 255.0, opencv_core.NORM_MINMAX, -1, Mat())
                // 将 norm 转换为 8 位图像(CV_8U)
                val calc = Mat()
                norm.convertTo(calc, opencv_core.CV_8U)
                // 进行二值化处理,提取运动区域(mask 的类型为 CV_8UC1)
                //opencv_imgproc.threshold(calc, mask, 10.0, 255.0, opencv_imgproc.THRESH_BINARY)
                opencv_imgproc.adaptiveThreshold(
                    calc, mask, 255.0,
                    opencv_imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
                    opencv_imgproc.THRESH_BINARY,
                    10, 2.0
                )
                // 形态学处理去噪声
                val kernel = opencv_imgproc.getStructuringElement(opencv_imgproc.MORPH_RECT, Size(1, 1))
                opencv_imgproc.morphologyEx(mask, mask, opencv_imgproc.MORPH_OPEN, kernel)
                opencv_imgproc.morphologyEx(mask, mask, opencv_imgproc.MORPH_CLOSE, kernel)
                // 确保类型一致
                val comm = Mat()
                opencv_imgproc.cvtColor(mask, comm, opencv_imgproc.COLOR_GRAY2BGR)
                // 确保大小一致
                if (comm.size() != org.size()) {
                    opencv_imgproc.resize(comm, comm, org.size())
                }
                // 进行拼接显示
                val show = Mat()
                opencv_core.hconcat(org, comm, show)
                opencv_highgui.imshow("Optical Flow BSM", show)
            }
            // 复制当前帧用于下一次计算
            gray.copyTo(prev)
            // 检查用户按键
            if (opencv_highgui.waitKey(30) == 'q'.code) break
        }
        // 释放资源
        capture.release()
        opencv_highgui.destroyAllWindows()
    }

    fun gmm() {
        // 打开视频流(可使用摄像头或者视频文件路径)
        val capture = VideoCapture(0)
        capture.open("lib/video/video_003.avi")
        // 创建背景减除器
        val bg = opencv_video.createBackgroundSubtractorMOG2().apply {
            history = 500         // 历史帧数
            varThreshold = 16.0   // 方差阈值
            detectShadows = true  // 检测阴影
        }
        // 创建Mat对象用于存储视频帧和结果
        val org = Mat()
        val dst = Mat()

        while (true) {
            // 读取当前帧
            capture.read(org)
            if (org.empty()) break
            // 应用背景减除器
            bg.apply(org, dst)
            // 可选:对前景蒙版进行一些后处理(如形态学操作)
            val kernel = opencv_imgproc.getStructuringElement(opencv_imgproc.MORPH_RECT, Size(1, 1))
            opencv_imgproc.morphologyEx(dst, dst, opencv_imgproc.MORPH_CLOSE, kernel)
            // 确保类型一致
            val mat = Mat()
            opencv_imgproc.cvtColor(dst, mat, opencv_imgproc.COLOR_GRAY2BGR)
            // 确保大小一致
            if (dst.size() != org.size()) {
                opencv_imgproc.resize(mat, mat, org.size())
            }
            // 进行拼接
            val show = Mat()
            opencv_core.hconcat(org, mat, show)
            opencv_highgui.imshow("MOG2 BSM", show)
            // 检查用户按键
            if (opencv_highgui.waitKey(30) == 'q'.code) break
        }
        // 释放资源
        capture.release()
        opencv_highgui.destroyAllWindows()
    }

    fun knn() {
        // 打开视频流(可使用摄像头或者视频文件路径)
        val capture = VideoCapture("lib/video/video_003.avi")
        if (!capture.isOpened) {
            return
        }
        // 创建 KNN 背景减除器
        val bg = opencv_video.createBackgroundSubtractorKNN().apply {
            history = 500         // 历史帧数
            dist2Threshold = 400.0 // 距离阈值,控制前景检测的敏感度
            detectShadows = true  // 是否检测阴影
        }
        // 创建 Mat 对象用于存储视频帧和结果
        val org = Mat()
        val dst = Mat()
        while (true) {
            // 读取当前帧
            capture.read(org)
            if (org.empty()) break
            // 应用背景减除器
            bg.apply(org, dst)
            // 可选:对前景蒙版进行一些后处理(如形态学操作)
            val kernel = opencv_imgproc.getStructuringElement(opencv_imgproc.MORPH_RECT, Size(3, 3))
            opencv_imgproc.morphologyEx(dst, dst, opencv_imgproc.MORPH_CLOSE, kernel)
            // 确保类型一致
            val mat = Mat()
            opencv_imgproc.cvtColor(dst, mat, opencv_imgproc.COLOR_GRAY2BGR)
            // 确保大小一致
            if (dst.size() != org.size()) {
                opencv_imgproc.resize(mat, mat, org.size())
            }
            // 进行拼接
            val show = Mat()
            opencv_core.hconcat(org, mat, show)
            // 显示结果
            opencv_highgui.imshow("KNN BSM", show)
            // 检查用户按键
            if (opencv_highgui.waitKey(30) == 'q'.code) break
        }
        // 释放资源
        capture.release()
        opencv_highgui.destroyAllWindows()
    }

}

3 测试结果

在这里插入图片描述


http://www.kler.cn/a/540255.html

相关文章:

  • JAVA中的抽象学习
  • 【C++】命名空间
  • 【韩顺平linux】部分上课笔记整理
  • 【Python】元组
  • 迁移学习 Transfer Learning
  • C 移位运算符
  • 防火墙:用户认证综合练习实验
  • http 模块
  • 自有服务与软件包
  • vite + axios 代理不起作用 404 无效
  • DeepSeek帮助做【真】软件需求-而不是批量刷废话
  • 【Flink源码分析】5. Flink1.19源码分析-异步编程(CompletableFuture)
  • 单片机上SPI和IIC的区别
  • DuckDB:pg_duckdb集成DuckDB和PostgreSQL实现高效数据分析
  • CWOI-N RER 1 > 2 Solution
  • MYSQL学习笔记(七):新年第一篇之子查询
  • 机器学习:定义、原理、应用与未来(万字总结)
  • 标签画像系统设计分析
  • 一、boolen盲注和时间盲注
  • Linux系统-centos防火墙firewalld详解
  • 《StyTr²:基于 Transformer 的图像风格迁移》学习笔记
  • ES传输带宽优化方案
  • 9.JVM-方法区
  • 第四个Qt开发实例(为Label组件添加显示的文字)
  • 【机器学习与数据挖掘实战】案例13:基于BP神经网络模型的家用热水器用户行为分析与事件识别
  • 哪些情况会导致JVM内存泄露