一、图像处理的一般需要导入的包的集合
import cv2
import matplotlib
import matplotlib.pyplot as plt #取别名(用于绘图展示)
import numpy as np #取别名,下面是notepad专用,立即显示图像
%matplotlib inline
二、图片的读写
1. 读取图像
img = cv2.imread('tgcf.png')
# opencv的默认读取方式是BGR(从上至下),若要读取灰度图,则应设置参数cv2.IMREAD_GRAYSCALE
# 彩图的参数为cv2.IMREAD_COLOR
2. 输出图像
- N维阵列:灰度图一般是一维;
- 彩色图(BGR)一般是三维;
img # 三层
array([[[255, 254, 253],
[255, 254, 253],
[255, 254, 253],
...,
[255, 255, 255],
[255, 255, 255],
[255, 255, 255]],
...,
[[255, 254, 253],
[255, 254, 253],
[255, 254, 253],
...,
[255, 254, 253],
[255, 254, 253],
[255, 254, 253]]], dtype=uint8)
3. 使用imwrite保存图片
- 前一参数为路径+名称
- 后一参数为需要保存的对象
cv2.imwrite('Graytgcf.png',img)
True
cv_show('Graytgcf',cv2.imread('Graytgcf.png'))
4. 读取、播放视频
import cv2
import matplotlib
import matplotlib.pyplot as plt #取别名(用于绘图展示)
import numpy as np #取别名,下面是notepad专用,立即显示图像
%matplotlib inline
vdo = cv2.VideoCapture('dfh.mp4')
# 检查文件是否打开正确
if vdo.isOpened():
open, frame = vdo.read()
else:
open = False
while open: # 若打开正常
ret, frame = vdo.read() #
if frame is None:
break
if ret == True:
# gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# cv2.imshow('result',frame) #可以直接使用frame进行原彩显示
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('result',gray)
# 如果不清楚键盘上对应的ASCII码,则可使用ord('')来获取对应字符的ASCII码
if cv2.waitKey(10) & 0xFF == 27: ##27是退出键Esc
break
vdo.release() #释放视频
cv2.destroyAllWindows()
5. 创建图片显示端口(可创建多个)
- 注意waitKey值的设置
cv2.imshow('Test',img)
#等待时间
cv2.waitKey(0) #设置以ms为单位的等待时间,0表示任意键停止(按下任意键就停止等待)
cv2.destroyAllWindows()
6. 解决名称乱码:先编码为GBK,再解码为UTF-8
def rename(name):
return name.encode('gbk').decode('utf-8',errors='ignore')
# ①尚未解决 编码问题
#cv_show(rename('壁纸'),cv2.imread('tgcf.png'))#不要忘了imread是cv2内置方法
三、灰度图操作
1.读取灰度图并显示其阵列
img2 = cv_readgray('tgcf.png')
cv_show('GRAY',img2) #可以将衣服彩色图像以灰度输出
2. 自定义读取为灰度图的函数和显示函数
def cv_readgray(imgname): #(多此一举)根据图片名打开图片,改为读取灰度图
return cv2.imread(imgname,cv2.IMREAD_GRAYSCALE)
def cv_show(name, img): #定义函数用于显示图片,此处name为窗口名,img为cv2调用imread方法的返回值
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 查看灰度图属性
img2 #注意看数组层数仅有一层
array([[254, 254, 254, ..., 255, 255, 255],
[254, 254, 254, ..., 255, 255, 255],
[254, 254, 254, ..., 255, 255, 255],
...,
[254, 254, 254, ..., 254, 254, 254],
[254, 254, 254, ..., 254, 254, 254],
[254, 254, 254, ..., 254, 254, 254]], dtype=uint8)
img2.shape #仅有一个颜色通道时,不会显示 1
(1880, 854)
四、查看图像属性及切片
1. 显示图片对象的各项属性
- shape
- size
- type()
- ntype()
img.shape #作为CV2的实例对象,查看其尺寸,3表示三个通道,即BGR方式
(1880, 854, 3)
img2.size
1605520
type(img2) #显示对象类型,N维数组
numpy.ndarray
img2.dtype #显示对象数据类型
dtype('uint8')
2. 利用切片读取图片部分(ROI的提取)
- 注意图片数组的排列方式: 以左上角为原点,x轴正方向向右,y轴正方向向下
#利用Python切片来读取部分图像数据,三个参数(起始点,终止点,步长)
# 利用步长可以达到模糊效果——失真
cv_show('SliceDisplay',img2[0:-1:4,0:-1:4])
cv_show('SliceDisplay',img2[940:-1,450:-1]) # 注意图片截取的方向,
3. 颜色通道的提取
- 0表示黑色
- 255表示白色
- OpenCV是 8 比特表示法,也就是说灰度区间为[0, 255]
sys = cv2.imread('sys.jpg')
b, g, r = cv2.split(sys)
b
array([[ 0, 2, 15, ..., 61, 70, 62],
[ 6, 13, 29, ..., 63, 64, 54],
[ 7, 15, 32, ..., 57, 53, 54],
...,
[ 8, 5, 13, ..., 63, 68, 56],
[ 0, 3, 14, ..., 59, 68, 61],
[ 4, 12, 18, ..., 54, 64, 59]], dtype=uint8)
g
array([[ 9, 11, 24, ..., 45, 54, 46],
[15, 22, 38, ..., 50, 48, 41],
[16, 24, 41, ..., 46, 40, 43],
...,
[ 8, 5, 13, ..., 68, 72, 60],
[ 0, 3, 15, ..., 64, 71, 64],
[ 4, 12, 19, ..., 59, 67, 62]], dtype=uint8)
r
array([[ 0, 1, 14, ..., 62, 71, 63],
[ 5, 12, 28, ..., 66, 65, 57],
[ 6, 14, 31, ..., 62, 56, 59],
...,
[24, 21, 29, ..., 71, 77, 65],
[15, 19, 29, ..., 67, 75, 68],
[20, 28, 33, ..., 62, 71, 66]], dtype=uint8)
b.shape #bgr每个变量都是单通道了
(540, 720)
五、图像通道
1. 显示单个通道的图片信息
- 这三个通道的元素值只是对应的通道的灰度值,不会显示颜色
- 衡量值是对应色光的光强
cv_show('RED',r)
cv_show('Green',g)
cv_show('Blue',b)
2. 三个通道的的过滤显示仍需在三维数组中进行
- 两个冒号分离三个维度
# 只显示红色通道
img0 = sys.copy()
# 这里的 , 起到了分割维度的作用,其实还可以简写: img0[...:0] ,就会自动补齐了。
# 前两维都是对应通道的坐标
img0[:,:,0] = 0 #B
img0[:,:,1] = 0 #G
cv_show('R',img0)
# 只显示绿色通道
img0 = sys.copy()
img0[:,:,0] = 0 #B
img0[:,:,2] = 0 #R
cv_show('G',img0)
# 只显示蓝色通道
img0 = sys.copy()
img0[:,:,1] = 0 #G
img0[:,:,2] = 0 #R
cv_show('B',img0)
3. 三个通道合并
- merge的用法
_img = cv2.merge((b, g, r)) ## merge必须传入元组
cv_show('Test',_img) #不能直接用imshow()输出显示,另外还要设置waitKey与destroyAllWindows信息
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
F:\Temp1/ipykernel_4296/1515998152.py in <module>
1 _img = cv2.merge((b, g, r)) ## merge必须传入元组
----> 2 cv_show('Test',_〇img) #不能直接用imshow()输出显示,另外还要设置waitKey与destroyAllWindows信息
NameError: name '_〇img' is not defined
六、图像基本操作
1. 边界填充
- 卷积:对图像进行特征提取
- 参数说明:(那么四个角是如何复制的呢?)
-
BORDER_REPLICATE:直接复制边缘像素
-
BORDER_REFLECT:镜面反射 —— hgfedcba|abcdefgh|hgfedcba(会复制边缘像素)
-
BORDER_REFLECT_101:以最边缘元素为轴,不会复制最边缘像素—— hgfedcb|abcdefgh|gfedcba
-
BORDER_WRAP:外包装法—— cdefgh|abcdefgh|abcdef,区内部像素向外平移
-
BORDER_CONSTANT:常数填充,需要设置value值
-
#初始化边界填充的边界大小,定义成tuple不能赋值
top, bottom, left, right = (100, 100, 100, 100)
replicate = cv2.copyMakeBorder(img, top, bottom, left, right, borderType = cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top, bottom, left, right, borderType = cv2.BORDER_REFLECT)
reflect101= cv2.copyMakeBorder(img, top, bottom, left, right, borderType = cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top, bottom, left, right, borderType = cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top, bottom, left, right, borderType = cv2.BORDER_CONSTANT, value = 0)
import matplotlib.pyplot as plt
plt.subplot(351), plt.imshow(img,'gray'), plt.title('ORIGINAL')
plt.subplot(352), plt.imshow(replicate,'gray'), plt.title('replicate')
plt.subplot(353), plt.imshow(reflect,'gray'), plt.title('reflect')
plt.subplot(354), plt.imshow(reflect101,'gray'), plt.title('reflect101')
plt.subplot(355), plt.imshow(wrap,'gray'), plt.title('wrap')
plt.subplot(356), plt.imshow(constant,'gray'), plt.title('constant')
(<AxesSubplot:title={'center':'constant'}>,
<matplotlib.image.AxesImage at 0x20c3c52dc70>,
Text(0.5, 1.0, 'constant'))
2. 数值计算
- 加法:
-
常数:所有阵列像素都会加上对应常数
- 注意:若常数加法所得结果超过了 n 比特表示法的最大值也即大于 (2^n-1) 则会将结果取余。也即若为 8 比特表示法,运算结果为509,则会将509 % 255 = 254 填入
-
两个尺寸匹配的图像相加:对应阵列元素相加,
- 应该注意:超出部分直接取最大值,不会进行取余(上例则取255)
-
img_sys = cv2.imread('sys.jpg')
img_tgcf = cv2.imread('tgcf.png')
img_sys[:5,:,0] #只打印B通路的前5行
array([[ 0, 2, 15, ..., 61, 70, 62],
[ 6, 13, 29, ..., 63, 64, 54],
[ 7, 15, 32, ..., 57, 53, 54],
[ 4, 8, 18, ..., 46, 44, 64],
[16, 9, 7, ..., 45, 43, 65]], dtype=uint8)
img_sys2 = img_sys + 255 ##可以看出加法就是所有阵列元素都加
img_sys2[:5,:,0]
array([[255, 1, 14, ..., 60, 69, 61],
[ 5, 12, 28, ..., 62, 63, 53],
[ 6, 14, 31, ..., 56, 52, 53],
[ 3, 7, 17, ..., 45, 43, 63],
[ 15, 8, 6, ..., 44, 42, 64]], dtype=uint8)
(img_sys2 + img_sys)[:5,:,0]
array([[255, 3, 29, ..., 121, 139, 123],
[ 11, 25, 57, ..., 125, 127, 107],
[ 13, 29, 63, ..., 113, 105, 107],
[ 7, 15, 35, ..., 91, 87, 127],
[ 31, 17, 13, ..., 89, 85, 129]], dtype=uint8)
3. 图像融合
img_sys + img_tgcf #宽长不同不能相加,必须进行调整
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
F:\Temp1/ipykernel_4296/2369869610.py in <module>
----> 1 img_sys + img_tgcf
ValueError: operands could not be broadcast together with shapes (540,720,3) (1880,854,3)
img_tgcf.shape
(1880, 854, 3)
img_sys = cv2.resize(img_sys,(854, 1880)) #利用CV模块中的resize方法调整大小,注意传入参数的顺序,宽在前,而shape是宽在后
img_sys + img_tgcf
array([[[255, 7, 253],
[ 0, 9, 254],
[ 9, 17, 6],
...,
[ 63, 47, 64],
[ 67, 51, 68],
[ 61, 45, 62]],
...,
[ 58, 61, 63],
[ 62, 64, 68],
[ 58, 60, 63]],
[ 57, 60, 62],
[ 62, 64, 67],
[ 58, 60, 63]]], dtype=uint8)
4. resize的用法
-
resize(img, (width, length)):直接指定宽长
-
resize(img, (0, 0), fx = n, fy = n):传入(0, 0)表示不直接指定宽长,后面参数是宽长的放缩比例。
res = cv2.resize(img_sys, (0, 0), fx = 3, fy = 1) #参数含义依次为:图像对象、不给予具体数值、横轴倍数、纵轴倍数
plt.imshow(res)
<matplotlib.image.AxesImage at 0x2090800e790>
res = cv2.resize(img_sys, (0, 0), fx = 1, fy=3)
cv_show('Test', res) #注意,若我们要在当前界面显示而非弹出新窗口,则应调用plt模块
plt.imshow(res)
<matplotlib.image.AxesImage at 0x2090adc46d0>
img_tgcf = cv2.imread('tgcf.png')
res = cv2.resize(img_tgcf, (0, 0), fx = 0.5, fy= 0.5)
plt.imshow(res)
<matplotlib.image.AxesImage at 0x2090ae0ca00>
5. 图像融合公式
- New = α * img1 + β * img2 + b
- 阿尔法和贝塔都是图片所占的权值,取值范围为 0-1 ,取值越大代表在图片中占比越大
- b是偏移量,对整体亮度的改变
- addWeighted(img1, α, img2, β, b)
img_tgcf = cv2.imread('tgcf.png')
img_tgcf = cv2.resize(img_tgcf, (0,0) ,fx=0.4, fy=0.4)
cv_show('Half',img_tgcf)
img_tgcf.shape
img_sys = cv2.resize(img_sys, (342, 752))
cv_show('Adjust',img_sys)
res = cv2.addWeighted(img_tgcf, 0.5, img_sys, 0.5, 0)
plt.imshow(res)
<matplotlib.image.AxesImage at 0x209083a7280>
cv_show('Mixed',res)