opencv入门:十类常用基础指令

71 阅读10分钟

[toc] opencv是一个计算机视觉相关的库,可以用于处理图片和视频,本篇介绍opencv中的一些基础入门指令

〇、安装opencv库和numpy库

pip3 install opencv – python
pip3 install numpy

opencv处理视频图片时是将图片转换成三维数组,包含画面中每个像素点的BGR三个颜色通道灰度信息(值在0~255)
使用指令代码前需要在开头引入opencv库和numpy库

import cv2
import numpy as np

之后就可以用cv2. 和np. 调用库中的函数

一、图像读取与显示

1.读取图像

image = cv2.imread('image.jpg') 读取图像文件;该函数接受图像文件的路径作为参数,并返回一个表示图像的 NumPy 数组,后续对图像的处理都将基于修改这个数组进行操作
代码的同目录下只需要输入文件名称作为参数,不在同一目录下则需要输入文件从根目录开始的的完整路径

2.显示图像

cv2.imshow('Image', image) 在弹出窗口中显示图像;该函数接受窗口名称和图像数组作为参数
cv2.waitKey(0) 等待按键,括号内表示等待的毫秒数,0 表示无限等待;在等待时间内按下任意键进行下一步,并返回键的 ASCII 值,或是等待时间结束后自动进行下一步
cv2.destroyAllWindows() 关闭所有窗口,括号内输入窗口名称则关闭指定窗口
可以定义一个函数

def cv_show(name, img, win_property=None):
	cv2.imshow(name, img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

之后使用cv_show('image_name' , image) 即可打开窗口查看图片,并在输入任意键后关闭窗口

3.图像保存

cv2.imwrite('output.jpg', image) 将处理后的图像保存到文件中,该函数接受保存的文件名和图像数组作为参数,位置在代码同一目录下,如果没有则会创建一个新文件来保存

4.读取视频

vc=cv2.VideoCapyure('video.mp4') 可以捕获摄像头,用 0,1 指定设备(默认唯一摄像头为 0 ),对视频则用路径即可,返回一个视频数组
vc.isOpened() 判断是否打开正确,返回布尔型
ret, frame=vc.read() 按帧读取取视频,返回储存在 ret 的布尔型,和储存在 frame 的图片数组;ret 代表是否正确读取视频,frame 储存一帧画面,并把指针移到下一帧,因此循环重复该代码可以一帧一帧读取视频
视频的显示也用cv2.imshow(),但需要循环读取和显示

vc=cv2.VideoCapyure('video.mp4')
ret, frame=vc.read()
if ret:#正确打开则执行
	cv2.imshow('frame', frame) #显示视频帧
	key=cv2.waitKey(10) #等待时间决定视频播放速度
	if key=27#读取键值esc退出
	break

vc.release() #释放视频

二、图像基本操作

1.数值运算

'img2=img[0:200 0:200]' 用列表切片截取部分图像
图片数组的运算即是像素灰度值的运算;图片数组加常数值代表图片每一个像素的灰度值都加这个常数
'print(img.shape)' 返回图片大小和颜色通道
'cv2.resaize(img, (宽, 长))' 或 'cv2.resaize(img, (0, 0), fx=倍宽系数, fy=倍长系数)' 修改图片大小
'cv2.addWeighted(img1, 权重, img2, 权重, 提亮等级)' 合并两张图片

2.颜色通道处理

b, g, r=cv2.split(img) 分别提取bgr三个颜色通道存入三个数组
img=cv2.merge((b, g, r)) 合并颜色通道
img[ : , : ,1]=0 调整颜色通道的输出情况,b,g,r对应0,1,2;=0表示不输出,=1输出
det=cv2.cvtColor(img, option) 按选择转换图片通道,选择(option)有:

cv2.COLOR_BGR2GRAY:转换为灰度通道图片,在滤波,边缘检测,轮廓检测等之前需要先转换 cv2.COLOR_BGR2HSV:转化为HSV色彩空间,用于颜色识别 cv2.COLOR_BGR2RGB:转换为RGB格式,颜色通道轮换

边界填充

cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType) 将图片按指定方式向外填充指定宽度,方式(borderType)有:

cv2.BORDER_CONSTANT: 使用常数值填充边界 cv2.BORDER_REFLECT: 边界像素是源图像边界像素的镜像反射 gfedcba|abcdefgh|hgfedcba cv2.BORDER_REFLECT_101: 与cv2.BORDER_REFLECT类似,但稍有不同 gfedcb|abcdefgh|gfedcba cv2.BORDER_REPLICATE: 使用源图像边界像素的值填充边界 cv2.BORDER_WRAP: 将源图像边界像素的值进行环绕填充 cdefgh|abcdefgh|abcdefg

