版权声明:作者已开启版权声明,如转载请注明转载地址。 https://blog.csdn.net/qq_34829447/article/details/84980659
计算机视觉加强之几何变换
一.图像几何变换概述
几何变换的实质就是矩阵的运算,根据矩阵的不同从而实现不同的变换
1.图片缩放
- imageInfo:图片宽、高、通道个数等
- 缩放
- 等比例缩放:宽高比不变
- 任意比例缩放:图片拉伸 非拉伸
2.图片剪切
- 根本思路:拿到图片矩阵中的数据,根据数据完成剪切【本质是对矩阵的操作】
3.图片位移
- 根本思路:根据矩阵实现图片的映射变化
4.图片镜像
- 实现步骤
- 创建一个足够大的画板
- 将一副图像分别从前向后、从后向前绘制
- 绘制中心分割线
5.仿射变换:位移 旋转 缩放
二.图片缩放实例
1.开发思路
- 拿到图片的原始数据(图片的加载)
- 获取图片的信息(图片的宽度、高度)
- 调用resize方法完成图片的缩放
- 检查最终的结果
2.实例代码
import cv2
img = cv2.imread('test.JPG',1)
imgInfo = img.shape
print(imgInfo)#打印图片的宽度 高度 颜色组成方式
height = imgInfo[0]
width = imgInfo[1]
mode = imgInfo[2]#颜色组成方式为3,表示一个像素点由3个基本颜色组成
#1.有放大和缩小两种情况
#2.根据比例有等比例缩放和非等比例缩放,与原图片的宽高比相同称为等比例
dstHeight = int(height*0.1)
dstWidth = int(width*0.1)
#在OpenCV中有四种常见的图片缩放方法
#1.最近领域插值
#2.双线性插值——我们采用
#3.像素关系重采样
#4.立方插值
dst = cv2.resize(img,(dstWidth,dstHeight))
cv2.imshow('image',dst)
cv2.waitKey(0)
3.最近邻域插值法与双线性插值法
-
目标图形上的点都来自于原图形
- 如
src 10*20 dst 5*10
dst <- src
(1,2) <- (2,4)
其中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 = 20% * 下 + 80%*上
- B1、B2 = 30% * 右 + 70%*左
- 计算方法一:最终点 = A1 * 70% + A2*20%
- 计算方法二:最终点 = B1 * 80% + B2*20%
4.源码实现最近邻域插值法图片缩放
-
实现步骤
- 获得图片info
- 创建空白模板
- 重设xy坐标
-
实例代码
import cv2 import numpy as np #使用numpy创建空白模板 #获得图片信息 img = cv2.imread("image0.jpg",1) imgInfo = img.shape #通过img.shape拿到当前图片的信息 height = imgInfo[0] width = imgInfo[1] dstHeight = int(height*0.1) dstWidth = int(width*0.1) #创建空白模板 dstImage = np.zeros((dstHeight,dstWidth,3),np.uint8) #np.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.开发思路
- x轴从100剪切到200
- y轴从100剪切到300
2.实例代码
import cv2
img = cv2.imread('image0.jpg',1)
imgInfo = img.shape
dst = img[100:200,100:300]#x轴值从100到200,y轴值从100到300
cv2.imshow('image',dst)
cv2.waitKey(0)
四.图片移位
1.开发思路
- 如何使用OpenCV API实现移位的功能
- 了解移位的算法原理
- 通过源码实现移位
2.实例代码
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的矩阵,float32表示32类型,水平方向上移动100个像素,垂直方向上移动200个像素
dst = cv2.warpAffine(img,matShift,(height,width)) #完成当前矩阵的映射,参数:原始图片的data信息;移位矩阵;图片的info信息
#完成矩阵的移位,实际是矩阵的运算
cv2.imshow('dst',dst)
cv2.waitKey(0)
3.图像移位的算法原理
- API级别的实现原理
- 将[1,0,100]和[0,1,200]拆分成2*2和2*1
- [[1,0],[0,1]] 2*2矩阵 定义为A
- [[100],[200]] 2*1矩阵 定义为B
- 输入的xy定义为C
- 当前的计算公式
A*C + B = [[1*x+0*y],[0*x+1*y]]+[[100],[200]] = [[x+100],[y+200]]
相当于沿着x轴右移100,沿着y轴下移200
- 基于像素级别的实现原理
- (10,20) -> (110,220)
4.源码实现图像位移
import cv2
import numpy as np
img = cv2.imread('image0.jpg',1)
cv2.imshow('src',img)
imgInfo = img.shape
dst = np.zeros(img.shape,np.uint8)
height = imgInfo[0]
width = imgInfo[1]
for r in range(0,height-200):
for j in range(0,width-100):
dst[i+200,j+100] = img[i,j] #表示总宽度不变,向右移动100;总高度不变,向下移动200
cv2.imshow('image',dst)
cv2.waitKey(0)
五.图片镜像
1.开发思路
- 完成图片的上下反转,每个像素点的x坐标不变,y坐标 = 高度*2-y初始高
- 创建画板,宽度一致,高度两倍,将图片从上到下绘制
- 绘制到中间时,将图片从后向前绘制
- 绘制中间的分割线
2.实例代码
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]#颜色深度,表示RGB3种颜色
newImageInfo = (height*2,width,deep)
dst = np.zeros(newImageInfo,np.uint8)
for i in range(0,height):
for j in range(0,width):
#绘制上半部分
dst[i,j] = img[i,j]
#绘制下半部分 x值不变,y变为高度的两倍-y-1
dst[height*2-i-1,j] = img[i,j]
#绘制中间线
for i in range(0,width):
dst[height,i] = (0,0,255)#当前颜色组成是BGR的形式
cv2.imshow('dst',dst)
cv2.waitKey(0)
六.图片缩放
1.回顾图片位移实现原理
- 定义矩阵
[[A1,A2,B1],[A3,A4,B2]]
- 拆分矩阵
[[A1,A2],[A3,A4]] [[B1],[B2]]
- 矩阵运算获得新的x坐标
newX = A1*x + A2*y +B1
- 矩阵运算获得新的y坐标
newY = A3*x + A4*y +B2
2.分析图片缩放实现原理
- 如缩放0.5
x->x*0.5 y->y*0.5
- 即
newX = 0.5*x ; newY = 0.5*y
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]
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)
七.图片的仿射变换
仿射变换就是原图片上的点按照新的规律映射到新的图片上,即求解新的x和新的y,通常情况下没有明确的公式进行计算,而是通过左上角左下角和右上角的点的拉伸实现对图片的仿射变换【三点确定唯一的平面】
1.开发思路
- 将原图上的三个点映射到目标图片上三个新的位置上[左上角,左下角,右上角]
2.实现代码
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]
#src 3个点 -> dst 3个点[左上,左下,右上]
#matSrc表示原始图片上的三个点
matSrc = np.float32([[0,0],[0,height-1],[width-1,0]])
#matDst表示对于matSrc上的三个点,在新的dst上的位置
matDst = np.float32([[50,50],[300,height-200],[width-300,100]])
#组合两个矩阵
matAffine = cv2.getAffineTransform(matSrc,matDst) #得到矩阵组合,本质上是一个mat,参数:src中左上角、左下角及右上角的矩阵;原来图片上三个点在dst上的位置
dst = cv2.warpAffine(img,matAffine,(width,height))
cv2.imshow('dst',dst)
cv2.waitKey(0)
八.图片旋转
1.开发思路
- 定义旋转矩阵,并初始化
- 调用仿射方法,完成仿射变换
2.实例代码
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]
#定义旋转矩阵,并初始化
matRotate = cv2.getRotationMatrix2D((height*0.5,width*0.5),45,0.5) #描述旋转矩阵,参数:旋转中心点;旋转角度;缩放的系数
#调用仿射方法,完成仿射变换
dst = cv2.warpAffine(img,matRotate,(width,height))
cv2.imshow('dst',dst)
cv2.waitKey(0)