OpenCV1
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 1. 简介
- 2. 图像基础操作
- 2.1 图像的IO操作
- 2.2 绘制图形
- 2.3 获取并修改图像中的像素点
- 2.4 获取图像属性
- 2.5 图像通道的拆分和合并
- 2.6 色彩空间转换
- 3. 算术操作
- 3.1 图像加法
- 3.2 图像混合
- 4. OpenCV图像处理
- 4.1 几何变换
- 4.2 图像平移
- 4.3 图像旋转
- 4.4 仿射变换
- 4.5 透射变换
- 总结
前言
1. 简介
灰度图:0~255
彩色图:RGB三个分量
安装OpenCv之前需要先安装numpy,matplotlib。
pip install opencv-python
import cv2
能导入这个就说明安装成功了
安装包含 contrib 扩展模块的版本----》因为我们要利用SIFT和SURF等进行特征提取
pip install opencv-python opencv-contrib-python
core模块实现了最核心的数据结构及其基本运算,如绘图函数、数组操作相关函数等。
·highgui模块实现了视频与图像的读取、显示、存储等接口。
·imgproc模块实现了图像处理的基础方法,包括图像滤波、图像的几何变换、平滑、阈值分割、形态学
处理、边缘检测、目标检测、运动分析和对象跟踪等。
2. 图像基础操作
2.1 图像的IO操作
import numpy as py
import cv2 as cv
import matplotlib.pyplot as plt#读取图像---》默认读取--》彩色
img = cv.imread("../image/dili.jpg")
#显示图像
cv.imshow("dili",img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(0)的作用是
这是一个等待键盘输入的函数,参数 0 表示无限期等待用户按下任意键。
OpenCV 的 cv.imshow() 显示窗口需要配合 cv.waitKey() 才能正常停留,否则窗口会瞬间闪过。
只有当用户按下键盘上的任意键后,程序才会继续执行后续代码(这里就是执行 cv.destroyAllWindows())。
如果参数是其他数值(如 cv.waitKey(500)),则表示等待 500 毫秒(0.5 秒)后自动继续,无需按键。
cv.destroyAllWindows()是关闭图像
img = cv.imread("../image/dili.jpg")plt.imshow(img[:,:,::-1])
plt.show()
OpenCV 读取图像时,默认使用 BGR 颜色通道顺序(蓝色、绿色、红色)。
Matplotlib 的 imshow() 函数则默认期望图像是 RGB 颜色通道顺序(红色、绿色、蓝色)
第一个 : :表示选取所有行(图像的高度方向)
第二个 : :表示选取所有列(图像的宽度方向)
::-1 :表示对第三个维度(颜色通道)进行反向切片,即把 BGR 顺序反转成 RGB 顺序
img = cv.imread("../image/dili.jpg",0)plt.imshow(img,cmap="gray")
plt.show()
img = cv.imread(…, 0) 执行后,img 是一个二维数组(形状为 (高度, 宽度)),每个元素代表对应像素的灰度值(0 为纯黑,255 为纯白),灰度图像没有RGB
Matplotlib 默认的颜色映射表不是灰度(而是 viridis 等彩色映射),如果不指定 cmap=“gray”,直接显示二维灰度数组,会用彩色伪影来表示不同的灰度值
#保存图像
cv.imwrite("../image/dili_save.jpg",img)
2.2 绘制图形
import numpy as py
import cv2 as cv
import matplotlib.pyplot as plt#创建图形
img = py.zeros((512,512,3),py.uint8)
#绘制线
cv.line(img,(0,0),(511,511),(255,0,0),5)
#显示结果
plt.imshow(img[:,:,::-1])
plt.show()
np.zeros() 创建一个全为 0 的数组,代表黑色图像
(512,512,3) 表示图像尺寸为 512x512 像素,3 个颜色通道(BGR 格式),意思就是长宽为512,高为3,这个高就是RGB
np.uint8 是数据类型,代表每个像素值范围是 0-255
(0,0) 是线段的起点坐标(左上角)
(511,511) 是线段的终点坐标(右下角)
(255,0,0) 是线条颜色,这里是蓝色(BGR 格式)
5 是线条的粗细,单位为像素
cv.circle(img,(256,256),60,(0,0,255),4)
(256,256)表示圆心,60表示半径,4表示宽度
cv.circle(img,(256,256),60,(0,0,255),-1)
-1表示填充
cv.rectangle(img,(100,100),(300,300),(0,255,0),5)
分别是左上角坐标和右下角坐标
cv.putText(img,"hello",(100,150),cv.FONT_HERSHEY_COMPLEX,5,(255,255,255),3)
5表示字体大小,3表示字体宽度,(100,150)表示字体位置
2.3 获取并修改图像中的像素点
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img = np.zeros((256,256,3),np.uint8)
plt.imshow(img[:,:,::-1])
其实应该是全黑的,因为我的背景是黑色,所以显示为白色
img[100,100]
返回的是这个位置的RGB值
img[100,100,0]
返回的是这个位置,蓝色通道的值
img[100,100] = [0,0,255]
plt.imshow(img[:,:,::-1])
img[100,100]
2.4 获取图像属性
img.shape
img.dtype
img.size
2.5 图像通道的拆分和合并
dili = cv.imread("../../py/image/dili.jpg")
plt.imshow(dili[:,:,::-1])
plt.show()
b,g,r = cv.split(dili)
一个通道就是灰色了
img2=cv.merge((b,g,r))
plt.imshow(img2[:,:,::-1])
2.6 色彩空间转换
gray = cv.cvtColor(dili,cv.COLOR_BGR2GRAY)
plt.imshow(gray, cmap="gray")
这样就转换为灰度图了
hsv = cv.cvtColor(dili,cv.COLOR_BGR2HSV)
plt.imshow(hsv)
3. 算术操作
3.1 图像加法
np相加的话,超过255的话,那么就是和之后取模255—》模运算
cv加法的话,超过255的话,那么就是等于255了—》饱和运算
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
rain = cv.imread("../../py/image/rain.jpg")
plt.imshow(rain[:,:,::-1])
view = cv.imread("../../py/image/view.jpg")
plt.imshow(view[:,:,::-1])
img1 = cv.add(rain,view)
plt.imshow(img1[:,:,::-1])
img2= rain+ view
plt.imshow(img2[:,:,::-1])
所以cv的加法更好
3.2 图像混合
就是加法的权重不同
反正就是这样
img = aimg1 +bimg2+x
a,b,x都是参数
img3 = cv.addWeighted(rain,0.3,view,0.7,0)
plt.imshow(img3[:,:,::-1])
权值之和为1,0就是x
4. OpenCV图像处理
4.1 几何变换
kids = cv.imread("../../py/image/kids.jpg")
plt.imshow(kids[:,:,::-1])
#绝对尺寸缩放
rows,cols = kids.shape[:2]
kids.shape 是 OpenCV 中图像的形状属性,返回一个元组 (高度, 宽度, 通道数)(对于彩色图像)或 (高度, 宽度)(对于灰度图像)。
第一个元素是图像的高度(行数,rows)
第二个元素是图像的宽度(列数,cols)
第三个元素(如果存在)是通道数(如 RGB 图像为 3)
[:2] 表示截取元组的前 2 个元素,即只获取高度和宽度,忽略通道数(即使图像有通道信息也不处理)
res = cv.resize(kids,(cols*2,rows*2))
plt.imshow(res[:,:,::-1])
看坐标就知道变大了
res1=cv.resize(kids,None,fx=0.5,fy=0.5)
plt.imshow(res1[:,:,::-1])
0.5表示缩小为原来的de0.5倍
4.2 图像平移
#图像平移->平移矩阵
M = np.float32([[1,0,100],[0,1,50]])
表示往(1,0)方向也就是x方向移动100,y方向移动50
res2 = cv.warpAffine(kids,M,(cols,rows))
plt.imshow(res2[:,:,::-1])
(cols,rows)表示移动后显示范围画布的大小,并不是图像的大小
注意cv中,坐标原点在左上角,x轴往右,y轴往下
res2 = cv.warpAffine(kids,M,(cols*2,rows*2))
plt.imshow(res2[:,:,::-1])
4.3 图像旋转
#图像旋转
M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)
res3 = cv.warpAffine(kids,M,(cols,rows))
plt.imshow(res3[:,:,::-1])
(cols/2,rows/2)是旋转中心,90就是选择角度,1表示对图像的缩放比例
(cols,rows)表示画布的大小
#图像旋转
M = cv.getRotationMatrix2D((cols/2,rows/2),90,0.5)
res3 = cv.warpAffine(kids,M,(cols,rows))
plt.imshow(res3[:,:,::-1])
4.4 仿射变换
仿射变换就是对图像缩放旋转平移的组合
点之间的映射,仿射前后,平行的线还是平行的,线的比例关系不变
共线的点还是共线,共面的还是共面
plt.imshow(res3[:,:,::-1])
#%%
#仿射变换
#原始图像位置
pts1 = np.float32([[50,50],[200,50],[50,200]])
#仿射变换后位置
pts2 = np.float32([[100,100],[200,50],[100,250]])
#构建仿射变换矩阵
M = cv.getAffineTransform(pts1,pts2)
M
前面两列是线性变换,后一列是平移
#仿射变换
#原始图像位置
pts1 = np.float32([[50,50],[200,50],[50,200]])
#仿射变换后位置
pts2 = np.float32([[100,100],[200,50],[100,250]])
#构建仿射变换矩阵
M = cv.getAffineTransform(pts1,pts2)
#应用仿射变换
res4 = cv.warpAffine(kids,M,(cols,rows))
plt.imshow(res4[:,:,::-1])
(cols,rows)是输出图像大小
仿射变换后,点线的关系和原图是一样的
但是线的长度会发送变化,角度也会