3.图像阈值

ret, det=cv2.threshold(img, 阈值, 最大值, 二值化方式) 按一定方式将原图像素进行二值化,方式有:

cv2.THRESH_BINARY:大于阈值取最大值,否则取0 cv2.THRESH_BINARY_INVcv2.THRESH_BINARY的反转,大于阈值取0,否则取最大值 cv2.THRESH_TRUNC:大于阈值设为阈值 cv2.THRESH_TOZERO:小于阈值设为0 cv2.THRESH_TOZERO_INVcv2.THRESH_TOZERO的反转

4.图像滤波去噪

blur=cv2.blur(img, (3, 3)) 均值滤波,进行卷积,用一个值均为1的卷积核滑窗扫过图片,滑窗内像素点的均值代替滑窗中心像素点的值,接收图片数组和卷积核大小
gaussian=cv2.GaussianBlur(img, (5, 5), 0) 高斯滤波,卷积核的数值越靠近中间的越大,相当于更重视中间的,接收图片数组、卷积核大小和权重
median=cv2.medianBlur(img, 3) 中值滤波,取滑窗内像素点的中位数作为中心像素的值,接收图片数组和卷积核边长

5.形态学处理

卷积核

一个逐步滑过画面像素的滑窗,输出核的值与对应像素值乘积的和
kernel=np.ones((5, 5), np.unit8) 创建一个5×5的核,需要在接收核作为参数的函数之前创造

腐蚀与膨胀

erosion=cv2.erode(img, kernel, iterations=1) 腐蚀操作,只要核范围内存在黑像素,中心像素就变为黑,用于去除白噪声或断开连接,接收图片数组,卷积核,迭代次数(默认1) dilate=cv2.dilate(img, kernel, iteratuion=1) 膨胀操作,只要核范围内存在白像素,中心像素就变为白,一般除噪是先腐蚀再膨胀,接收图片数组,卷积核,迭代次数(默认1) det=cv2.morphologyEx(img, option, kernel, iteration=1) 按指定方式进行腐蚀膨胀复合运算,接收图片,方式函数,卷积核,迭代次数;方式(option)有:

cv2.MORPH_OPEN:开运算,先腐蚀后膨胀,用于移除由图像噪音形成的斑点 cv2.MORPH_CLOSE:闭运算,先膨胀后腐蚀,用来连接被误分为许多小块的对象 cv2.MORPH_GRADIENT:梯度运算,开运算-闭运算,形成中空图像 cv2.MORPH_TOPHAT:礼帽算法,原始输入-开运算 cv2.MORPH_BLACKHA:黑帽算法,闭运算-原始输入

6.边缘检测

Sobel算子

设置邻域权重不同的卷积核,对x或y方向进行像素梯度计算,通过高梯度确定边缘信息
sobelx=cv2.Sobel(img, CV_64F, 1, 0, ksize=3) 接收图片,图片深度(存储位数,建议 CV_64F ),梯度计算方向(dx,dy用1,0或0,1决定在x或y方向上),边缘检测模板大小
sobelx=cv2.convertScaleAbs(sobelx) Sobel算子计算结果有正有负,需要绝对值转换
sobel=cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) 分别计算x和y再求和得到梯度方向

Scharr算子

对斜向边缘更敏感,对噪声也更敏感

scharrx=cv2.Scharr(img, cv2.CV_64F, 1, 0) #与sobel相同  
scharrx=cv2.convertScaleAbs(scharrx)  #需要绝对值转换  

Laplacian算子

不用分xy方向,对边缘更不敏感

laplacian = cv2.Laplacian(img, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian) #绝对值转换 

Canny边缘检测流程

  1. 高斯滤波,平滑处理滤除噪声
  2. Sobel算子计算梯度
  3. 非极大值抑制(比较该像素点和其梯度正负方向(垂直边界)的像素点的梯度强度,如果该点梯度强度最大则保留,否则抑制为0)
  4. 双阈值检测来确定真实和潜在的边界,抑制孤立的弱边缘完成边缘检测(设置一个阈值上界和阈值下界,强度超过上界的为强边界(必然是边界,保留),低于下界的必然不是边界(抛弃),介于上下界之间的为弱边界(与强边界相连则保留,否则抛弃))
det=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gaussian=cv2.GaussianBlur(det, (5, 5), 0)
canny=cv2.Canny(img, 下界, 上界) #canny算子进行边缘检测,接收图片和上下界
cv_show('canny', canny)

