计算机视觉之几何变换(实现图片缩放、剪切、移位、镜像、仿射变换、旋转等功能)

1.图片的缩放

图片是由许多基本的像素点组成的,一般来说彩色图像中的像素点由三个数值组成,分别是蓝色分量、红色分量和绿色分量。

图片缩放分为:

  1. 普通的缩放,即确定下缩放后的尺寸大小,再进行缩放。
  2. 等比例缩放,即确定一个比例系数,长宽都乘以一个相同的比例系数,实现等比例缩放。

一般来说,图片的缩放方法有:

  1. 最近临域插值
  2. 双线性插值(默认情况)
  3. 像素关系重采样
  4. 立方插值

下面简单实现等比例缩放,用最近领域插值方法实现,测试代码如下:

 1 # encoding:utf-8
 2 # 基本实现步骤:
 3 # 1 load 读取图片
 4 # 2 info 获取图片信息
 5 # 3 resize 实现图片缩放即改变图片大小
 6 # 4 check 展示操作后的图像
 7 import cv2
 8 img = cv2.imread('image0.jpg', 1)
 9 # 图片的大小
10 imgInfo = img.shape
11 print(imgInfo)
12 height = imgInfo[0]
13 width = imgInfo[1]
14 mode = imgInfo[2]  # 为3 表示一个像素点由三个数值组成
15 cv2.imshow('src', img)
16 # 1 放大 缩小
17 # 2 等比例缩放 宽高比不变即为等比例缩放
18 # 等比例缩放 长宽乘以一个相同的系数
19 dstHeight = int(height*0.5)
20 dstWidth = int(width*0.5)
21 # 非等比例缩放
22 # dstHeight = 500
23 # dstWidth = 500
24 # 缩放方法:最近临域插值 双线性插值(默认情况) 像素关系重采样 立方插值
25 dst = cv2.resize(img, (dstWidth, dstHeight))
26 cv2.imshow('image', dst)
27 cv2.waitKey(0)

运行效果如下:(src为原始图像,dst为目标图像即缩放后的图像)

原始图像:

 缩放后的图像:

下面简单的说下最近临域插值的双线性插值(默认情况)的原理:

 1 # 原图像src 10*20 目标图像dst 5*10
 2 # src-->dst
 3 # (2,4)-->(1,2)
 4 # 计算公式 dst x 1 -> src x 2 newX
 5 # newX=x*(src的行/dst的行) newX=1*(10/5)=2
 6 # newY=y*(src的列/目标的列) newY=2*(20/10)=4
 7 # 12.3 = 12 最近领域插值法 取最近的整数
 8 #
 9 # 双线性插值法
10 # A1=20% 上+ 80% 下 A2
11 # B1=30% 左+ 70% 右 B2
12 # 1 最终点 = A1 30% + A2 70%
13 # 2 最终点 = B1 20% + B2 80%

简单的实现下最近领域插值算法,测试代码如下:

 1 # 最近临域插值算法代码实现
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 imgInfo = img.shape
 6 height = imgInfo[0]
 7 width = imgInfo[1]
 8 dstHeight = int(height/3)
 9 dstWidth = int(width/2)
10 dstImage = np.zeros((dstHeight, dstWidth, 3), np.uint8)  # 0-255 创建一个空白模版
11 for i in range(0, dstHeight):  #
12     for j in range(0, dstWidth):  #
13         iNew = int(i*(height*1.0/dstHeight))
14         jNew = int(j*(width*1.0/dstWidth))
15         dstImage[i, j] = img[iNew, jNew]
16 cv2.imshow('dst', dstImage)
17 cv2.waitKey(0)

运行结果如下:(即展示缩放后的图像)

图像的缩放再测试,代码如下:

 1 # 图片缩放
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 cv2.imshow('src', img)
 6 imgInfo = img.shape
 7 height = imgInfo[0]
 8 width = imgInfo[1]
 9 matScale = np.float32([[0.5, 0, 0], [0, 0.5, 0]])
10 dst = cv2.warpAffine(img,matScale,(int(width/2),int(height/2)))
11 cv2.imshow('dst',dst)
12 cv2.waitKey(0)

运行结果如下:(src为初始图像,dst为目标图像)

src初始图像:

dst缩放后的图像:

2.图片的剪切

图片剪切的大致原理,按照我的理解就是:确定两个点,连接两个的线段即为剪切矩阵的对角线,通过这两个的坐标,就可以确定需要剪切的矩阵的方位以及矩阵大小。

更通俗一点的理解就是,你在用QQ截图的时候,总是先点一个起始点,最后再点一个终止点,最后形成一个矩阵,最后再输出这个矩阵中所有的像素值,即为剪切后的图片。

图片的剪切,测试代码如下:

1 # 实现图片的剪切
2 import cv2
3 img = cv2.imread('image0.jpg', 1)
4 cv2.imshow('src', img)
5 imgInfo = img.shape
6 # dst = img[100:500, 200:500]
7 dst = img[100:400, 100:500]  # 前面是纵向的范围 后面的是横向的范围
8 cv2.imshow('image', dst)
9 cv2.waitKey(0)

