opencv图像透视处理

news2024/9/23 5:29:21

引言

在图像处理与计算机视觉领域,透视变换(Perspective Transformation)是一种重要的图像校正技术,它允许我们根据图像中已知的四个点(通常是矩形的四个角)和目标位置的四个点,将图像从一个视角映射到另一个视角。这种技术广泛应用于文档扫描、增强现实、图像拼接以及许多其他领域。本文将通过OpenCV这一强大的图像处理库,介绍如何执行图像的透视变换。

目录

引言

OpenCV简介

透视变换的基础

公式

OpenCV中的透视变换

步骤

结论


OpenCV简介

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它包含了大量的图像处理函数和算法,可以运行在多种操作系统上,具有高效的性能和广泛的应用。

透视变换的基础

透视变换可以通过一个3x3的变换矩阵(也称为透视变换矩阵)来实现。这个矩阵定义了源图像和目标图像之间的映射关系。为了计算这个矩阵,我们需要知道源图像和目标图像中对应点的坐标。

公式

透视变换的数学表达式通常表示为:

begin{bmatrix} x' \\ y' \\ w' end{bmatrix} = begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & 1 end{bmatrix} begin{bmatrix} x \\ y \\ 1 end{bmatrix}

其中,(x,y) 是源图像中的点,(x′,y′) 是变换后图像中的对应点。w′ 是一个用于归一化的因子(通常不需要直接使用,但在计算时很有用)。

OpenCV中的透视变换

在OpenCV中,cv2.getPerspectiveTransform() 函数用于计算透视变换矩阵,而 cv2.warpPerspective() 函数则用于应用这个矩阵到图像上。

步骤

  1. 确定源点和目标点:首先,你需要从源图像中选取四个点(通常是矩形的四个角),并确定这四个点在目标图像中的位置。

  2. 计算透视变换矩阵:使用 cv2.getPerspectiveTransform(src, dst) 来计算透视变换矩阵,其中 src 是源点坐标(形式为 (x, y) 的列表的列表),dst 是目标点坐标。

  3. 应用透视变换:使用 cv2.warpPerspective(src_img, M, (width, height)) 将变换矩阵 M 应用到源图像 src_img 上,width 和 height 是目标图像的宽度和高度。

代码示例

import cv2  
import numpy as np  
  
# 读取图像  
img = cv2.imread('source_image.jpg')  
  
# 定义源点和目标点  
pts_src = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])  
pts_dst = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])  
  
# 计算透视变换矩阵  
M = cv2.getPerspectiveTransform(pts_src, pts_dst)  
  
# 应用透视变换  
height, width = img.shape[:2]  
warped_img = cv2.warpPerspective(img, M, (width, height))  
  
# 显示结果  
cv2.imshow('Warped Image', warped_img)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

代码实例

import cv2
import numpy as np


def order_points(pts):
    """
    根据点的位置对它们进行排序,以便左上角、右上角、右下角、左下角的顺序。
    这里使用简单的排序逻辑,可能需要根据实际情况调整。
    """
    rect = np.zeros((4, 2), dtype="float32")

    # 按x坐标排序,然后按y坐标排序(如果需要)
    s = pts.sum(axis=1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]

    # 计算x坐标的差值
    diff = np.diff(pts, axis=1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]

    return rect


def four_point_transform(image, pts):
    """
    对图像进行透视变换。
    :param image: 输入图像
    :param pts: 源图像中的四个点(矩形的四个角),格式为[(x1, y1), (x2, y2), (x3, y3), (x4, y4)]
    :return: 变换后的图像
    """
    rect = order_points(pts)
    (tl, tr, br, bl) = rect

    # 计算目标矩形的宽度
    widthA = np.linalg.norm(br - bl)
    widthB = np.linalg.norm(tr - tl)
    maxWidth = max(int(widthA), int(widthB))

    # 计算目标矩形的高度
    heightA = np.linalg.norm(tr - br)
    heightB = np.linalg.norm(tl - bl)
    maxHeight = max(int(heightA), int(heightB))

    # 目标点
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")

    # 计算透视变换矩阵并应用它
    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))

    # 返回变换后的图像
    return warped


