3 计算机视觉入门之OpenCV
3-1 本章介绍
图片的几何变换:
- 图片缩放
- 图片剪切
- 图片位移
- 图片镜像
- 图片仿射变换
3-2 图片缩放1
图片缩放分为下面两种:
- 等比例缩放:宽高比不变
- 任意比例缩放:图片拉伸 非拉伸
具体的缩放代码如下:
import cv2
img = cv2.imread('11.jpg', 1)
imgInfo = img.shape
print(imgInfo) # (287, 450, 3)
cv2.imshow('img', img)
height = imgInfo[0]
weight = imgInfo[1]
mode = imgInfo[2]
dstHeight = int(height * 0.5)
dstWeight = int(weight * 0.5)
print(dstHeight, dstWeight)
# 常用的插值法有最近临域插值 双线性插值 像素关系重采样 立方插值
# 这里使用的是双线性插值
dst = cv2.resize(img, (dstWeight, dstHeight))
cv2.imshow('dst', dst)
cv2.waitKey(0)
代码运行结果如下:
3-3 图片缩放2
双线性插值法(视频里面讲反了,距离越近,权重越大,距离越远,权重越小):
# 最近临域插值 双线性插值 原理
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 = 20% 上+80%下 A2
B1 = 30% 左+70%右 B2
1 最终点 = A1 30% + A2 70%
2 最终点 = B1 20% + B2 80%
# 实质:矩阵运算
3-4 图片缩放3
代码如下:
import cv2
import numpy as np
img = cv2.imread('01.jpg', 1)
imgImg = img.shape
cv2.imshow('img', img)
height = imgImg[0]
weight = imgImg[1]
dstHeight = int(height / 2)
dstWeight = int(weight / 2)
dstImage = np.zeros((dstHeight, dstWeight, 3), np.uint8) # 0-255
for i in range(0, dstHeight): # 行
for j in range(0, dstWeight): # 列
iNew = int(i * (height * 1.0 / dstHeight)) # 这里直接i*2不就行了么,为什么这么复杂,搞不懂
jNew = int(j * (weight * 1.0 / dstWeight))
dstImage[i, j] = img[iNew, jNew]
cv2.imshow('dst1', dstImage)
cv2.imshow('dst2', dstImage)
cv2.waitKey(0)
运行结果如下:
3-5 图片剪切
图片剪切可以剪切出自己感兴趣的部分。
比如以下代码:
import cv2
img = cv2.imread('04.jpg')
cv2.imshow('img', img)
imgInfo = img.shape
roi = img[50:250, 350:550]
cv2.imshow('roi', roi)
cv2.waitKey(0)
运行结果如下:
怎么样?是不是很不错,可以裁剪出自己感兴趣的部分。
3-6 图片位移1
图片位移说白了就是将图片进行位置偏移。
代码如下:
# 1.API 2.算法原理 3.源代码
import cv2
import numpy as np
img = cv2.imread('09.jpg')
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
weight = imgInfo[1]
matShift = np.float32([[1, 0, 50], [0, 1, 50]])
dst = cv2.warpAffine(img, matShift, (height, weight)) # 1.data 2.mat 3.info
# 移位 矩阵
cv2.imshow('dst', dst)
cv2.waitKey(0)
运行结果如下:
3-7 图片移位2
[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]]
(10,20)->(110,120)
3-8 图片移位3
代码如下:
import cv2
import numpy as np
img = cv2.imread('07.jpg')
cv2.imshow('img', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros(img.shape, np.uint8)
for i in range(0, height):
for j in range(0, width - 100):
dst[i, j + 100] = img[i, j]
cv2.imshow('image', dst)
cv2.waitKey(0)
运行结果如下:
3-9 图片镜像
实现步骤:
- 创建一个足够大的“花板”
- 将一副图像分别从前向后、从后向前绘制
- 绘制中心分割线
代码如下:
import cv2
import numpy as np
img = cv2.imread('08.jpg')
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
mode = imgInfo[2]
newImgInfo = (height * 2, width, mode)
dst = np.zeros(newImgInfo, np.uint8)
for i in range(0, height): # 高==列
for j in range(0, width): # 宽==行
dst[i, j] = img[i, j] # 将原图像放到目标图
dst[height * 2 - i - 1, j] = img[i, j] # 将原图像一点点放到备份的图像
for i in range(0, width):
dst[height, i] = (255, 0, 0)
cv2.imshow('dst', dst)
cv2.waitKey(0)
运行结果如下:
3-10 图片缩放
代码如下:
# [[A1 A2 B1],[A3 A4 B2]]
# [[A1 A2],[A3 A4]] [[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
import cv2
import numpy as np
img = cv2.imread('05.jpg', 1)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
# np.float32中前两个数字表示宽高的缩放比,第三个表示偏移量
matScale = np.float32([[0.5, 0, 20], [0, 0.5, 30]])
# 第一个参数是原始图像数据,第二个参数是缩放矩阵,第三个参数是目标图片的宽高信息
dst = cv2.warpAffine(img, matScale, (int(width * 5 / 10), int(height * 5 / 10)))
cv2.imshow('dst', dst)
cv2.waitKey(0)
运行结果如下:
3-11 图片仿射变换
仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。仿射变换需要一个M矩阵,但是由于仿射变换比较复杂,一般直接找很难找到这个矩阵,opencv提供了根据变换前后三个点的对应关系来自动求解M的函数,这个函数就是:
matAffine = cv2.getAffineTransform(matSrc, matDst)
其中,
- matSrc:原始图像中的三个点的坐标
- matDst:变换后的这三个点对应的坐标
- matAffine :根据三个对应点求出的仿射变换矩阵
然后再使用函数cv2.warpAffine()利用得到的M对原始图像进行变换即可
代码如下:
import cv2
import numpy as np
img = cv2.imread('03.jpg', cv2.IMREAD_UNCHANGED)
cv2.imshow('src', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
# src 3 -> dst 3 (左上角、左下角、右上角)
matSrc = np.float32([[0, 0], [0, height - 1], [width - 1, 0]])
matDst = np.float32([[50, 50], [100, height - 100], [width - 100, 100]])
# 组合
matAffine = cv2.getAffineTransform(matSrc, matDst)
dst = cv2.warpAffine(img, matAffine, (width, height))
cv2.imshow('dst', dst)
cv2.waitKey(0)
运行结果如下:
3-12 图片旋转
代码如下:
import cv2
import numpy as np
img = cv2.imread('04.jpg', cv2.IMREAD_UNCHANGED)
cv2.imshow('img', img)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
# mat rotate:1.center 2.angle 3.scale
matRotate = cv2.getRotationMatrix2D((height * 0.5, width * 0.5), 30, 1)
dst = cv2.warpAffine(img, matRotate, (height, width))
cv2.imshow('dst', dst)
cv2.waitKey(0)
运行结果如下:
3-13 图片几何变换小结
本章学完啦,学会了图像的基本操作,其实这都是源码上面修改的,其实还有直接使用OpenCV对图像进行操作的。可以自己找资料学习。
多敲多敲,然后理解之后再敲。