计算机视觉加强之几何变换

本文详细介绍了在OpenCV中实现图像的几何变换,包括图片缩放、剪切、移位、镜像翻转、利用矩阵移位缩放、仿射变换及旋转。通过实例代码展示了各种变换的效果,并强调了理解矩阵运算在几何变换中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇笔记的运行环境为:windows下配置好opencv3.1.0和tensorflow1.2.1环境的python3.5.4编辑器pycharm。(ps:没用到tensorflow所以可以忽略)

1. 图片缩放

即改变图片的高度与宽度
1.加载 2.获取图片信息 3.调用resize方法改变大小 4.检查改变的结果
图片缩放的形式可以分为:放大,缩小
根据图片缩放的比例,可以分为等比例和非等比例
非等比例缩放:宽高比与原图片不一致
opencv中提供的四种常见图片缩放方法:
1.最近邻域插值 2.双线性插值 3.像素关系重采样 4.立方插值
默认情况下使用双线性插值。

# 1 load  2.info  3.resize  4.check
import cv2 #导入opencv
img = cv2.imread("image0.jpg",1) #imread方法参数:图片的名称 1表示获取彩色图片
#cv2.imshow('image0',img)
imginfo = img.shape #图片的宽度,高度以及图片的颜色组成方式,返回值是一个元组
#print(imginfo)
height = imginfo[0] #获取当前图片的高度
width = imginfo[1] #获取当前图片的宽度
mode = imginfo[2] #图片的颜色组成方式
#  1 放大 缩小  2  等比例,非等比例   2:3
dstHeight = int(height*0.5) #目标的高度信息,并转化成int类型
dstWidth = int(width*0.5) #目标的宽度信息,并转化成int类型
# 最近邻域插值  双线性插值  像素关系重采样  立方插值
dst = cv2.resize(img,(dstWidth,dstHeight)) #定义最终生成的图片
                            # resize方法参数:原始图片的名称,最终我们要生成的图片的宽度,高度信息

cv2.imshow('image',dst) #imshow参数:显示窗口的名称 将要打开的图片名称
cv2.waitKey(0)

最近邻域插值法和双线性插值法的原理和实现
最近邻域插值法:
原图像大小为1020,目标图像的大小为510
原图像上的(2,4)->目标图像上的(1,2)
dst x 1 ->src x 2 newX
newX = x*(src 行/目标 行)newX=1*(10/5)=2
newY = y*(src 列/目标 列) newY = 2*(20/10)=4
若计算结果不是整数,那么取最靠近的那个整数为结果 12.3->12
双线性插值法:
在这里插入图片描述
操作流程:先将目标点在水平方向上投影:黄线与蓝线交于两点A1,A2;
然后将目标点在竖直方向上投影:绿线与蓝线相较于两点B1,B2;
在这里插入图片描述
A1,A2,B1,B2四个点的坐标计算:
A1 = 20%上 +80%下 A2
B1 = 30%左+70%右 B2
最终点1 = A1 30%+A2 70% 或 2 = B1* 20% + B2* 80%**

代码实现:

#1 info 2.空白模板 3.计算xy的坐标值
import cv2
import numpy as np
img = cv2.imread('image0.jpg',1)
cv2.imshow('img',img)
imginfo = img.shape
height = imginfo[0]
width = imginfo[1]
dstHeight = int(height*0.5)
dstWidth = int(width*0.5)
dstImage = np.zeros((dstHeight,dstWidth,3),np.uint8) #uint8的取值范围是0-255
for i in range(0,dstHeight):#行
    for j in range(0,dstWidth):# 列
        iNew = int(i*(height*1.0/dstHeight))
        jNew = int(j*(width*1.0/dstWidth))
        dstImage[i,j] = img[iNew,jNew]
cv2.imshow('dst',dstImage)
cv2.waitKey(0)

运行效果图(左边为原图片,右边为缩放过的图片)
在这里插入图片描述
学习图片缩放的总结:
1.学习opencv中api的调用
2.学习api的算法原理
3.源码实现

2.图片剪切

将图片的一部分剪切出来自成一图
1.了解想要剪切的位置在原图片中的位置
2.找到原图片中需要剪切的位置,对其进行矩阵操作
3.生成目标图片
源代码:

# x轴 100->200
# y轴 100->300
import cv2
img = cv2.imread('image0.jpg',1)
cv2.imshow('img',img)
imgInfo = img.shape
dst = img[100:200,100:300]
cv2.imshow('dst',dst)
cv2.waitKey(0)

运行效果(左边原图片右边目标图片):
在这里插入图片描述

3.图片的移位

1.opencv的api
2.算法原理
3.源码实现
调用opencvAPI实现的代码:

# 1 API 2.算法原理 3.源码实现
import cv2
import numpy as np
img = cv2.imread('image0.jpg',1) #图片的读取
cv2.imshow('src',img)
imgInfo = img.shape
height = imgInfo[0]
width  = imgInfo[1]
######
matShift = np.float32([[1,0,100],[0,1,200]]) #设置移位矩阵   2*3的矩阵
dst = cv2.warpAffine(img,matShift,(height,width))#参数:原始图片的data信息  移位矩阵 图片info信息
#函数功能:完成当前图片移位(矩阵的运算)
cv2.imshow('dst',dst)
cv2.waitKey(0)

效果图:
在这里插入图片描述
图像位移的算法原理:
1.API的算法原理 :
偏移矩阵:[1,0,100],[0,1,200] 将该2行三列的矩阵拆分为一个22的矩阵 和一个21的矩阵
22: [[1,0],[0,1]] 定义为A
2
1: [[100],[200]] 定义为B
将每个坐标xy定义为C(2* 1)
AC +B = [[1 x+0* y],[0* x+1* y]]+[[100],[200]]
= [[x+100],[y+200]]
2.像素级别的原理:
(10,20)->(110,120)
源码实现图片位移:

