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

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正

Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正

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

在OpenCV中,仿射变换(Affine Transformation)和透视变换(Perspective Transformation)是两种常用的图像几何变换方法。

变换方法适用场景
仿射变换简单的几何变换(平移、旋转、缩放、剪切)。
透视变换改变图像视角和模拟3D投影效果。
变换方法解释特点应用场景实现方法
仿射变换仿射变换是一种线性变换,它保持了图像中直线的直线性和平行线的平行性。常见的仿射变换包括平移、旋转、缩放、剪切等。输入空间和输出空间之间存在线性关系。
直线和平行性在变换后保持不变,但角度和长度可能发生改变。
图像平移、旋转或缩放。
图像对齐(如在模板匹配中的坐标对齐)。
简单的几何变形,如剪切变换。
准备变换矩阵(2x3)。
使用 OpenCV 的 cv2.warpAffine() 方法进行变换。
透视变换透视变换是一种非线性变换,用于将图像从一个平面映射到另一个平面。它允许改变图像的视角,从而获得三维的透视效果。输入空间和输出空间之间是非线性的。
直线保持直线,但平行线不再平行。
需要 4 对点来定义变换关系。
图像校正(如将拍摄的书本照片调整为平面图)。
视角转换(如模拟3D效果或鸟瞰视图)。
投影变换(如在增强现实中的投影映射)。
定义输入和输出平面上的 4 个对应点。
使用 cv2.getPerspectiveTransform() 获取 3x3 的透视变换矩阵。
使用 cv2.warpPerspective() 方法进行变换。

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.trans

import org.bytedeco.javacpp.Loader
import org.bytedeco.javacpp.Pointer
import org.bytedeco.opencv.global.opencv_core
import org.bytedeco.opencv.global.opencv_highgui
import org.bytedeco.opencv.global.opencv_imgcodecs
import org.bytedeco.opencv.global.opencv_imgproc
import org.bytedeco.opencv.opencv_core.Mat
import org.bytedeco.opencv.opencv_core.Point
import org.bytedeco.opencv.opencv_core.Point2f
import org.bytedeco.opencv.opencv_core.Scalar
import org.bytedeco.opencv.opencv_highgui.MouseCallback

object Restore {

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

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

    /**
     * 透视变换 图像修改
     *
     * @since 2025年1月20日12点33分
     */
    private fun restore(type: Int) {
        // 读取图像
        val src = opencv_imgcodecs.imread("C:\\Users\\xuyq\\Desktop\\11.png")
        if (src == null || src.empty()) {
            return
        }
        // 创建源点矩阵4个点
        val org = Mat(1, 4, opencv_core.CV_32FC2)
        org.ptr(0, 0).put<Pointer>(Point2f(0f, 0f))
        org.ptr(0, 1).put<Pointer>(Point2f(src.cols().toFloat(), 0f))
        org.ptr(0, 2).put<Pointer>(Point2f(src.cols().toFloat(), src.rows().toFloat()))
        org.ptr(0, 3).put<Pointer>(Point2f(0f, src.rows().toFloat()))
        // 创建目标点矩阵4个点
        val dst = Mat(1, 4, opencv_core.CV_32FC2)
        if (1 == type) {
            val target = click(src)
            for (i in target.indices) {
                dst.ptr(0, i).put<Pointer>(target[i])
            }
        } else {
            dst.ptr(0, 0).put<Pointer>(Point2f(21f, 20f))
            dst.ptr(0, 1).put<Pointer>(Point2f(953f, 74f))
            dst.ptr(0, 2).put<Pointer>(Point2f(847f, 574f))
            dst.ptr(0, 3).put<Pointer>(Point2f(109f, 643f))
        }
        // 获取透视变换矩阵
        val matrix = opencv_imgproc.getPerspectiveTransform(dst, org)
        // 应用透视变换
        val images = Mat()
        opencv_imgproc.warpPerspective(src, images, matrix, src.size())
        // 显示结果
        opencv_highgui.imshow("RESTORE", images)
        opencv_highgui.waitKey(0)
    }


    private fun click(image: Mat): List<Point2f> {
        // 创建画布(白色背景)
        val window = "Click"
        // 创建窗口
        opencv_highgui.namedWindow(window, opencv_highgui.WINDOW_AUTOSIZE)
        val points = listOf<Point2f>().toMutableList()
        // 创建鼠标回调对象
        val callback = object : MouseCallback() {
            override fun call(event: Int, x: Int, y: Int, flags: Int, params: Pointer?) {
                when (event) {
                    opencv_highgui.EVENT_LBUTTONDOWN -> {
                        println("点击点: ($x, $y)")
                        points.add(Point2f(x.toFloat(), y.toFloat()))
                        // 在原图上绘制点
                        opencv_imgproc.circle(
                            image, Point(x, y), 5,
                            Scalar(0.0, 0.0, 255.0, 0.0), -1, opencv_imgproc.LINE_AA, 0
                        )
                        opencv_highgui.imshow(window, image)
                    }
                }
            }
        }
        // 设置鼠标回调
        opencv_highgui.setMouseCallback(window, callback, null)
        // 主循环
        while (true) {
            opencv_highgui.imshow(window, image)
            if (opencv_highgui.waitKey(1).toChar() == 27.toChar() || points.size >= 4) {
                opencv_highgui.destroyWindow(window)
                break
            }
        }
        return points
    }

}

3 测试结果

在这里插入图片描述
在这里插入图片描述


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

相关文章:

  • Spring自定义BeanPostProcessor实现bean的代理Java动态代理知识
  • 运动相机拍视频过程中摔了,导致录视频打不开怎么办
  • Output
  • macOS Sequoia 15.3 beta3(24D5055b)发布,附黑、白苹果镜像下载地址
  • Linux使用SSH连接GitHub指南
  • PHP xml 常用函数整理
  • C#如何获取电脑中的端口号和硬件信息
  • Observability:最大化可观察性 AI 助手体验的 5 大提示(prompts)
  • 游戏开发中常用的设计模式
  • 大数据中 TopK 问题的常用套路
  • 基于.NetCore+Vue的贫困地区儿童资助系统
  • GraphRAG: Auto Prompt Tuning 实践
  • 一文大白话讲清楚webpack基本使用——1——完成webpack的初步构建
  • PyTorch使用教程- Tensor包
  • windows 远程链接 Ubuntu 24.04 LTS 图形界面
  • 机器狗:科技新宠,未来已来
  • TensorBoard 无数据问题
  • 物联网在烟草行业的应用
  • 深入浅出:Go语言os包中的API使用指南
  • 中国石油大学(华东)自动评教工具(涵盖爬虫的基础知识,适合练手)
  • 【Flink系列】9. Flink容错机制
  • 第8章:Python TDD处理货币类代码重复问题
  • 假设k8s集群规模上千,需要注意的问题有哪些?
  • 在 CentOS 7.9 上编译 Nginx 并启用 SSL 模块时遇到缺少 OpenSSL 源码的编译问题及解决方案
  • 1.18学习
  • 汽车 SOA 架构下的信息安全新问题及对策漫谈