【计算机视觉】OpenCV篇(3) - 图像几何变换(仿射变换/透视变换)

图像的几何变换从原理上看主要包括两种:基于2×3矩阵的仿射变换(平移、缩放、旋转和翻转等)、基于3×3矩阵的透视变换。

  •  仿射变换

基本的图像变换就是二维坐标的变换:从一种二维坐标(x,y)到另一种二维坐标(u,v)的线性变换:

如果写成矩阵的形式,那就是:

作如下定义:

矩阵T(2×3)就称为仿射变换的变换矩阵,R为线性变换矩阵,t为平移矩阵,简单来说,仿射变换就是线性变换+平移。变换后直线依然是直线,平行线依然是平行线,直线间的相对位置关系不变,因此非共线的三个对应点便可确定唯一的一个仿射变换,线性变换4个自由度+平移2个自由度→仿射变换自由度为6。

仿射变换在OpenCV中的实现如下:

import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('drawing.jpg')
rows, cols = img.shape[:2]# 变换前的三个点
pts1 = np.float32([[50, 65], [150, 65], [210, 210]])
# 变换后的三个点
pts2 = np.float32([[50, 100], [150, 65], [100, 250]])# 生成变换矩阵,维数:2*3
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))plt.subplot(121), plt.imshow(img), plt.title('input')
plt.subplot(122), plt.imshow(dst), plt.title('output')
plt.show()

 运行结果:

其实平移、旋转、缩放和翻转等变换就是对应了不同的仿射变换矩阵,下面分别来看:

 

(1)平移

平移就是x和y方向上的直接移动,可以上下/左右移动,自由度为2,变换矩阵可以表示为:

# 平移图片
import numpy as nprows, cols = img.shape[:2]# 定义平移矩阵,需要是numpy的float32类型
# x轴平移100,y轴平移50
M = np.float32([[1, 0, 100], [0, 1, 50]])
dst = cv2.warpAffine(img, M, (cols, rows))cv2.imshow('shift', dst)
cv2.waitKey(0)

 

  

 

 

 

(1)通过比例进行缩放

import cv2 as cv
import numpy as np# 图片缩放
img = cv.imread('images/animal.jpg', flags=1)  # flags=1读取为彩色,flags=0读取为灰度
cv.imshow('i', img)
h, w, channel = img.shape  # 以行列形式存储, 第几行到第几行为图像高度
dst_h = int(h*0.5)
dst_w = int(w*0.5)
# 最近邻域差值 双线性插值 像素关系重采样 立方差值
dst = cv.resize(img, (dst_w, dst_h))  # 默认双线性差值
cv.imshow('img', dst)
cv.waitKey(0)

OpenCV提供了resize函数来改变图像的大小,C++中的函数原型如下:

void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );

函数参数说明:

src:输入,原图像,即待改变大小的图像;

dst:输出,改变大小之后的图像,这个图像和原图像具有相同的内容,只是大小和原图像不一样而已;

dsize:输出图像的大小。如果这个参数不为0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为0,那么原图像缩放之后的大小就要通过下面的公式来计算:

dsize = Size(round(fx*src.cols), round(fy*src.rows))

其中,fx和fy就是下面要说的两个参数,是图像width方向和height方向的缩放比例。

fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;

fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;

interpolation:这个是指定插值的方式,图像缩放之后,肯定像素要进行重新计算的,就靠这个参数来指定重新计算像素的方式,有以下几种:

  • INTER_NEAREST - 最邻近插值
  • INTER_LINEAR - 双线性插值,如果最后一个参数你不指定,默认使用这种方法
  • INTER_AREA - resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
  • INTER_CUBIC - 4x4像素邻域内的双立方插值
  • INTER_LANCZOS4 - 8x8像素邻域内的Lanczos插值

函数使用说明:

  1. dsize和fx/fy不能同时为0,要么你就指定好dsize的值,让fx和fy空置直接使用默认值,就像resize(img, imgDst, Size(30,30)); 要么你就让dsize为0,指定好fx和fy的值,比如fx=fy=0.5,那么就相当于把原图两个方向缩小一倍!
  2. 至于最后的插值方法,正常情况下使用默认的双线性插值就够用了。几种常用方法的效率是:最邻近插值>双线性插值>双立方插值>Lanczos插值;但是效率和效果成反比,所以根据自己的情况酌情使用。
  3. 正常情况下,在使用之前dst图像的大小和类型都是不知道的,类型从src图像继承而来,大小也是从原图像根据参数计算出来。但是如果你事先已经指定好dst图像的大小,那么你可以通过下面这种方式来调用函数:
resize(src, dst, dst.size(), 0, 0, interpolation);

 

(2)通过矩阵变换进行缩放  

import cv2 as cv
import numpy as np# 图片缩放
img = cv.imread('../images/moon.jpg', flags=1)  # flags=1读取为彩色,flags=0读取为灰度
h, w = img.shape[:2]
mat_shift = np.float32([[0.5, 0, 0], [0, 0.5, 0]])  # 缩放矩阵
dst = cv.warpAffine(img, mat_shift, (int(w/2), int(h/2)))
cv.imshow('img1', img)
cv.imshow('img2', dst)
cv.waitKey(0)

 

 

转载于:https://www.cnblogs.com/carsonzhu/p/10763438.html

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

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

相关文章

OpenCL 与 CUDA

根据网站资料,简单地汇编一下CUDA与OpenCL的区别。如有错误请指出。 题外话: 美国Sandia国家实验室一项模拟测试证明:由于存储机制和内存带宽的限制,16核、32核甚至64核处理器对于超级计算机来说,不仅不能带来性能提升…

