博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【计算机视觉】OpenCV篇(3) - 图像几何变换(仿射变换/透视变换)
阅读量:6719 次
发布时间:2019-06-25

本文共 3137 字,大约阅读时间需要 10 分钟。

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

  •  仿射变换

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

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

作如下定义:

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

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

import cv2import numpy as npimport 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*3M = 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轴平移50M = 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 cvimport 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 cvimport 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

你可能感兴趣的文章
快速配置oralce11g安装环境脚本
查看>>
int.Parse
查看>>
光纤跳线
查看>>
day02:管道符、shell及环境变量
查看>>
php设计模式——适配器模式
查看>>
C#文件、文件夹操作
查看>>
MySQL编译安装加入service
查看>>
以rsync进行同步镜像备份
查看>>
热烈祝贺VMware View4.5荣获“2010年度最佳产品”大奖
查看>>
ORACLE 11G 中表空间传输 TransportableTablespace
查看>>
自动化1
查看>>
Jenkins 2.32.3参数化构建maven项目
查看>>
使用Oracle存储过程批量生成测试数据
查看>>
正则表达式 - ×××
查看>>
Target runtime Apache Tomcat v6.0 is not defined
查看>>
.net密码找回
查看>>
安装mysql遇到的问题
查看>>
我的友情链接
查看>>
大道至简--GoEasy推送
查看>>
免费邮箱服务器(收藏)
查看>>