首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android OpenCV(十):图像透视变换

Android OpenCV(十):图像透视变换

作者头像
Vaccae
发布于 2021-01-06 07:55:53
发布于 2021-01-06 07:55:53
1.3K00
代码可运行
举报
文章被收录于专栏:微卡智享微卡智享
运行总次数:0
代码可运行

图像透视变换

透视变换(Perspective Transformation)是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。透视变换是按照物体成像投影规律进行变换,即将物体重新投影到新的成像平面。透视变换常用于机器人视觉导航研究中,由于相机视场与地面存在倾斜角使得物体成像产生畸变,通常通过透视变换实现对物体图像的校正。

原理

1

2

3

4

透视变换的方程组有8个未知数,所以要求解就需要找到4组映射点,四个点就刚好确定了一个三维空间。

API

求取变换矩阵

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static Mat getPerspectiveTransform(Mat src, Mat dst, int solveMethod)
  • 参数一:src,原图像中的四个像素坐标
  • 参数二:dst,目标图像中的四个像素坐标
  • 参数三:solveMethod,选择计算透视变换矩阵方法的标志,默认情况下选择的是最佳主轴元素的高斯消元法DECOMP_LU
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
enum DecompTypes {
    DECOMP_LU       = 0,
    DECOMP_SVD      = 1,
    DECOMP_EIG      = 2,
    DECOMP_CHOLESKY = 3,
    DECOMP_QR       = 4,
    DECOMP_NORMAL   = 16
};

标志位

作用

DECOMP_LU

0

最佳主轴元素的高斯消元法

DECOMP_SVD

1

奇异值分解(SVD)方法

DECOMP_EIG

2

特征值分解法

DECOMP_CHOLESKY

3

Cholesky分解法

DECOMP_QR

4

QR分解法

DECOMP_NORMAL

16

使用正规方程公式,可以去前面的标志一起使用

透视变换

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void warpPerspective(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode, Scalar borderValue) 

参数一:src,原图

参数二:dst,透视变换后输出图像,与src数据类型相同,但是尺寸与dsize相同

参数三:M,3*3变换矩阵

参数四:dsize,输出图像的尺寸

参数五:flags,插值方法标志

参数六:borderMode,像素边界外推方法的标志。BORDER_CONSTANT 或者BORDER_REPLICATE

参数七:borderValue,填充边界使用的数值,默认情况下为0

操作

下面代码实现将相机视线不垂直于马路平面拍摄的图像经过透视变换变成相机视线垂直于马路平面拍摄的图像。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class PerspectiveTransformationActivity : AppCompatActivity() {

    private lateinit var mBinding: ActivityPerspectiveTransformationBinding
    private lateinit var mRgb: Mat
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_perspective_transformation)

        val bgr = Utils.loadResource(this, R.drawable.road)
        mRgb = Mat()
        Imgproc.cvtColor(bgr, mRgb, Imgproc.COLOR_BGR2RGB)
        showMat(mBinding.ivRoad, mRgb)

        doPerspectiveTransform()
    }

    private fun showMat(view: ImageView, source: Mat) {
        val bitmap = Bitmap.createBitmap(source.width(), source.height(), Bitmap.Config.ARGB_8888)
        Utils.matToBitmap(source, bitmap)
        view.setImageBitmap(bitmap)
    }

    private fun getPerspectiveTransform(): Mat {
        val srcPoints = ArrayList<Point>()
        val p1 = Point(325.0000, 374.0000)
        srcPoints.add(p1)
        val p2 = Point(597.0000, 374.0000)
        srcPoints.add(p2)
        val p3 = Point(960.0000, 505.0000)
        srcPoints.add(p3)
        val p0 = Point(0.0000, 505.0000)
        srcPoints.add(p0)
        val srcMat = Converters.vector_Point2f_to_Mat(srcPoints)

        val resultWidth = 500.0
        val resultHeight = 500.0
        val dstPoints = ArrayList<Point>()
        val p5 = Point(0.0, 0.0)
        dstPoints.add(p5)
        val p6 = Point(resultWidth, 0.0)
        dstPoints.add(p6)
        val p7 = Point(resultWidth, resultHeight)
        dstPoints.add(p7)
        val p4 = Point(0.0, resultHeight)
        dstPoints.add(p4)
        val dstMat = Converters.vector_Point2f_to_Mat(dstPoints)
        return Imgproc.getPerspectiveTransform(srcMat, dstMat)
    }

    private fun doPerspectiveTransform() {
        val transform = getPerspectiveTransform()
        val dst = Mat()
        Imgproc.warpPerspective(
            mRgb,
            dst,
            transform,
            Size(500.0, 500.0),
            Imgproc.INTER_NEAREST
        )
        showMat(mBinding.ivResult, dst)
    }

    override fun onDestroy() {
        mRgb.release()
        super.onDestroy()
    }
}