运行结果如下:(src为原始图像,image为目标图像)

src原始图像:

image剪切后的图像:(剪了一朵大发发)

 3.图片的移位

通过api调用实现图片的移位,测试代码如下:

 1 # 通过api调用实现图片的移位
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 imgInfo = img.shape
 6 height = imgInfo[0]
 7 width = imgInfo[1]
 8 img = cv2.resize(img,(int(height*0.5),int(width*0.5)))  # 原始图像长宽缩小一半
 9 cv2.imshow('src', img)
10 # 移位矩阵
11 matShift = np.float32([[1,0,50],[0,1,100]])  # 第一个移位矩阵
12 matShift2 = np.float32([[1,0,200],[0,1,100]])  # 第二个移位矩阵
13 # 目标矩阵
14 dst = cv2.warpAffine(img,matShift,(height,width-200))  # 第一个目标矩阵
15 dst2 = cv2.warpAffine(img,matShift2,(height,width-200))  # 第二个目标矩阵
16 # 展示两个目标图像
17 cv2.imshow('dst',dst)
18 cv2.imshow('dst2',dst2)
19 cv2.waitKey(0)

运行结果如下:(src为测试图像,dst为第一个移位后的图像,dst2为第二个移位后的图像)

src测试图像:

dst第一个移位图像:

dst2第二个移位图像:

自行实现图片向右移动100个像素,测试代码如下:

 1 # 自行实现图片向右移动100个像素
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.5)))
 6 cv2.imshow('src',img)
 7 imgInfo = img.shape
 8 height = imgInfo[0]
 9 width = imgInfo[1]
10 dst = np.zeros(img.shape,np.uint8)
11 for i in range(0,height):
12     for j in range(0,width-100):
13         dst[i,j+100]=img[i,j]
14 cv2.imshow('image',dst)
15 cv2.waitKey(0)

运行结果如下:(src为原始图像,image为移位后的图像)

src原始图像:

image移位后的图像:

 4.图片镜像

图像镜像的实现步骤是:

  1. 先创建一个最够大的画板,能够“装得下”镜像化之后的图像
  2. 然后再将该图像分别从前向后、从后向前绘制
  3. 最后绘制中心分割线

测试代码如下:

 1 import cv2
 2 import numpy as np
 3 img = cv2.imread('image0.jpg', 1)
 4 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.3)))
 5 cv2.imshow('src', img)
 6 imgInfo = img.shape
 7 height = imgInfo[0]
 8 width = imgInfo[1]
 9 deep = imgInfo[2]
10 newImgInfo = (height*2, width, deep)
11 dst = np.zeros(newImgInfo, np.uint8)
12 for i in range(0, height):
13     for j in range(0, width):
14         dst[i, j] = img[i, j]
15         # x y = 2*j - y- 1
16         dst[height*2-i-1, j] = img[i, j]
17 for i in range(0, width):
18     dst[height, i] = (0, 0, 255)
19 cv2.imshow('image', dst)
20 cv2.waitKey(0)

运行结果如下:(src为初始图像,image为镜像后的图像)

src初始图像:

image镜像后的图像:

5.图片的放射变换

放射变换融合了如下几点:

  • 位移
  • 旋转
  • 缩放

 测试代码如下:

 1 # 仿射变换:位移 旋转 缩放
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 cv2.imshow('src', img)
 6 imgInfo = img.shape
 7 height = imgInfo[0]
 8 width = imgInfo[1]
 9 # src 3->dst 3 (左上角 左下角 右上角)
10 matSrc = np.float32([[0,0],[0,height-1],[width-1,0]])
11 matDst = np.float32([[50,50],[300,height-200],[width-300,100]])
12 # 组合
13 matAffine = cv2.getAffineTransform(matSrc,matDst)
14 dst = cv2.warpAffine(img,matAffine,(width,height))
15 cv2.imshow('dst',dst)
16 cv2.waitKey(0)

运行结果如下:(src为初始图像,dst为目标图像)

src初始图像:

dst目标图像:

6.图片的旋转

 调用api实现图片的旋转,测试代码如下:(主要有三个参数,旋转中心的坐标、旋转角度以及缩放系数(至于为什么有缩放系数,因为旋转的时候可能会触碰到图像矩阵框的边缘,所以需要缩放处理))

 1 # 图片旋转
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.5)))
 6 cv2.imshow('src', img)
 7 imgInfo = img.shape
 8 height = imgInfo[0]
 9 width = imgInfo[1]
10 # 得到旋转矩阵 center angle sc 中心点 角度 缩放系数
11 matRotate = cv2.getRotationMatrix2D((height*0.5,width*0.5),45,0.7)
12 dst = cv2.warpAffine(img,matRotate,(height,int(width*1.5)))
13 cv2.imshow('image',dst)
14 cv2.waitKey(0)

运行效果如下:(src为初始图像,image为目标图像)

src初始图像:

image目标图像:

 暂时先记下这么多,还有的话再更新。。。

posted @ 2019-05-20 17:35  wydxry  阅读(2864)  评论(0编辑  收藏  举报
Live2D