Python新手入门 | OpenCV计算机视觉教程,带你探索视觉领域
目录
一、OpenCV简介
1.应用场景
2.学习与使用
二、OpenCV安装
1.安装
2.验证
三、OpenCV使用
1.图片读取与展示(cv2.imread() | cv2.imshow())
2.图片灰度图(cv2.IMREAD_GRAYSCALE)
3.图片保存(cv2.imwrite())
4.视频读取(cv2.VideoCapture())
5.图像截取
6.提取与合并RGB颜色通道
1)提取(B, G, R = cv2.split(pic))
2)合并(cv2.merge((B, G, R)))
7.图片修改
1)图片组合
2)图片缩放(cv2.resize())
8.图像运算
1)图像加法运算(cv2.add(pic_1, pic_2))
2)图像加权运算(cv2.addWeighted())
9.边界填充(cv2.copyMakeBorder())
10.阈值处理(cv2.threshold())
11.图像平滑处理
1)均值滤波(cv2.blur)
2)方差滤波(cv2.boxFilter())
3)高斯滤波(cv2.GaussianBlur())
4)中值滤波(cv2.medianBlur())
12.图像形态学(cv2.morphologyEx)
1)图像腐蚀(cv2.erode())
2)图像膨胀(cv2.dilate())
3)图像开运算与闭运算(cv2.MORPH_OPEN()、cv2.MORPH_CLOSE())
4)顶帽、黑帽运算(cv2.MORPH_TOPHAT()、cv2.MORPH_BLACKHAT())
13.轮廓检测(cv2.findContours())
14.绘制轮廓(cv2.drawContours())
四、基础篇总结
一、OpenCV简介
OpenCV,即开源计算机视觉库(Open Source Computer Vision Library),是一个广泛使用的计算机视觉和图像处理软件库。它提供了大量的算法和函数,用于图像和视频处理、目标检测、机器学习等任务。
1.应用场景
OpenCV在卫星和网络地图上拼接图像、图像扫描校准、医学图像的降噪、目标分析、安保以及工业检测系统等多个领域都有广泛的应用。此外,OpenCV还在自动驾驶和安全系统、制造感知系统、相机校正、军事应用以及无人空中、地面、水下航行器等方面发挥着重要作用。
2.学习与使用
OpenCV为初学者提供了丰富的教程和示例代码,帮助他们快速入门和提高。开发者可以通过阅读OpenCV的官方文档、参加在线课程或加入社区论坛等方式获取帮助和支持。
随着对OpenCV的深入了解和实践经验的积累,开发者将能够更加熟练地运用这个强大的计算机视觉库来解决实际问题。
二、OpenCV安装
1.安装
打开终端,输入 pip install opencv-python 即可,如需指定版本,输入 pip install opencv-python==版本号 即可。
2.验证
打开Python解释器。
输入import cv2
和 print(cv2.__version__)
来验证OpenCV是否安装成功以及安装的版本号。
三、OpenCV使用
1.图片读取与展示(cv2.imread() | cv2.imshow())
pic = cv2.imread('图片路径') # 读取图片
cv2.imshow('pic', pic) # 显示图片(自定义名称, 图片数据)
cv2.waitKey(ms) # 在一个给定的时间内(ms)等待用户按键触发, 到时自动结束
cv2.destroyAllWindows() # 关闭所有打开的窗口并释放所有相关内存
cv2.imread():传入图片路径及图片后缀;
cv2.imshow():参数1:自定义的图片名称,参数2:传入读取到的图片;
cv2.waitKey():传入图片展示等待的时间,传入0图片会一直展示,直到按任意键退出;
cv2.destroyALLWindows():关闭所有打开的窗口,无需传入参数。
2.图片灰度图(cv2.IMREAD_GRAYSCALE)
#方法一
pic_gray = cv2.imread('图片路径', cv2.IMREAD_GRAYSCALE)
#方法二
pic_gray = cv2.cvtColor(pic, cv2.COLOR_BGR2GRAY)
方法一:读取时直接读取灰度图
方法二:将读取到的原图转换为灰度图
3.图片保存(cv2.imwrite())
cv2.imwrite('保存路径', pic)
cv2.imwrite():参数1:需要保存到的路径,记得加图片后缀,不然会保存失败,参数2:要保存的图片
4.视频读取(cv2.VideoCapture())
vc = cv2.VideoCapture('视频路径')
if vc.isOpened(): # 判断vc视频是否正确打开
open_vd, frame = vc.read() # 读取每一帧视频。返回值1为读取是否有内容,Fasle表示读取结束。返回值2为这一帧的图片内容
else:
open_vd = False
while open_vd: (open_vd=True则一直运行)
open_vd, frame = vc.read()
if frame is None: # 读取完毕之后,frame的值为None
break
cv2.imshow('frame', frame)
if cv2.waitKey(50) == 27: # cv2.waitKey获取键盘符号的ASCII码,27为键盘Esc键
break
vc.release() # 是cv2.VideoCapture对象的一个方法,用于释放视频捕获器的资源。在调用该方法后,视频捕获器将不再使用,因此应该在使用完毕后立即调用该方法。
视频读取的原理就是基于每一帧进行读取与处理
vc.read():返回值1:为布尔值,True为有内容,False为未读取到内容,返回值2:视频这一帧的图像
5.图像截取
pic_roi = pic[200:800, 400:800]
pic_roi = pic[高, 宽]
6.提取与合并RGB颜色通道
1)提取(B, G, R = cv2.split(pic))
#方法一
B = pic[:, :, 0] # B
G = pic[:, :, 1] # G
R = pic[:, :, 2] # R
#方法二
B, G, R = cv2.split(pic)
# 只保留B通道
pic[:, :, 1] = 0 # G通道设为0
pic[:, :, 2] = 0 # R通道设为0
2)合并(cv2.merge((B, G, R)))
pic = cv2.merge((B, G, R))
也可用这种方式将图像1通道转换为3通道,例如:pic = cv2.merge((pic_gray, pic_gray, pic_gray))
7.图片修改
1)图片组合
方法一
pic_gray = np.stack((pic_gray) * 3, axis=-1) # 将灰度图片1通道转换成3通道
方法二
pic_gray = cv2.merge((pic_gray, pic_gray, pic_gray)) # 将灰度图片1通道转换成3通道
图片组合
pic1[100:200, 100:200] = pic2[300:400, 400:500] # 矩阵大小必须要统一
2)图片缩放(cv2.resize())
pic_resize = cv2.resize(pic, (200, 200))
cv2.resize(src, dsize)
src:要调整大小的输入图像;
dsize:输出图像的大小,可以是一个元组,例如(宽,高),或者使用整数标量来缩放原始图像。
8.图像运算
1)图像加法运算(cv2.add(pic_1, pic_2))
对于 + 运算, 有两种方法,当对图像a, 图像b进行加法求和时, 遵循以下规则:
当某位置像素相加得到的数值小于255时, 该位置数值为两图像位置像素相加之和
当某位置像素相加得到的数值大于255时, 该位置数值为两图像位置像素相加之和对255取模
方法一
pic_1 = pic_1 + 40 # 亮度增加40
#这里假设pic_1尺寸小于pic_2尺寸,要保证相加的两张图片尺寸一致
pic_3 = pic_1 + pic_2[100:300, 400:500]
#这里假设pic_1尺寸与pic_2尺寸相等
pic_3 = pic_1 + pic_2
方法二
pic_3 = cv2.add(pic_1, pic_2)
2)图像加权运算(cv2.addWeighted())
就是在计算两幅图像的像素值之和时,将每幅图像的权重考虑进来,可以用公式表示为dst=src1×α+src×β+γ
pic_3 = cv2.addWeighted(pic_1, 0.5, pic_2, 0.5, 10)
9.边界填充(cv2.copyMakeBorder())
# cv2.copyMakeBorder()是OpenCV库中的一个函数,用于给图像添加额外的边界(padding)。
# copyMakeBorder(src: UMat, top: int, bottom: int, left: int, right: int, borderType: int, dst: UMat | None = ..., value: cv2.typing.Scalar = ...)
# 它有以下几个参数:
# src:要扩充边界的原始图像。
# top, bottom, left, right:相应方向上的边框宽度。
# borderType:定义要添加边框的类型,它可以是以下的一种:
# cv2.BORDER_CONSTANT:添加的边界框像素值为常数(需要额外再给定一个参数)。
# cv2.BORDER_REFLECT:添加的边框像素将是边界元素的镜面反射,类似于gfedcba|abcdefgh|hgfedcba。
# cv2.BORDER_REFLECT_101 或 cv2.BORDER_DEFAULT:和上面类似,但是有一些细微的不同,类似于gfedcb|abcdefgh|gfedcba
# cv2.BORDER_REPLICATE:使用最边界的像素值代替,类似于aaaaaa|abcdefgh|hhhhhhh
# cv2.BORDER_WRAP:左右两边替换,cdefgh|abcdefgh|abcdefg
top, bottom, left, right = 50, 50, 50, 50
constant =cv2.copyMakeBorder(pic,top,bottom,left,right,borderType=cv2.BORDER_CONSTANT, value=100)
reflect = cv2.copyMakeBorder(pic, top,bottom,left,right,borderType=cv2.BORDER_REFLECT)
reflect_101=cv2.copyMakeBorder(pic,top,bottom,left,right,borderType=cv2.BORDER_REFLECT_101)
replicate=cv2.copyMakeBorder(pic,top,bottom,left,right,borderType=cv2.BORDER_REPLICATE)
wrap = cv2.copyMakeBorder(pic, top, bottom, left, right, borderType=cv2.BORDER_WRAP)
效果展示:
10.阈值处理(cv2.threshold())
选项 像素值>thresh 其他情况
cv2.THRESH_BINARY maxval 0
cv2.THRESH_BINARY_INV 0 maxval
cv2.THRESH_TRUNC thresh 当前灰度值
cv2.THRESH_TOZERO 当前灰度值 0
cv2.THRESH_TOZERO_INV 0 当前灰度值
# 阈值处理是指剔除图像内像素值高于一定值或低于一定值的像素点。例如,设定阈值为127.使用的方法为:
# retval,dst=cv2.threshold(src,thresh,maxval,type)thresh:100,maxval:200
# retval代表返回的阈值
# dst代表阈值分割结果图像,与原始图像具有相同的大小和类型
# src代表要进行阈值分割的图像,可以是多通道的,8位或32位浮点型数值
# thresh代表要设定的阈值
# maxval代表type参数位THRESH_BINARY或者THRESH_BINARY_INV类型时,需要设定的最大值
original = cv2.imread('图片路径', cv2.IMREAD_GRAYSCALE) # 灰度图
ret1, binary = cv2.threshold(original, 175, 255, cv2.THRESH_BINARY)
ret2, binary_inv = cv2.threshold(original, 175, 255, cv2.THRESH_BINARY_INV)
ret3, trunc = cv2.threshold(original, 175, 255, cv2.THRESH_TRUNC)
ret4, to_zero = cv2.threshold(original, 175, 255, cv2.THRESH_TOZERO)
ret5, to_zero_inv = cv2.threshold(original, 175, 255, cv2.THRESH_TOZERO_INV)
效果展示
11.图像平滑处理
1)均值滤波(cv2.blur)
# dst=cv2.blur(src,ksize,anchor,borderType)
# dst是返回值
# src是需要处理的图像
# kszie是滤波核(卷积核)的大小
# anchor是锚点,默认值是(-1,-1)一般无需更改
# borderType是边界样式,一般无需更改
# 一般情况下,使用dst=cv2.blur(src,ksize)即可
blur_1 = cv2.blur(pic, (3, 3))
2)方差滤波(cv2.boxFilter())
# dst=cv2.boxFilter(src,ddepth,ksize,anchor,normalize,borderType)式中:
# ● dst是返回值,表示进行方框滤波后得到的处理结果。
# ● src 是需要处理的图像,即原始图像。
# ● ddepth是处理结果图像的图像深度,一般使用-1表示与原始图像使用相同的图像深度。
# ● ksize 是滤波核的大小。滤波核大小是指在滤波处理过程中所选择的邻域图像的高 度和宽度。
# ● anchor 是锚点,
# ● normalize 表示在滤波时是否进行归一化。
# 1.当值为True时,归一化,用邻域像素值的和除以面积。此时方框滤波与均值滤波效果相同。
# 2.当值为False时,不归一化,直接使用邻域像素值的和。和>255时使用255
boxFilter_1 = cv2.boxFilter(pic, -1, (3, 3), normalize=True)
3)高斯滤波(cv2.GaussianBlur())
# cv2.GaussianBlur(src, ksize[, sigmaX[, sigmaY[, dst]]])高斯滤波
# 参数说明:
# src:输入图像,通常是一个NumPy数组。
# ksize:滤波器的大小,它是一个元组,表示在水平和垂直方向上的像素数量。例如,(5, 5)表示一个5x5的滤波器。
# sigmaX和sigmaY:分别表示在X轴和Y轴方向上的标准差。这些值与滤波器大小相同。默认情况下,它们都等于0,这意味着没有高斯模糊。
# dst:输出图像,通常是一个NumPy数组。如果为None,则会创建一个新的数组来存储结果
gaussian = cv2.GaussianBlur(pic, (3, 3), 0)
4)中值滤波(cv2.medianBlur())
# cv2.medianBlur(src, ksize[, dst])中值滤波
# 参数说明:
# src:输入图像。
# ksize:滤波器的大小,它是一个整数,表示在水平和垂直方向上的像素数量。例如,5表示一个5x5的滤波器。
# dst:输出图像,通常是一个NumPy数组。如果为None,则会创建一个新的数组来存储结果。
median = cv2.medianBlur(pic, 3)
效果展示:
原图:
处理图:
12.图像形态学(cv2.morphologyEx)
1)图像腐蚀(cv2.erode())
cv2.erode(src, kernel, iterations)
# src: 输入的图像
# kernel: 用于腐蚀的结构元件如果element = Mat(),则使用3 × 3的矩形结构单元。
# iterations:腐蚀操作的迭代次数,默认为1。次数越多, 腐蚀操作执行的次数越多,腐蚀效果越明显
sun = cv2.imread('./sun.png')
kernel = np.ones((10, 10), np.uint8)
pic_erode = cv2.erode(sun, kernel, iterations=3)
2)图像膨胀(cv2.dilate())
pic_dilate = cv2.dilate(sun, kernel, iterations=1)
3)图像开运算与闭运算(cv2.MORPH_OPEN()、cv2.MORPH_CLOSE())
# 开运算:先腐蚀后膨胀。闭运算:先膨胀后腐蚀
pic_open = cv2.morphologyEx(sun, cv2.MORPH_OPEN, kernel)
pic_close = cv2.morphologyEx(sun, cv2.MORPH_CLOSE, kernel)
效果展示:
4)顶帽、黑帽运算(cv2.MORPH_TOPHAT()、cv2.MORPH_BLACKHAT())
# 顶帽 = 原始图像 - 开运算结果(先腐蚀后膨胀)
# 黑帽 = 闭运算(先膨胀后腐蚀) - 原始图像
# 用来检测处理后图像与原图像之间的变化
kernel = np.ones((2, 2), np.uint8)
top = cv2.morphologyEx(sun, cv2.MORPH_TOPHAT, kernel)
black = cv2.morphologyEx(sun, cv2.MORPH_BLACKHAT, kernel)
效果图展示:
13.轮廓检测(cv2.findContours())
注意这是3版本的opencv,4版本的返回值没有image
# 查找轮廓的API:image, contours, hierarchy = cv2.findContours(img, mode, method)
# 参数:img:需要实现轮廓检测的原图
# mode: 轮廓的检索模式
# method:轮廓的近似方法
# 返回:image:返回处理的原图
# contours:包含图像中所有轮廓的list对象。其中每一个独立的轮廓信息以边界点坐标(x,y)的形式储存在numpy数组中。
# hierarchy:轮廓的层次结构。一个包含4个值的数组:[Next, Previous, First Child, Parent]
# Next:与当前轮廓处于同一层级的下一条轮廓
# Previous:与当前轮廓处于同一层级的上一条轮廓
# First Child:当前轮廓的第一条子轮廓
# Parent:当前轮廓的父轮廓
# 注意:做轮廓检测前需要将图片读取为二值数据,即像素值只为0和255。
mode: 轮廓的检索模式,主要有四种方式:
cv2.RETR_EXTERNAL:只检测外轮廓,所有子轮廓被忽略
cv2.RETR_LIST:检测的轮廓不建立等级关系,所有轮廓属于同一等级
cv2.RETR_CCOMP:返回所有的轮廓,只建立两个等级的轮廓。一个对象的外轮廓为第1级组织 结构。而对象内部中空洞的轮廓为第2级组织结构,空洞中的任何对象的轮 廓又是第 1 级组织结构。
cv2.RETR_TREE:返回所有的轮廓,建立一个完整的组织结构的轮廓。
method:轮廓的近似方法,主要有以下两种:
cv2.CHAIN_APPROX_NONE:存储所有的轮廓点。
cv2.CHAIN_APPROX_SIMPLE:压缩模式,只保留该方向的终点坐标,例如一个矩形轮廓只需4 个点来保存轮廓信息。
image, contours, hierarchy = cv2.findContours(pic, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
该方法是平时较常用的轮廓提取方法
14.绘制轮廓(cv2.drawContours())
# cv2.drawContours(image, contours, contourIdx, color, thickness=None,
# lineType=None, hierarchy=None, maxLevel=None, offset=None)
# 参数含义如下:
# image:要在其上绘制轮廓的输入图像。
# contours:轮廓列表,通常由cv2.findContours()函数返回。
# contourIdx:要绘制的轮廓的索引。如果为负数,则绘制所有轮廓。 -1
# color:轮廓的颜色,以BGR格式表示。例如,(0, 255, 0)表示绿色。
# thickness:轮廓线的粗细。默认值为1。
# lineType:轮廓线的类型。默认值为cv2.LINE_8。
# hierarchy:轮廓层次结构。通常由cv2.findContours()函数返回。
# maxLevel:绘制的最大轮廓层级。默认值为None,表示绘制所有层级。
# offset:轮廓点的偏移量。默认值为None。
contours为上一步操作 findcontours 检测出的轮廓
phone_draw = cv2.drawContours(phone, contours=contours, contourIdx=-1, color=(0, 0, 255), thickness=3)
四、基础篇总结
OpenCV是一个功能强大的计算机视觉库,为开发者提供了丰富的算法和工具。通过入门教程的学习,我们掌握了OpenCV的基础知识和常用功能,如图像读取、显示、处理和轮廓检测等。这些基础技能为我们在计算机视觉领域进一步探索和实践打下了坚实的基础。
后续会对基础篇做一些完善,还会补充一些opencv进阶操作,感谢支持!
想要实操的同学可前往-项目实战–OpenCV–信用卡识别
–OpenCV–小金鱼图像提取裁剪
作者:AI_茗