人工智能——OpenCv基础
一、OpenCv环境安装
Opencv是C++的类和函数构成的,我们在python中进行开发和使用的时候是用OpenCV-Python这个库
在终端输入命令行下载:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
二、OpenCV的思想,和numpy的结合
像素是图像的基本单元,每个像素存储着图像的颜色、亮度和其他特征 在计算机中,图像以像素的形式存在并采用二进制格式进行存储。计算机采用0/1编码的系统,数字图像也是利用0/1来记录信息,我们平常接触的图像都是8位数图像。
日常生活中常见的图像是RGB三原色图。RGB图上的每个点都是由红(R)、绿(G)、蓝(B)三个颜色按照一定比例混合而成的,几乎所有颜色都可以通过这三种颜色按照不同比例调配而成。在计算机中,RGB三种颜色被称为RGB三通道,每个通道的取值都是0-255,根据这三个通道存储的像素值,来对应不同的颜色
opencv的核心思想是:“将视觉问题转化为可以计算的数字问题,用高效的算法处理图像/视频数据”
图像即数组:用数字描述视觉信息,图像是像素的有序排列,而数组是存储这种排列的容器
1、不同图像的类型和数组维度相对应
图像类型 数组维度 (shape) 数组含义 灰度图 (高度,宽度) 每个元素是单个像素的亮度值(0-255,uint8 类型) 彩色图(RGB) (高度,宽度,3) 最后一个维度对应 R、G、B 三个通道的像素值(如 [255,0,0]
表示红色)带透明度的图 (高度,宽度,4) 前 3 个通道同 RGB,第 4 个通道是透明度(alpha 值,0-255)
2、图像的“宽高通道数”与数组的“维度”是对应的
图像属性
数组维度(shape) 含义举例 高度(Height) 数组第 0 维( shape[0]
)图像的垂直像素数量(从上到下的行数)。例如 shape[0] = 480
表示图像高 480 像素。宽度(Width) 数组第 1 维( shape[1]
)图像的水平像素数量(从左到右的列数)。例如 shape[1] = 640
表示图像宽 640 像素。通道数(Channels) 数组第 2 维( shape[2]
)图像的色彩通道数量:
- 灰度图无此维度(shape = (H, W)
)
- 彩色图(如 BGR)为 3(shape = (H, W, 3)
)
- 带透明度的图为 4(shape = (H, W, 4)
)
3、数组索引对应了图像的“像素位置和色彩”
数组的索引操作可以直接定位到图像中的某个像素及其色彩通道,例如一张(480,640,3)的彩色图也就是(高480,宽640,通道数3):
1、定位像素位置
数组索引 img[y,x] 对应图像中坐标为(x,y)的像素 (#注意:图像坐标通常是(x,y)的形式,但是数组索引是 [y,x] )因为数组是先按行(y)再按列(x)进行存储的(行优先原则):
y:范围在0~479(数组是左闭右开,对应图像高度的像素行)
x:范围在0~479(对应图像的像素列)
例如:img [100,200] 表示图像中“第100行,第200列”的像素
2、定位像素的彩色通道
加上通道维度的索引 img [y,x,c] 可获取单个通道的像素值:
c=0
:B 通道(蓝色分量,0~255)c=1
:G 通道(绿色分量,0~255)c=2
:R 通道(红色分量,0~255)例如:
img[100, 200, 2]
表示 “第 100 行、第 200 列” 像素的红色分量值
3、图像的修改——数组赋值
(1)修改单个像素:将(100,200)位置的像素改为红色
img[100, 200] = [0, 0, 255] # B=0, G=0, R=255
(2)批量修改:例如将图像上半部分改为绿色
img[:240, :] = [0, 255, 0] # 前240行(高度的一半)全部设为绿色
总结:核心对应关系
图像概念 | 数组概念 | 操作示例 |
---|---|---|
高度(像素行数) | 数组第 0 维(shape[0] ) | img[y, ...] 访问第 y 行像素 |
宽度(像素列数) | 数组第 1 维(shape[1] ) | img[:, x] 访问第 x 列像素 |
色彩通道 | 数组第 2 维(shape[2] ) | img[..., c] 访问第 c 个通道 |
单个像素 | 数组的元素 | img[y, x] 或 img[y, x, c] |
局部区域 | 数组的切片 | img[y1:y2, x1:x2] 截取区域 |
三、图像的基本操作——创建窗体,读取图像,显示图像,保存图像,创建黑白图像,图像切片(剪裁),图像大小调整
图像的读取、显示、保存、灰度图像、彩色图像
先导入包
import cv2 as cv
读取图像:cv.imread(path,读取方式)默认读为彩色图,还有参数就是读取方式
其中对于路径(path):../是返回上一级,./是当前文件目录
路径包括两种,一是相对路径,一是绝对路径
#读取图像 cv.imread(path,读取方式),默认读为彩色图,还有参数就是读取方式 #../是返回上一级,./是当前文件目录 cat = cv.imread('../images/1.jpg') cat1 = cv.imread('../images/1.jpg', cv.IMREAD_GRAYSCALE) boy = cv.imread("D:/bizhi/2F9509464A66BC95CB68607678FA23BD.jpg") #读取的路径为绝对路径,不然会报错 print(cat)
保存图像:cv.imwrite((path, image),保存的图像格式必须是png或者jpg,要写明不然就会报错
#保存图像 cv.imwrite(path, image),保存的图像格式必须是png或者jpg,要写明不然就好报错 cv.imwrite('./cat.png', cat)
显示图像:cv.imshow(name, image) 此处的image其实就是传入一个参数,数据类型是数组
#显示图像 cv.imshow(name, image) 此处的image其实就是传入一个参数,数据类型是数组 cv.imshow('cat', cat) # cv.imshow('cat1', cat1) # cv.imshow('cat1', cat1) # cv.imshow('boy', boy)
对于彩色图像,其数组显示出来的返回图像的形状,行数(高),列数(宽),通道数(BGR)打印出来的类型是元组
对于灰度图像,返回图像的形状,行数(高),列数(宽),通道数(1)
#彩色图:返回图像的形状,行数(高),列数(宽),通道数(BGR)打印出来的类型是元组 print(cat.shape)#灰度图:返回图像的形状,行数(高),列数(宽),通道数(1) print(cat1.shape)
显示时要设置图像显示时间:cv.waitKey(n)此处的n为参数是等待时间,单位是毫秒,0表示无限等待,如果是n的话就是等待n毫秒
然后释放资源关闭窗口
#等待键盘输入, cv.waitKey(n)此处的n为参数是等待时间,单位是毫秒,0表示无限等待,如果是n的话就是等待n毫秒 cv.waitKey(0) #关闭窗口 cv.destroyAllWindows() 关闭所有窗口,也就是释放窗口资源 cv.destroyAllWindows()
创建黑白图像或者彩色图像
1、使用np.zeros创建全0的图像表示黑色图像
black = np.zeros((360,480,3),dtype=np.uint8) cv.imshow("black",black)
2、使用np.full创建全1的图像,表示白色图像,np.full(shape,fill_value)
flill_value:
如果创建灰度图像(二维数组
(H, W)
):fill_value
是单个整数(0-255),表示灰度值(0 为黑,255 为白,中间值为灰色)如果创建彩色图像(三维数组
(H, W, 3)
):fill_value
是一个包含 3 个整数的元组(B, G, R),分别对应蓝、绿、红三个通道的像素值(每个值 0-255)#使用np.full 创建一个全1图像,表示白色图像 white = np.full((360,480,3),255,dtype=np.uint8) cv.imshow("white",white)
#使用np.full 创建某个特定颜色的图像 color = np.full((360,480,3),(122,54,122),dtype=np.uint8) cv.imshow("color",color)
3、通过索引,修改区域的像素值变换为白色图像(本质是数组的赋值)
#索引修改像素值,表示白色图像 black[:,:,:] = 255 # black[:,:]=255 # black[:]=255 cv.imshow("black1",black)
4、np.ramdom.randint(low,high,size,dtype)创建随机像素的图像,其中low为随机生成数的最低值,high是随机生成数的最高值,然后大小...,这个随机数是左闭右开
#创建随机像素值的图像,np.random.randint(low,high,size,dtype),左闭右开 random = np.random.randint(0,256,(360,480,3),dtype=np.uint8) cv.imshow("random",random)
图像切片(剪裁)
本质上是运用数组切片的思想
拿到剪裁区域的左上和右下点的坐标,就可以切片出想要的区域(值小的在前面,分清楚宽高,因为在数组中是先剪切行再剪切高)
#(280,232),(356,300)在画图软件中是(宽,高),但是在数组中arr[h1:h2,w1:w2]是(高,宽),h2=h1+h eye =cat[232:300,232:356] #裁剪图像
调整图像大小
通过cv.resize(img,(宽,高)),这里是要调整的宽和高
#调整图片大小,cv.resize(img,(宽,高)) pig2=cv.resize(pig,(480,530))
四、图像绘制
绘制直线cv.line(img, start_point, end_point, color, thickness)
img:要绘制直线的图像
start、end:直线的起点和终点
color:直线的颜色(对于彩色图像,使用 BGR 格式指定颜色)
thickness:线条宽度
#绘制直线cv.line(img, start_point, end_point, color, thickness) cv.line(cat,(70,400),(100,300),(220,221,0),thickness=10)
绘制矩形cv.rectangle(img, leftupper, rightdown, color,thickness),如果thickness为-1,则填充矩形
img:要绘制矩形的图像
leftupper、rightdown:矩形的左上角和右下角坐标
color:线条的颜色
thickness:线条的宽度
#绘制矩形cv.rectangle(img, lefttop, rightbottom, color,thickness),如果thickness为-1,则填充矩形 cv.rectangle(cat,(85,96),(264,256),color=(220,255,0),thickness=3)
绘制圆,cv.circle(img, center, radius, color, thickness)
img:要绘制圆形的图片
centerpoint、r:圆心和半径
color:线条颜色
tnickness:线条宽度,为-1时生成闭合图案并填充颜色
#绘制圆,cv.circle(img, center, radius, color, thickness) cv.circle(cat,(325,269),35,color=(0,0,255),thickness=3,lineType=cv.LINE_AA)
五、读取视频
创建一个videocapture对象,参数为视频文件名cv,VideoCapture(),传入视频路径,如果为0表示打开摄像头#创建一个videocapture对象,参数为视频文件名cv,VideoCapture(),传入视频路径,如果为0表示打开摄像头 cap = cv.VideoCapture('../images/videocap.mp4')
利用ret,frame=cap.read()可以拿到每一帧的图像,并返回它的状态标志,是一个布尔值,(
True
或False
),用于表示当前帧是否读取成功,cap.read最终返回的值一般命名为ret,frame当
ret = True
时:表示成功从视频中读取到一帧图像。当
ret = False
时:表示读取失败通过循环读取每一张图片:
import cv2 as cv #创建一个videocapture对象,参数为视频文件名cv,VideoCapture(),传入视频路径,如果为0表示打开摄像头 cap = cv.VideoCapture('../images/videocap.mp4')#循环读取每一帧图片 while True:# cap.read()#读取视频的每一帧,返回值是布尔值,如果读取成功为True,读取失败为Falseret, img = cap.read()#是否读取成功if not ret:print('播放完毕')breakcv.imshow('video', img)#此处的waitKey()中的参数表示切换下一帧间隔的时间if cv.waitKey(40) == ord('q'):print('您已按键退出')break# 释放摄像头和窗口资源 cap.release() cv.destroyAllWindows()