# 1 API 2.算法原理 3.源码实现
import cv2
import numpy as np
img = cv2.imread('image0.jpg',1) #图片的读取
cv2.imshow('src',img)
imgInfo = img.shape
height = imgInfo[0]
width  = imgInfo[1]
dst = np.zeros(img.shape,np.uint8)
height = imgInfo[0]
width = imgInfo[1]
for i in range(0,height):
    for j in range(0,width-100):
        dst[i,j+100]= img[i,j]
cv2.imshow('dst',dst)
cv2.waitKey(0)

效果(图片向右移动了100像素):
在这里插入图片描述

4.图片的镜像翻转

实现步骤:
1 创建一个足够大的“画板”
2.将一幅图片分别从前向后,从后向前绘制
3.绘制中心分割线
源码显示:

import cv2
import numpy as np
img = cv2.imread('image0.jpg',1) #图片的读取
cv2.imshow('src',img)
imgInfo = img.shape
height = imgInfo[0]
width  = imgInfo[1]
deep = imgInfo[2]
newImgInfo = (height*2,width,deep)
dst = np.zeros(newImgInfo,np.uint8)
for i in range(0,height):
    for j in range(0,width):
        dst[i,j]= img[i,j]
        #x 不变 y=2*h - y -1
        dst[height*2-i-1][j]=img[i,j]
for i in range(0,width):
    dst[height,i]=(0,0,255)
cv2.imshow('dst',dst)
cv2.waitKey(0)


效果展示:
在这里插入图片描述

5.利用矩阵移位实现图像的缩放

首先复习一下矩阵移位的算法原理:
首先定义一个2* 3的矩阵[[A1,A2,B1],[A3,A4,B2]]
接着将该矩阵拆分成两个矩阵:2* 2 [[A1,A2],[A3,A4]] 和 2* 1 [[B1],[B2]]
newX = A1* x +A2* y+B1
newY = A3* x +A4* y+B2
要想实现缩放功能,x->x* 0.5 y->y* 0.5
newX = 0.5* x
newY = 0.5* y
源码展示:

import cv2
import numpy as np
img = cv2.imread('image0.jpg',1)
cv2.imshow('img',img)
imginfo = img.shape
height = imginfo[0]
width = imginfo[1]
matScale = np.float32([[0.5,0,0],[0,0.5,0]])
dst = cv2.warpAffine(img,matScale,(int(width/2),int(height/2))) #仿射方法 参数为:原始图像信息
                                                        # 位移矩阵  宽高信息
cv2.imshow('dst',dst)
cv2.waitKey(0)

效果图:

在这里插入图片描述

6.图片的仿射变换

将图片上的每一个点映射到新的位置上,实际上就是求解新的x和新的y的过程。这和我们之前讲的矩阵变换十分相似。只不过,与其他变换不同的是,使用这种方式来进行仿射变换,是没有一个明确的公式来进行计算,而是通过图片上三个点的拉伸来重新映射出一个新的x和一个新的y。比如,我们可以通过确定左上角,左下角,右上角点的位置,通过这三个点的拉伸来对图片进行仿射变换。
在这里插入图片描述
原理:两点可以确定唯一的一条直线,三点可以确定唯一的一个平面。
仿射变换的实质就是把原图像上的三个点映射到新的位置上。
功能实现:

import cv2
import numpy as np
img = cv2.imread('image0.jpg',1)
cv2.imshow('img',img)
imginfo = img.shape
height = imginfo[0]
width = imginfo[1]
matSrc = np.float32([[0,0],[0,height-1],[width-1,0]]) #表示原图像上左上角,左下角,右上角的位置信息
matDst = np.float32([[50,50],[300,height-200],[width-300,100]]) #这三个点在目标图像上的位置信息
#组合
#定义一个仿射变换矩阵
matfAffine = cv2.getAffineTransform(matSrc,matDst)  #该方法得到的是一个矩阵组合
                            #本质上获取的是一个mat,参数:原图片上三个点的位置  目标图片上三个点的位置
dst = cv2.warpAffine(img,matfAffine,(width,height))
cv2.imshow('dst',dst)
cv2.waitKey(0)

效果图:
在这里插入图片描述

7.图片的旋转

代码:

import cv2
import numpy as np

img = cv2.imread('image0.jpg', 1)
cv2.imshow('img', img)
imginfo = img.shape
height = imginfo[0]
width = imginfo[1]
# Rotate
matRotate = cv2.getRotationMatrix2D((height*0.5,width*0.5),45,0.5)  # 该方法作用:得到一个旋转矩阵  参数;旋转的中心点,旋转的角度 缩放的系数
# 为什么旋转要进行缩放?
#假设有一个图片的大小是100*100,将其旋转25度之后,它的四个角就会超出显示的范围
#为了便于展示旋转之后的完整图片,我们还是设置了缩放参数
dst = cv2.warpAffine(img,matRotate,(width,height))
cv2.imshow('dst',dst)
cv2.waitKey(0)

效果图:
在这里插入图片描述

全部总结

本次笔记主要是总结了opencv中的常用图片几何变换功能,主要包括图片的缩放,图片的剪切,位移,镜像,旋转。最后还介绍了仿射变换并将其应用在了位移,旋转,缩放上。
几何变换的实质就是矩阵的运算,根据不同的矩阵运算,我们能够使原图片变成不同的形状,这点我就觉得学习好线性代数是非常重要的~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值