opencv-python常用知识速查
Posted Rainbowman 0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv-python常用知识速查相关的知识,希望对你有一定的参考价值。
目录
1 基本操作
1.1 读入并显示图片:imread()、imshow()
import cv2 as cv
import numpy as np
img = cv.imread(r'E:\\0_postgraduate\\test.jpg', flags=0)
cv.imshow('title', img)
k = cv.waitKey(0)
if k & 0xFF == ord('s'):
cv.destroyAllWindows()
cv.imwrite(r'E:\\1.jpg', img)
(1)cv.imread(filename,flags)
两个参数,第一个参数filename是图片的路径,第二个参数flags是图像的通道和色彩信息
flags = -1, 8位深度,原通道
flags = 0, 8位深度,1通道
flags = 1, 8位深度,3通道
flags = 2, 原深度, 1通道
flags = 3, 原深度, 3通道
flags = 4, 8位深度,3通道
默认flags=1,为彩色图。flags=0为灰度图。
注意1:cv.imread()读取的图片类型为numpy.ndarray,数据类型为np.uint8
img = cv.imread(r'E:\\0_postgraduate\\test.jpg', flags=1)
print('img的数据类型是:%s'%type(img))
print('img的数据范围是:'.format(img.dtype))
print('img的形状为:'.format(img.shape))
# 结果
img的数据类型是:<class 'numpy.ndarray'>
img的数据范围是:uint8
img的形状为:(440, 640, 3)
注意2:cv.imread()读入的三通道图片的顺序是BGR
img = cv.imread(r'E:\\0_postgraduate\\test.jpg', flags=1)
print('原图的形状为:'.format(img.shape))
cv.imshow('original pic', img)
(b, g, r) = cv.split(img) # 将图片分成BGR三个通道
print('每个通道的形状为:\\nB: G: R:'.format(b.shape, g.shape, r.shape))
zeros = np.zeros(img.shape[:2], dtype=np.uint8)
merged1 = cv.merge([b, zeros, zeros])
merged2 = cv.merge([zeros, g, zeros])
merged3 = cv.merge([zeros, zeros, r])
print('合并后的形状为:'.format(merged1.shape))
cv.imshow('blue channel', merged1)
cv.imshow('green channel', merged2)
cv.imshow('red channel', merged3)
k = cv.waitKey(0)
if k == ord('s'):
cv.destroyAllWindows()
# 结果
原图的形状为:(440, 640, 3)
每个通道的形状为:
B:(440, 640) G:(440, 640) R:(440, 640)
合并后的形状为:(440, 640, 3)
(2)cv.imshow(name, img):
展示图片,name是标题,img是要展示的图片
(3)cv.waitKey(delay):
作用:对键盘事件进行delay(ms)的等待(delay=0则为无限等待),若触发则返回该按键的ASSIC码(范围是0-255)(否则返回-1)
着重解释下这句代码:
k = cv.waitKey(0)
if k & 0xFF == ord('q'):
cv.destroyAllWindows()
其实挺好理解的,不过,既然cv.waitKey()返回的是按键的ASSIC码,那为什么还要让k和0xFF相与呢?(0xFF为16进制,换成二进制是8位1111 1111)
解释如下:
来源
(4)cv.destroyAllWindows():
关闭所有窗口
(5)cv.imwrite(filepath, img):
把图片写入硬盘。filepath是写入的地址,img是imread()读取的图片。
1.2 读取摄像头操作
基本框架代码:
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("can't open your camera")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("can't receive the frame...")
break
cv.imshow('frame', frame)
k = cv.waitKey(25) # 25ms for 1 frame
if k & 0xFF == ord('q'):
break
cap.release() # 释放摄像头
cv.destroyAllWindows() # 关闭所有窗口
(1)cap.read():
返回两个参数,ret为Bool型,检查是否读到帧,如果是读取视频文件的话可以用来检测是否到视频结尾。frame为一帧图片。
(2)cap.release():
释放摄像头资源
改变摄像头窗口的尺寸
cap = cv.VideoCapture(0)
w = cap.get(3) # 得到当前视频窗口的weight
h = cap.get(4) # 得到当前视频窗口的height
print('当前窗口的wight:,当前窗口的height:\\n'.format(w, h))
# 设置当前的窗口为1280 x 720
cap.set(3, 1280)
cap.set(4, 720)
w = cap.get(3) # 得到当前视频窗口的weight
h = cap.get(4) # 得到当前视频窗口的height
print('当前窗口的wight:,当前窗口的height:\\n'.format(w, h))
if not cap.isOpened():
print('没打开摄像头')
exit()
while True:
ret, frame = cap.read()
if not ret:
print('未读取到帧...')
break
cv.imshow('frame', frame)
k = cv.waitKey(10)
if k & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()
# 结果
当前窗口的wight:640.0,当前窗口的height:480.0
当前窗口的wight:1280.0,当前窗口的height:720.0
(3) cap.get():获取当前图像信息
参数 | 含义 |
---|---|
cv2.VideoCapture.get(0) | 视频文件的当前位置(播放)以毫秒为单位 |
cv2.VideoCapture.get(1) | 基于以0开始的被捕获或解码的帧索引 |
cv2.VideoCapture.get(2) | 视频文件的相对位置(播放):0=电影开始,1=影片的结尾。 |
cv2.VideoCapture.get(3) | 在视频流的帧的宽度 |
cv2.VideoCapture.get(4) | 在视频流的帧的高度 |
cv2.VideoCapture.get(5) | 帧速率 |
cv2.VideoCapture.get(6) | 编解码的4字-字符代码 |
cv2.VideoCapture.get(7) | 编解码的4字-字符代码 |
cv2.VideoCapture.get(8) | 返回对象的格式 |
cv2.VideoCapture.get(9) | 返回后端特定的值,该值指示当前捕获模式 |
cv2.VideoCapture.get(10) | 图像的亮度(仅适用于照相机) |
cv2.VideoCapture.get(11) | 图像的对比度(仅适用于照相机) |
cv2.VideoCapture.get(12) | 图像的饱和度(仅适用于照相机) |
cv2.VideoCapture.get(13) | 色调图像(仅适用于照相机) |
cv2.VideoCapture.get(14) | 图像增益(仅适用于照相机)(Gain在摄影中表示白平衡提升 |
cv2.VideoCapture.get(15) | 曝光(仅适用于照相机) |
cv2.VideoCapture.get(16) | 指示是否应将图像转换为RGB布尔标志 |
cv2.VideoCapture.get(17) | × 暂时不支持 |
cv2.VideoCapture.get(18) | 立体摄像机的矫正标注(目前只有DC1394 v.2.x后端支持这个功能) |
来源:OpenCV VideoCapture.get()参数详解
(4)cap.set():改变图像属性信息
1.3 绘图
(1)绘制直线:
cv.line(img, startpoint, endpoint, color, thickness)
img:原始图像
startpoint:开始点坐标
endpoint:结束点坐标
color:直线的颜色
thickness:直线的厚度
(2)绘制矩形:
cv.rectangle(img, pos1, pos2, color, thickness)
img:原始图像
pos1:左上角坐标
pos2:右下角坐标
color:颜色
thickness:厚度(thickness=-1代表填充)
(3)绘制圆形
cv.circle(img, pos, radius, color, thickness)
img:原始图像
pos:圆心坐标
radius:半径
color:颜色
thickness:厚度(thickness=-1代表填充)
(4)添加文本:
cv.putText(img, ‘text’, pos, font, size, color)
img:原始图像
text:输出的文本
pos:文本的位置坐标
font:文本字体
size:文本大小
color:文本颜色
bg = np.zeros((550,550,3), dtype=np.uint8)
# 画一条直线
cv.line(bg, (0,0), (549,549), (255,0,0), 5)
# 画矩形
cv.rectangle(bg, (100,100), (200,200), (0,255,0), -1)
# 画圆形
cv.circle(bg, (300,300), 50, (0,0,255), 3)
# 放文字
cv.putText(bg, '123', (0,400), 0, 4, (255,0,0))
cv.imshow('draw', bg)
k = cv.waitKey(0)
if k & 0xFF == ord('q'):
cv.destroyAllWindows()
2. 图像操作
2.1 分割和合并通道cv.split(img) cv.merge([b,g,r])
这个前面举过例子了,不多说,不过有一点是:使用numpy索引要比cv.split(img)更高效,两者的效果是一样的:
img = cv.imread(r'E:\\opencv.jpg')
e1 = cv.getTickCount()
b, g, r = cv.split(img)
e2 = cv.getTickCount()
print('cv.split time is: ms'.format((e2-e1)*1000/cv.getTickFrequency()))
e1 = cv.getTickCount()
b = img[:,:,0]
g = img[:,:,1]
r = img[:,:,2]
e2 = cv.getTickCount()
print('numpy time is: ms'.format((e2-e1)*1000/cv.getTickFrequency()))
# 结果
cv.split time is:0.7039 ms
numpy time is:0.1805 ms
2.2 边框填充:cv.copyMakeBorder()
用法:cv.copyMakeBorder(img, top, bottom, left, right, borderType)
img:原始图像
top:顶部填充的边框宽度(单位为像素值)
bottom:底部填充的边框宽度(单位为像素值)
left:左部填充的边框宽度(单位为像素值)
right:右部填充的边框宽度(单位为像素值)
borderType:填充类型
img = cv.imread(r'E:\\test.jpg')
img1 = cv.copyMakeBorder(img, 20,20,20,20, 0) #第0类填充:黑边填充
img2 = cv.copyMakeBorder(img, 20,20,20,20, 1) #第1类填充
img3 = cv.copyMakeBorder(img, 20,20,20,20, 2) #第2类填充
img4 = cv.copyMakeBorder(img, 20,20,20,20, 3) #第3类填充
cv.imshow('0', img1)
cv.imshow('1', img2)
cv.imshow('2', img3)
cv.imshow('3', img4)
k = cv.waitKey(0)
if k & 0xFF == ord('q'):
cv.destroyAllWindows()
2.3 图像加法:cv.add()
我们已经知道了读入的图像本质上是numpy.ndarry数组,那么如果将两个同样维度的数组相加会怎样?
对于相加,我们有两种方式:假设a和b都为numpy.ndarry数组,
(1)使用numpy数组直接相加:a + b
(2)使用cv.add(a, b)
这两种方法的不同之处在于:
a + b:250+10 = 260 => 255
cv.add(a, b):250+10 = 260 % 256 = 4
具体来说,OpenCV加法是一个饱和操作,而Numpy加法是一个模数操作
举个例子:
np.random.seed(100)
a = np.random.randint(250,255,(10,10), dtype=np.uint8)
print('a数组:\\n'.format(a))
b = np.ones((10,10),dtype=np.uint8) * 5
print('b数组:\\n'.format(b))
print('a+b的结果为:\\n'.format(a+b))
print('cv.add(a,b)的结果为:\\n'.format(cv.add(a,b)))
# 结果
a数组:
[[250 254 253 250 253 250 253 253 253 253]
[251 254 250 251 250 253 250 252 252 251]
[251 254 250 252 250 254 252 253 252 251]
[253 253 252 253 253 251 253 252 250 252]
[251 250 251 251 253 250 254 254 254 253]
[252 254 252 252 250 253 251 253 252 251]
[253 254 251 250 250 252 251 253 253 252]
[254 253 254 252 251 254 250 251 253 254]
[254 254 250 254 252 254 250 253 254 254]
[252 251 254 254 253 251 253 252 254 253]]
b数组:
[[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]]
a+b的结果为:
[[255 3 2 255 2 255 2 2 2 2]
[ 0 3 255 0 255 2 255 1 1 0]
[ 0 3 255 1 255 3 1 2 1 0]
[ 2 2 1 2 2 0 2 1 255 1]
[ 0 255 0 0 2 255 3 3 3 2]
[ 1 3 1 1 255 2 0 2 1 0]
[ 2 3 0 255 255 1 0 2 2 1]
[ 3 2 3 1 0 3 255 0 2 3]
[ 3 3 255 3 1 3 255 2 3 3]
[ 1 0 3 3 2 0 2 1 3 2]]
cv.add(a,b)的结果为:
[[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 以上是关于opencv-python常用知识速查的主要内容,如果未能解决你的问题,请参考以下文章