提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- [1. 简介](#1. 简介)
- [2. 图像基础操作](#2. 图像基础操作)
-
- [2.1 图像的IO操作](#2.1 图像的IO操作)
- [2.2 绘制图形](#2.2 绘制图形)
- [2.3 获取并修改图像中的像素点](#2.3 获取并修改图像中的像素点)
- [2.4 获取图像属性](#2.4 获取图像属性)
- [2.5 图像通道的拆分和合并](#2.5 图像通道的拆分和合并)
- [2.6 色彩空间转换](#2.6 色彩空间转换)
- [3. 算术操作](#3. 算术操作)
-
- [3.1 图像加法](#3.1 图像加法)
- [3.2 图像混合](#3.2 图像混合)
- [4. OpenCV图像处理](#4. OpenCV图像处理)
-
- [4.1 几何变换](#4.1 几何变换)
- [4.2 图像平移](#4.2 图像平移)
- [4.3 图像旋转](#4.3 图像旋转)
- [4.4 仿射变换](#4.4 仿射变换)
- [4.5 透射变换](#4.5 透射变换)
- 总结
前言
1. 简介
灰度图:0~255
彩色图:RGB三个分量
安装OpenCv之前需要先安装numpy,matplotlib。
java
pip install opencv-python
java
import cv2
能导入这个就说明安装成功了
安装包含 contrib 扩展模块的版本----》因为我们要利用SIFT和SURF等进行特征提取
java
pip install opencv-python opencv-contrib-python

core模块实现了最核心的数据结构及其基本运算,如绘图函数、数组操作相关函数等。
·highgui模块实现了视频与图像的读取、显示、存储等接口。
·imgproc模块实现了图像处理的基础方法,包括图像滤波、图像的几何变换、平滑、阈值分割、形态学
处理、边缘检测、目标检测、运动分析和对象跟踪等。
2. 图像基础操作
2.1 图像的IO操作
java
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()是关闭图像
java
img = cv.imread("../image/dili.jpg")
plt.imshow(img[:,:,::-1])
plt.show()

OpenCV 读取图像时,默认使用 BGR 颜色通道顺序(蓝色、绿色、红色)。
Matplotlib 的 imshow() 函数则默认期望图像是 RGB 颜色通道顺序(红色、绿色、蓝色)
第一个 : :表示选取所有行(图像的高度方向)
第二个 : :表示选取所有列(图像的宽度方向)
::-1 :表示对第三个维度(颜色通道)进行反向切片,即把 BGR 顺序反转成 RGB 顺序
java
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",直接显示二维灰度数组,会用彩色伪影来表示不同的灰度值

java
#保存图像
cv.imwrite("../image/dili_save.jpg",img)

2.2 绘制图形
java
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 是线条的粗细,单位为像素
java
cv.circle(img,(256,256),60,(0,0,255),4)
(256,256)表示圆心,60表示半径,4表示宽度

java
cv.circle(img,(256,256),60,(0,0,255),-1)
-1表示填充

java
cv.rectangle(img,(100,100),(300,300),(0,255,0),5)
分别是左上角坐标和右下角坐标
java
cv.putText(img,"hello",(100,150),cv.FONT_HERSHEY_COMPLEX,5,(255,255,255),3)
5表示字体大小,3表示字体宽度,(100,150)表示字体位置

2.3 获取并修改图像中的像素点
java
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
java
img = np.zeros((256,256,3),np.uint8)
java
plt.imshow(img[:,:,::-1])

其实应该是全黑的,因为我的背景是黑色,所以显示为白色
java
img[100,100]

返回的是这个位置的RGB值
java
img[100,100,0]
返回的是这个位置,蓝色通道的值
java
img[100,100] = [0,0,255]
plt.imshow(img[:,:,::-1])
img[100,100]

2.4 获取图像属性
java
img.shape

java
img.dtype

java
img.size

2.5 图像通道的拆分和合并
java
dili = cv.imread("../../py/image/dili.jpg")
plt.imshow(dili[:,:,::-1])
plt.show()

java
b,g,r = cv.split(dili)

一个通道就是灰色了
java
img2=cv.merge((b,g,r))
plt.imshow(img2[:,:,::-1])

2.6 色彩空间转换
java
gray = cv.cvtColor(dili,cv.COLOR_BGR2GRAY)
plt.imshow(gray, cmap="gray")

这样就转换为灰度图了
java
hsv = cv.cvtColor(dili,cv.COLOR_BGR2HSV)
plt.imshow(hsv)

3. 算术操作
3.1 图像加法
np相加的话,超过255的话,那么就是和之后取模255---》模运算
cv加法的话,超过255的话,那么就是等于255了---》饱和运算
java
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
java
rain = cv.imread("../../py/image/rain.jpg")
plt.imshow(rain[:,:,::-1])

java
view = cv.imread("../../py/image/view.jpg")
plt.imshow(view[:,:,::-1])

java
img1 = cv.add(rain,view)
plt.imshow(img1[:,:,::-1])

java
img2= rain+ view
plt.imshow(img2[:,:,::-1])

所以cv的加法更好
3.2 图像混合
就是加法的权重不同
反正就是这样
img = aimg1 +b img2+x
a,b,x都是参数
java
img3 = cv.addWeighted(rain,0.3,view,0.7,0)
plt.imshow(img3[:,:,::-1])

权值之和为1,0就是x
4. OpenCV图像处理
4.1 几何变换
java
kids = cv.imread("../../py/image/kids.jpg")
plt.imshow(kids[:,:,::-1])

java
#绝对尺寸缩放
rows,cols = kids.shape[:2]
kids.shape 是 OpenCV 中图像的形状属性,返回一个元组 (高度, 宽度, 通道数)(对于彩色图像)或 (高度, 宽度)(对于灰度图像)。
第一个元素是图像的高度(行数,rows)
第二个元素是图像的宽度(列数,cols)
第三个元素(如果存在)是通道数(如 RGB 图像为 3)
:2\] 表示截取元组的前 2 个元素,即只获取高度和宽度,忽略通道数(即使图像有通道信息也不处理)  ```java res = cv.resize(kids,(cols*2,rows*2)) plt.imshow(res[:,:,::-1]) ```  看坐标就知道变大了 ```java res1=cv.resize(kids,None,fx=0.5,fy=0.5) plt.imshow(res1[:,:,::-1]) ```  0.5表示缩小为原来的de0.5倍 ### 4.2 图像平移 ```java #图像平移->平移矩阵 M = np.float32([[1,0,100],[0,1,50]]) ``` 表示往(1,0)方向也就是x方向移动100,y方向移动50 ```java res2 = cv.warpAffine(kids,M,(cols,rows)) plt.imshow(res2[:,:,::-1]) ``` (cols,rows)表示移动后显示范围画布的大小,并不是图像的大小 注意cv中,坐标原点在左上角,x轴往右,y轴往下 ```java res2 = cv.warpAffine(kids,M,(cols*2,rows*2)) plt.imshow(res2[:,:,::-1]) ```  ### 4.3 图像旋转 ```java #图像旋转 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)表示画布的大小  ```java #图像旋转 M = cv.getRotationMatrix2D((cols/2,rows/2),90,0.5) res3 = cv.warpAffine(kids,M,(cols,rows)) plt.imshow(res3[:,:,::-1]) ```  ### 4.4 仿射变换 仿射变换就是对图像缩放旋转平移的组合  点之间的映射,仿射前后,平行的线还是平行的,线的比例关系不变 共线的点还是共线,共面的还是共面 ```java 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 ```  前面两列是线性变换,后一列是平移 ```java #仿射变换 #原始图像位置 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)是输出图像大小  仿射变换后,点线的关系和原图是一样的 但是线的长度会发送变化,角度也会    ### 4.5 透射变换  ## 总结