# 读取图像
image = cv2.imread('bea.jpg')
if image is None:
    print("Error: Unable to load image.")
else:
    # 假设我们手动选取了文档的四个角点(这里用示例坐标代替)
    pts = np.array([[56, 65], [368, 52], [28, 387], [389, 390]], dtype="float32")

    # 进行透视变换
    warped_image = four_point_transform(image, pts)

    # 显示结果
    cv2.imshow('Original Image', image)
    cv2.imshow('Warped Image', warped_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

结果:

结论

通过本文,我们学习了如何使用OpenCV进行图像的透视变换。从理论基础到实践代码,我们逐步了解了透视变换的整个过程。这项技术不仅可以用于图像校正,还可以为许多其他应用提供强大的支持。希望本文能为你处理图像透视变换提供有力的帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2122328.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024.9.10 作业

代码&#xff1a; /*******************************************/ 文件名&#xff1a;widget.h /*******************************************/ #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QLabel> #include <QTimeEdit> #includ…

opencv学习:信用卡卡号识别

该代码用于从信用卡图像中自动识别和提取数字信息。该系统将识别信用卡类型&#xff0c;并输出信用卡上的数字序列。 1.创建命令行参数 数字模板 信用卡 # 创建命令行参数解析器 ap argparse.ArgumentParser() # 添加命令行参数 -i/--image&#xff0c;指定输入图像路径 ap.…

破局DRG/DIP亏损,医院应该怎么做

DRG/DIP付费实施后&#xff0c;医院各临床科室可结合前期数据积累&#xff0c;根据DRG/DIP专科病组/病种四级手术占比与医疗收入占比之间的变化关系、建立DRG/DIP战略分布象限图&#xff0c;将病组分为优势病组&#xff08;病种&#xff09;、潜力病组&#xff08;病种&#xf…

线程(Thread)

目录 线程&#xff08;Thread&#xff09; 线程的创建方式 实现方式 Runnable和Callable的区别 线程的命名和优先级 线程的六种状态 线程的插队 线程的中断 线程的让出 守护线程 设置线程为守护线程 sleep()和wait()的区别 线程的同步synchronized锁 语法格式 实现…

在线动漫信息平台

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Spring Boot框架 工具&#xff1a;IDEA/Eclipse、Navicat、Maven 系统展示 首页 会员后台 管理员…

day-52 下一个排列

思路 从后向前遍历数组&#xff0c;把遍历过的元素加入一个有序链表&#xff0c;没变里一个元素判断链表中是否有元素大于当前遍历元素&#xff0c;如果有&#xff0c;把链表中大于当前遍历元素的元素集合中最小的那一个元素赋给当前元素&#xff0c;然后将链表中剩余元素依次赋…

建造者模式builder

此篇为学习笔记&#xff0c;原文链接 https://refactoringguru.cn/design-patterns/builder 能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象

JavaWeb【day14】--(SpingBoot原理)

SpingBoot原理 在前面十多天的课程当中&#xff0c;我们学习的都是web开发的技术使用&#xff0c;都是面向应用层面的&#xff0c;我们学会了怎么样去用。而我们今天所要学习的是web后端开发的最后一个篇章springboot原理篇&#xff0c;主要偏向于底层原理。 我们今天的课程安…

2-2 opencv实战进阶系列 多边形识别

目录 一、不说废话&#xff0c;先上现象 二、前言 三、思路讲解 step1&#xff1a;用阈值编辑器对图像进行处理。 step2&#xff1a;应用阈值进行二值化 step3&#xff1a;轮廓查找 step4&#xff1a; 显示文字 四、完整代码贴出 五、现象展示 六、结语 一、不说废话&…

在单向链表中找环

在单向链表中找环也是有多种办法&#xff0c;不过快慢双指针方法是其中最为简洁的方法之一&#xff0c;接下来介绍这种方法。 首先两个指针都指向链表的头部&#xff0c;令一个指针一次走一步&#xff0c;另一个指针一次走两步&#xff0c;如果它们相遇了&#xff0c;证明有环…

数据结构(7.2_1)——顺序查找

顺序查找&#xff0c;又叫"线性查找"&#xff0c;通常用于线性表&#xff08;或者顺序表和链表&#xff09;。 算法思想&#xff1a;从头到尾全部查找出来&#xff08;或者反过来也OK&#xff09; 顺序查找的实现 typedef struct {//查找表的数据结构(顺序表)Elem…

再遇“类和对象”

一、类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最后两个取地址重载不…

visio修改默认字体、颜色、形状格式、连接线格式

设计中取消勾选“将主题应用于新建的形状” 在开发工具中打开绘图资源管理器&#xff0c;并分别修改纯文本、连接线、主题的样式

文本转化为声音

在许多场景下需要将文本转化为MP3格式&#xff0c;本文将实现文本转化为声音&#xff0c;并且将声音保存为MP3格式。本文一朱自清的《春》为例&#xff0c;要实现阅读《春》并且转化为mp3格式的音频文件。 1 导入包 import pyttsx3 from docx import Document def read_word_…

ubuntu内核升级后的问题修复

文章目录 需求当前环境禁止内核更新安装内核修复/usr/include/dlocate 测试 需求 升级后的常见问题 驱动程序不兼容: 新内核版本可能导致某些硬件驱动程序不再兼容&#xff0c;尤其是专有驱动程序或第三方驱动程序。启动问题:内核更新可能导致启动问题&#xff0c;例如无法启动…

《创新电力巡检,机器人铸就安全高效未来》

近年来&#xff0c;我国电力建设投资额持续波动增长&#xff0c;至2023年底&#xff0c;全国电力工程投资总额高达14950亿元&#xff0c;同比增长22%。其中&#xff0c;电源工程建设和电网工程建设投资均达到新的高度。在这一背景下&#xff0c;电力行业对巡检工作的要求也日益…

苹果iOS/ iPadOS18 RC 版、17.7 RC版更新发布

iPhone 16 / Pro 系列新机发布后&#xff0c;苹果一同推出了 iOS 18 和 iPadOS 18 的 RC 版本&#xff0c;iOS 18 RC 的内部版本号为22A3354&#xff0c;本次更新距离上次发布 Beta/RC 间隔 12 天。 在 iOS 18 中&#xff0c;苹果给我们带来了 Apple Intelligence&#xff0c;这…

springboot高校兼职平台-计算机毕业设计源码65602

摘要 基于SpringBoot框架的高校兼职平台专注于为普通用户提供便捷的兼职信息服务。该平台包括普通用户功能、系统内容浏览、通知公告查看与论坛交流互动、兼职信息搜索与申请、个人中心管理和管理员权限管理等模块。利用SpringBoot框架实现了模块化开发和依赖注入&#xff0c;结…

驱动与应用的编译

无论是去驱动编译&#xff0c;还是应用编译&#xff0c;本质上都是用gcc这个工具&#xff0c;后面跟不同的参数来完成 驱动编译 放入内核编译 obj-y $(TARGET_SDK).o&#xff0c;就会直接将驱动编译成.o。供内核链接的时候&#xff0c;链接进整个内核镜像&#xff1b; obj-m…

Flutter自定义Icon的简易使用(两种)

方式一&#xff1a;利用第三方库&#xff08;建议&#xff09; 1、在阿里图标库(iconfont-阿里巴巴矢量图标库)上&#xff0c;加载购物车后&#xff0c;点击“下载素材”svg。 2、把下载的图片放入asstes目录下。​​​​​​​ 3、修改yaml配置文件&#xff0c;设置Icon图标所…