7.图像金字塔

用于分层提取图片信息

高斯金字塔

up=cv2.pyrUp(img) 向上采样,变大,边长倍长 down=cv2.pyrDown(img) 向下采样,变小,边长减半

拉普拉斯金字塔

down=cv2.pyrDown(img) #先向下采样
down_up=cv2.pyrUp(down) #再向上采样
img2=img-down_up #原始数据-采样数据

8.图像轮廓

获取轮廓

cv2.findContours(binary, mode, method) 按照一定的轮廓检索模式和轮廓逼近方法输出图像轮廓 轮廓检索模式(mode)有:

RETR_TREE:检索所有轮廓,并重构嵌套轮廓的整个层次,最常用 RETR_EXTERNAL:只检索最外围的轮廓 RETR_LIST:检索所有轮廓,并保存到一条链表中 RETR_CCOMP:检索所有轮廓,并组织为两层,顶层为各部分外部边界,第二层为空洞的边界 轮廓逼近方法(method)有: CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形顶点的序列 CHAIN_APPROX_SIMPLE:压缩水平、垂直和斜的部分,函数只保留终点的部分 接收的是二值图,所以需要先ret, binary=cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) 进行二值化处理
contours, hierarchy=cv2.findContours(binary, RETR_TREE, CHAIN_APPROX_NONE) 返回轮廓信息列表和轮廓对应属性列表

绘制轮廓

draw=img.copy() #绘制会改变原图,首先要复制图片
res=cv2.drawContours(darw, contours, -1, (0, 0, 255), 2) #接收图片,轮廓信息列表, 绘制轮廓序号(-1代表全绘制),绘制线条的bgr颜色通道,线条宽度
cv_show('res', res) #显示

轮廓特征

需要从轮廓列表中取出单个轮廓,如cnt=contour[0],用函数可以算面积周长等,如cv2.arcLength(cnt, True) 算周长

轮廓近似

epsilon=0.1*cv2.arcLength(cnt, True) #用0.1倍周长做阈值
approx=cv2.approxPolyDP(cnt, epsilon, True) #接收一个轮廓,阈值,阈值越小近似越拟合,返回一个轮廓
res=cv2.drawContours(draw, [approx], -1, (0, 0, 255), 2) #在图上绘制
cv_show('res', res) #显示

边界矩形

x, y, w, h=cv2.boundingRect(cnt) #接收一个轮廓,返回边界矩形的坐标和宽高
draw=cv2.rectangle(draw, (x, y), (x+w, y+h), (0, 0, 255), 2) #绘制边界矩形

9.图像增强

equ = cv2.equalizeHist(image) 直方图均衡化,使图像的亮度分布更加均匀 contrast = cv2.convertScaleAbs(image, alpha=1.5, beta=0) 对比度拉伸,扩大亮度范围增强对比度 gamma = cv2.pow(image, 0.5) 伽马校正,改变亮度和对比度

10.颜色识别

HSV颜色空间由三个分量组成:色相、饱和度和明度

import cv2
import numpy as np #引入库
img=cv2.imread('image.jpg') #读取图像
hsv=cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #先转换为HSV颜色空间
lower_red=np.array([0, 100, 100])
upper_red=np.array([10, 255, 255]) #创建代表所需颜色HSV上下限的数组
mask=cv2.inRange(hsv, lower_red, upper_red) #创建颜色掩膜进行二值化,在范围内的像素设置为255(白色),其他像素则设置为0(黑色)
kernel = np.ones((5, 5), np.uint8)
red_mask = cv2.morphologyEx(red_mask, cv2.MORPH_OPEN, kernel) #形态学处理去除噪声
contours, _ = cv2.findContours(red_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) #输出轮廓信息列表
copy=img.copy() #复制图片用于绘制
for contour in contours: #遍历列表中的轮廓
	x, y, w, h = cv2.boundingRect(contour) #输出边界矩形
	if cv2.contourArea(contour) > 500: #设置最小面积排除噪声
		if np.any(red_mask[y:y+h, x:x+w]): 可以判断在掩膜的对应位置是否为白色(即原图是否确实为所需颜色)
			cv2.rectangle(copy, (x, y), (x+w, y+h), (0, 0, 255), 2) #绘制边界矩形
			cv2.putText(copy, f '( {x}, {y} )' , (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 1) 绘制文本,接收图片、文字、位置、字体类型、大小、颜色、粗细
cv2.imshow('image', copy)
cv2.waitKey(0)
cv2.destroyAllWindows() #输出图像