Eclipse4JavaEE安装SpringBoot

第一步:下载SpringBoot SpringBoot官网下载链接 第二步:在Eclipse里进行安装 打开Eclipse,菜单栏Help -》Install New Software,进入下图界面,点击Add 设置Name和Location,Name看自己喜好,Locat…

从零开始玩转 logback、完整配置详解

官网地址:https://logback.qos.ch/manual/index.html 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 概述 LogBack是一个日志框架,它与Log4j可以说是同出一源&a…

ActiveMQ_Windows版本的安装部署

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 1, 保证电脑上安装了jdk6以上版本的java,并配置了好环境变量 ; 2, 官方下载地址:http://activemq.a…

如何将markdown转换为wxml

话说我要为技术博客写一个小程序版,我的博客解决方案是 hexo github-page,格式当然是技术控们喜欢的 markdown 了 。但小程序使用的却是独有的模版语言 WXML。我总不能把之前的文章手动转换成小程序的 wxml 格式吧,而网上也没完善的转换库&a…

巧妙喝水打败多种疾病

喝水,我们每天都会做的一件事,殊不知,喝水得当能打败多种疾病问题! 方法/步骤 一、很多人都听说过早晨喝一杯水对身体有好处,有人喝盐水?有人喝蜂蜜水?还有人为了美白喝柠檬水?到底喝什么水最好呢?人体经过了一宿的代谢&…

git 几个commit点合并成一个commit点

在用git做版本控制器的时候,经常会遇到以下情况: 1、在做1个功能的时候,你自己觉得代码没问题了,就本地commit,然后提交代码,在gitlab上发起和并请求,老大看完之后,觉得你还有修改的…

深入浅出 消息队列 ActiveMQ

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 一、 概述与介绍 ActiveMQ 是Apache出品,最流行的、功能强大的即时通讯和集成模式的开源服务器。ActiveMQ 是一个完全支持JM…

2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) - 4.28

赛后补了几道 赛中我就写了两个... A - Altruistic AmphibiansGym - 101933A 看了眼榜没几个人做。就没看。 最后发现就是一个DP(但是我觉得复杂度有点迷) 题意:$n$只青蛙有参数$l,w,h$分别表示弹跳力,体重,身高&#…

消息队列技术介绍 : ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ

一、 消息队列概述 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可…

python爬虫学习之页面登陆

爬虫学习的一点心得 登陆主要有3种方法:使用selenium,cookies,模拟表单登陆 个人对于一般情况使用cookies登陆 可以实现一次手动,长期自动,可以绕过登陆(登陆的相关信息密码,账号等会存于cookie…

消息队列 应用场景 解析

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 另外腾讯云-云社区还有一文不允许转载,但内容挺好的:https://cloud.tencent.com/developer/article/1006035 分布…

利用memcached实现CAS单点登录集群部署

前言:利用memcached实现CAS单点登录集群部署 负载均衡:将接口请求的有状态性变成无状态性。是我们在实现负载均衡时必要要解决的问题。以应用接口的session状态为例,一般解决方法都是将session数据和应用进行剥离,session数据统一…

分布式开放消息系统 ( RocketMQ ) 的原理与实践

分布式消息系统作为实现分布式系统可扩展、可伸缩性的关键组件,需要具有高吞吐量、高可用等特点。而谈到消息系统的设计,就回避不了两个问题: 消息的顺序问题消息的重复问题RocketMQ作为阿里开源的一款高性能、高吞吐量的消息中间件&#xff…

数据结构02-链表

说明:由于该数据结构是由java并且是原生实现,所以与C有一些出入,不过原理是相同的 1.链表的定义 为了表示线性表元素a与a1的逻辑关系,存储数据时,除了存储元素本身的信息之外,还存储了直接后继元素的位置信…

洛谷P2347 砝码称重 某一年noip提高组原题

可以转化为01背包求方案数的问题&#xff0c;dp数组f[][]表示第几个砝码能称出的重量,可压缩至一维 转移方程为f(i,j)f(i-1,j-w[i]) 当前我们可以称出的重量必定是由之前的砝码重量转移过来的 #include<bits/stdc.h> using namespace std; const int N550; const int max…

linux 下载、安装 maven

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 创建maven的文件夹并下载maven的tar包到此文件夹中 //进入一个目录 cd /usr/local//创建一个文件夹 mkdir maven//下载maven的tar包…

c# 编程学习(二)

2019独角兽企业重金招聘Python工程师标准>>> 标识符是对程序中的各个元素进行标识的名称。  只能使用字母(大写和小写)、数字和下划线  标识符必须以字母或下划线开头 变量是容纳值的存储位置。可将变量想象成容纳临时信息的容器 命名变量的建议&#xff1a; …

深入理解C++ 虚函数表

目录 深入理解C 虚函数表虚函数表概述单继承下的虚函数表派生类未覆盖基类虚函数派生类覆盖基类虚函数多继承下的虚函数表无虚函数覆盖派生类覆盖基类虚函数钻石型虚继承总结几个原则安全性问题深入理解C 虚函数表 ​ C中的虚函数的作用主要是实现了多态的机制。关于多态&#…

Bootstrap简介

1.使用准备 1.1 Bootstrap的下载 http://www.bootcss.com&#xff0c;下载用于生产环境的Bootstrap即可。 1.2 Bootstrap包含的内容 ● 全局CSS&#xff1a;基本的 HTML 元素均可以通过 class 设置样式并得到增强效果&#xff1b;还有先进的栅格系统。 ● 组件&#xff1a;无数…