效果

透视变换

源码

https://github.com/onlyloveyd/LearningAndroidOpenCV

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微卡智享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
windows API 开发飞机订票系统 图形化界面 (二)
首先,用到的数据结构的定义、以及全局变量和函数的声明如下: 1 // Flight.c : 定义应用程序的入口点。 2 // 3 #include "stdafx.h" 4 5 //订单 6 typedef struct OrderForm{ 7 TCHAR IdNum[32]; //订单用户身份证号 8 int Order_Number;
欠扁的小篮子
2018/04/10
1.3K0
自制截图工具V1.0
之前比较空闲,就尝试着做了个截图工具,功能还算实用。等以后有时间再研究V2.0。 这个项目都是用C语言做的,所以还算精简。 #include <windows.h> #include <stdio.h> #include "resource.h" #pragma comment(lib,"winmm.lib") HINSTANCE g_hInstance = NULL;//全局进程句柄 HWND g_hwndMain = NULL;//全局主窗口句柄 #define UM_SCREENCUT WM_U
_gongluck
2018/03/08
1.3K0
【二】Windows API 零门槛编程指南——CreateWindow 窗口创建 “万字长篇专业术语全解”
本系列博文几乎没有难啃的“专业术语”,尽量让读者能够看明白文章所述内容,是本系列博文的核心宗旨之一。(由于本人也是由于项目需要,所以才来查阅相关资料,文中出现的错误欢迎指出,共同进步!谢谢!)
1_bit
2020/10/23
1.6K0
【二】Windows API 零门槛编程指南——CreateWindow 窗口创建 “万字长篇专业术语全解”
【读书笔记】Windows程序设计5
与从BeginPaint函数返回的设备句柄不同,从GetDC返回的设备句柄中的裁剪区域是整个客户区,而不仅仅
zhang_derek
2022/12/21
2.6K0
MFc界面添加滚动条笔记
2.The Fingerprint Contrast and Analysis System
流川疯
2019/01/18
1.4K0
【Windows编程】系列第六篇:创建Toolbar与Statusbar
上一篇我们学习了解了如何使用Windows GDI画图,该应用程序都是光光的静态窗口,我们使用Windows应用程序,但凡稍微复杂一点的程序都会有工具栏和状态栏,工具栏主要用于一些快捷功能按钮。比如典型的windows应用程序的上面是菜单栏,从菜单栏我们可以选择应用程序提供的各种功能,但是有的功能比较常用,且不能放在第一级菜单,需要进入二级、三级甚至更多的菜单才能选择。显然这样使用起来比较麻烦,于是这时候工具栏的作用就体现出来了,一般工具栏位于菜单栏的下面,但是位于客户窗口的上面。下面就是windows的文
程序员互动联盟
2018/03/13
2.4K1
【Windows编程】系列第六篇:创建Toolbar与Statusbar
键盘钩子入门
钩子是操作系统消息处理的一种机制。通过钩子,应用程序可以安装一个钩子回调过程让系统调用,从而监视系统中的消息队列。在这些消息到达目标窗口之前对这些消息进行处理。
全栈程序员站长
2022/08/11
1.1K0
键盘钩子入门
Win基本框架代码
声明:本文为原创,作者为 对弈,转载时请保留本声明及附带文章链接:http://www.duiyi.xyz/c%e5%ae%9e%e7%8e%b0%e9%9b%b7%e9%9c%86%e6%88%98%e6%9c%ba-58/
对弈
2019/09/04
5380
【OpenGL】七、桌面窗口搭建 ( 导入头文件 | 桌面程序入口函数 | 注册窗口 | 创建窗口 | 显示窗口 )
基于 【OpenGL】一、Visual Studio 2019 创建 Windows 桌面程序 ( Visual Studio Installer 安装 C++ 桌面开发库 | 创建桌面程序 ) 博客中创建的 Windows 桌面程序继续向下讲解 , Visual Studio 自动生成了空白的桌面程序 , OpenGL 系列开发基于该桌面程序进行 ;
韩曙亮
2023/03/28
1.5K0
【OpenGL】七、桌面窗口搭建 ( 导入头文件 | 桌面程序入口函数 | 注册窗口 | 创建窗口 | 显示窗口 )
windows api学习笔记-简单的记事本
#include <windows.h> #include "resource.h" #include <string> LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);//窗口函数的函数原型 int APIENTRY WinMain( //APIENTRY是__stdcall的宏定义 HINSTANCE hInstance, //本模块的实例句柄
liulun
2022/05/09
4990
汇编语言学习笔记-使用窗体控件
.386 .model flat,stdcall;内存平坦,参数传递约定 option casemap:none;大小写敏感 ;;;;;;引用一些必要的数据 include D:\masm32\include\windows.inc include D:\masm32\include\user32.inc include \masm32\include\gdi32.inc includelib D:\masm32\lib\user32.lib include D:\masm32\
liulun
2022/05/09
4270
win32api显示BMP图片的最简单方案
三、补充 装载位图的方法其实很多,也不需要第三防库 1.从资源中装载,很简单: LoadBitmap(hInstance,(LPCTSTR)IDB_BITMAP1);
全栈程序员站长
2022/09/27
1.1K0
windows api学习笔记-使用定时器
#include <windows.h> #include "resource.h" #include <string> LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);//窗口函数的函数原型 int APIENTRY WinMain( //APIENTRY是__stdcall的宏定义 HINSTANCE hInstance, //本模块的实例句柄
liulun
2022/05/09
6020
win32程序之子窗口编程
  在前边我们已经讲解了窗口的本质.以及如何注册窗口类跟创建窗口. 还讲了消息循环.
IBinary
2018/09/28
2.1K0
win32程序之子窗口编程
BitBlt_bitcmp
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/02
3150
Win32实现GDI画太极图
声明:本文为原创,作者为 对弈,转载时请保留本声明及附带文章链接:http://www.duiyi.xyz/c%e5%ae%9e%e7%8e%b0%e9%9b%b7%e9%9c%86%e6%88%98%e6%9c%ba-60/
对弈
2019/09/04
8380
菜单的使用
2)弹出式菜单:一般在顶级菜单上都有很多菜单项,单击这些菜单项时会弹出一个下拉式的菜单项,我们点击的这个菜单称为弹出式菜单
Masimaro
2018/08/31
1.5K0
Windows窗口模板
1.界面效果 2.相关代码 #include<Windows.h> LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPAR
花狗Fdog
2020/10/28
6000
Windows窗口模板
单选钮和复选框控件的应用教案_在mfc中弹出一个窗口
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/170968.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/23
1.7K0
Windows 下窗口画图---十天教会你俄罗斯方块
接上篇:https://blog.csdn.net/qq_41603898/article/details/80968333
用户2965768
2018/08/30
6690
推荐阅读
相关推荐
windows API 开发飞机订票系统 图形化界面 (二)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档