Bootstrap

新手小白包会(python) | OpenCV进阶教程,带你踏入计算机视觉领域

目录

一、OpenCV简介

1.应用场景

2.学习与使用

二、OpenCV安装 

1.安装

2.验证

三、OpenCV使用

1.边缘检测

1)sobel算子(cv2.Sobel())

 2)Scharr算子(cv.Scharr())

 3)laplacian(cv2.Laplacian())

4)canny算法(cv.Canny())

2.下采样(cv2.pyrDown())

3.上采样(cv2.pyrUp())

4.拉普拉斯金字塔

5.mask掩膜

mask掩膜用法(cv2.bitwise_and())

 6.直方图均衡化(cv2.equalizeHist())

7.自适应直方图均衡化(cv2.createCLAHE())

四、OpenCV进阶操作

1.模板匹配(cv2.matchTemplate())

2.角点检测(cv2.cornerHarris())

3.特征提取SIFT

五、总结


 本篇文章为OpenCV进阶教程,想学基础篇的朋友可前往 OpenCV入门教程 !!!

一、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 cv2print(cv2.__version__)来验证OpenCV是否安装成功以及安装的版本号。

三、OpenCV使用

1.边缘检测

1)sobel算子(cv2.Sobel())

cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
参数:
        src:输入图像
        ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度
        dx,dy:当组合为dx=1,dy=0时求x方向的一阶导数,当组合为dx=0,dy=1时求y方向的一阶导数                   (如果同时为1,通常效果不佳)
        ksize:(可选参数)Sobel算子的大小,必须是1,3,5或者7,默认为3。

读取x方向边缘

# x方向的边缘
yuan = cv2.imread('./yuan.png')
yuan_x = cv2.Sobel(yuan, -1, dx=1, dy=0)

cv2.imshow('yuan', yuan)
cv2.waitKey(0)
cv2.imshow('yuan_x ', yuan_x)
cv2.waitKey(0)

该方法只能读取到左半边边缘,要想得到x方向整体边缘,需将ddeep=-1改为cv2.CV_64F

x方向整体边缘

# 如何得到x方向整体的边缘?
yuan_x_64f = cv2.Sobel(yuan, cv2.CV_64F, dx=1, dy=0)  # 默认uint8改为float64,可保存负数
yuan_x = cv2.convertScaleAbs(yuan_x_64f)  # 转换为绝对值,负数转换为正数

 同理可得y方向整体边缘

# y方向的边缘
yuan_y_64f = cv2.Sobel(yuan, cv2.CV_64F, dx=0, dy=1)
yuan_y = cv2.convertScaleAbs(yuan_y_64f)

通过加权运算将x,y方向边缘图像加起来 

# x, y 同时使用
yuan_xy = cv2.Sobel(yuan, -1, dx=1, dy=1)
# 使用图像加权运算组合x和y方向的2个边缘。
yuan_addWeight = cv2.addWeighted(yuan_x, 1, yuan_y, 1, 0)

 2)Scharr算子(cv.Scharr())

cv.Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]])
        src:输入图像
        ddepth:输出图片的数据深度,由输入图像的深度进行选择
        dx:x 轴方向导数的阶数
        dy:y 轴方向导数的阶数

phone = cv2.imread('./phone.jpg', cv2.IMREAD_GRAYSCALE)  # 转换灰度图,也可以不转换
phone_x = cv2.Scharr(phone, cv2.CV_64F, dx=1, dy=0)
phone_y = cv2.Scharr(phone, cv2.CV_64F, dx=0, dy=1)
phone_x_convert = cv2.convertScaleAbs(phone_x)
phone_y_convert = cv2.convertScaleAbs(phone_y)
phone_add_weight = cv2.addWeighted(phone_x_convert, 1, phone_y_convert, 1, 0)

 3)laplacian(cv2.Laplacian())

cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
参数说明:
        src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
        ddepth:输出图片的数据深度:
        ksize:计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
        scale:缩放比例因子,可选项,默认值为 1
        delta:输出图像的偏移量,可选项,默认值为 0

lap = cv2.imread('./phone.jpg')
lap_64f = cv2.Laplacian(lap, cv2.CV_64F)  # 默认uint8改为float64,可保存负数
lap_convert = cv2.convertScaleAbs(lap_64f)  # 转换为绝对值,负数转换为正数

效果不是很好

4)canny算法(cv.Canny())

cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
image:为输入图像。
threshold1:表示处理过程中的第一个阈值。
threshold2:表示处理过程中的第二个阈值。
threshold:不固定, 默认小的那个是最小阈值, 大的是最大阈值(大于高阈值的为强边缘, 小于低阈值的为弱边缘)

peng = cv2.imread('./peng.jpg', cv2.IMREAD_GRAYSCALE)
peng_canny = cv2.Canny(peng, 30, 100)
peng_canny_2 = cv2.Canny(peng, 100, 200)

 

2.下采样(cv2.pyrDown())

dst = cv2.pyrDown(src, dst, dstsize)
        dst:目标图像
        src:原始图像
        dstsize:目标图像的大小(可以不设置)

zhang = cv2.imread('./zhang.jpg')  # 读取图像
down_1 = cv2.pyrDown(zhang)  # 下采样

3.上采样(cv2.pyrUp())

高斯金字塔操作中的向上采样
dst = cv2.pyrUp(src, dst, dstsize)
dst:目标图像
src:原始图像
dstsize:目标图像的大小

up_1 = cv2.pyrUp(zhang)
cv2.imshow('up1', up_1)
cv2.waitKey(0)

 

4.拉普拉斯金字塔

zhang = cv2.imread('./zhang.jpg')  # 读取图像
down = cv2.pyrDown(zhang)  # 下采样
down_up = cv2.pyrUp(down)  # 上采样
# 差值,经过下采样上采样后图像损失的像素值
differ = zhang - down_up
# 处理后再加上差值,即可返回原图
zhang1 = down_up + differ

5.mask掩膜

phone = cv2.imread('./phone.jpg', cv2.IMREAD_GRAYSCALE)  # 彩图灰度图均可
# 将掩膜的尺寸设置与phone相同
mask = np.zeros(phone.shape[:2], np.uint8)  # 创建黑白图像,用于制作mask
mask[50:350, 100:470] = 255  # 设置部分区域为255亮度
cv2.imshow('mask', mask)
cv2.waitKey(0)

mask掩膜用法(cv2.bitwise_and()

cv2.bitwise_and():对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0
bitwise_and(src1, src2, dst=None, mask=None)

参数:
src1、src2:为输入图像或标量,标src1和src2相与。
dst:可选输出变量,如果需要使用非None则要先定义,且其大小与输入变量相同
mask:图像掩膜,可选参数,用于指定要更改的输出图像数组的元素,mask为0的值,src1和src2相与的值都为0.非0的值,为src1和src2相与的值。

phone_mask = cv2.bitwise_and(phone, phone, mask=mask)

 我的另一篇博客,小金鱼图像提取裁剪最后也用到了mask掩膜方法,可参考图像提取裁剪

 6.直方图均衡化(cv2.equalizeHist())

直方图均衡化:直方图均衡化是一种图像增强技术,它可以通过增加图像的对比度和亮度来改善图像的质量。
直方图均衡化通过将图像的像素值分布均匀化来实现这一目标。
在Python OpenCV中,可以使用cv2.equalizeHist()函数来实现直方图均衡化。
该函数将输入图像转换为灰度图像,并将其像素值分布均匀化,从而增强图像的对比度和亮度。

image = cv2.imread('./zhang.jpg', cv2.IMREAD_GRAYSCALE)
image_equal = cv2.equalizeHist(image)
# 横向拼接,将多个数组按水平方向(列顺序)堆叠成一个新的数组
res = np.hstack((image, image_equal))
cv2.imshow('res', res)
cv2.waitKey(0)

7.自适应直方图均衡化(cv2.createCLAHE())

自适应直方图均衡化(局部直方图处理),当需要保存细节特征,需要做局部处理
cv2.createCLAHE(clipLimit, tileGridSize) → retval
参数说明:
clipLimit:颜色对比度的阈值,可选项,默认值 8
titleGridSize:局部直方图均衡化的模板(邻域)大小,可选项,默认值 (8,8)

clahe = cv2.createCLAHE(clipLimit=1.0, tileGridSize=(16, 16))  # 自适应
image_clahe = clahe.apply(image)  # 应用到image图像上
res = np.hstack((image, image_equal, image_clahe))  # 将上步操作一起拿来做对比
cv2.imshow('res', res)
cv2.waitKey(0)

 

四、OpenCV进阶操作

1.模板匹配(cv2.matchTemplate()

cv2.matchTemplate(image, templ, method, result=None, mask=None)
image:待搜索图像
templ:模板图像
method:计算匹配程度的方法,可以有:
        TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;匹配越好,值越小;匹配越                                                               差,值越大。
        TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
        TM_CCOEFF 相关系数匹配法:数值越大表明匹配程度越好。
        TM_SQDIFF_NORMED 归一化平方差匹配法:匹配越好,值越小;匹配越差,值越大。
        TM_CCORR_NORMED 归一化相关匹配法:数值越大表明匹配程度越好。
        TM_CCOEFF_NORMED 归一化相关系数匹配法:数值越大表明匹配程度越好。

# 读取图像
kele = cv2.imread('./kekou.jpg')
# 读取模板图像
template = cv2.imread('./template.jpg')
# 获取模板图像高宽,方便后面进行框图
h, w = template.shape[:2]
# 建立模板匹配
match = cv2.matchTemplate(kele, template, cv2.TM_CCORR_NORMED)
# cv2.minMaxLoc可以获取矩阵中的最小值和最大值,以及最小值的索引号和最大值的索引号
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(match)  # 最小值、最大值、最小值位置、最大值位置
top_left = max_loc  # 得到的位置均为左上角位置
bottom_right = (top_left[0] + w, top_left[1] + h)  # 右下角位置
# 绘制矩形框
template_rect = cv2.rectangle(kele, top_left, bottom_right, color=(255, 0, 0), thickness=3)
cv2.imshow('match_template', template_rect)
cv2.waitKey(0)

2.角点检测(cv2.cornerHarris())

cornerHarris(img, blockSize, ksize, k) -> dst
* img: 输入图像
* blockSize: 角点检测中要考虑的领域大小
* ksize: Sobel 求导中使用的窗口大小
* k: Harris 角点检测方程中的自由参数, 取值参数为[0.04, 0.06]
* dst: 返回numpy,ndarray 对象, 大小和src相同, 值越大, 对应像素点是角的概率越高

img = cv2.imread('./huangHeLou.jpg')
# 角点检测需要转换为灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 角点检测  
dst = cv2.cornerHarris(img_gray, 4, 3, 0.04)
# 每个点得到的结果值大于最大角点值的0.01倍,即认为该点为角点,并用[0, 0, 255]红色绘制出
img[dst > 0.01 * dst.max()] = [0, 0, 255]
cv2.imshow('img', img)
cv2.waitKey(0)

3.特征提取SIFT

cv2.SIFT_create()    #创建一个sift特征的提取对象
sift.detect(img)        #在图像中查找关键点

zhang = cv2.imread('./zhang.jpg')
sift = cv2.SIFT_create()  #创建角点检测
kp = sift.detect(zhang)   #对图像进行角点检测,得到关键点

drawKeypoints(image, keypoints, outImage, color=None, flags=None)
image:原始图片
keypoints:从原图中获得的关键点,这也是画图时所用到的数据
outputimage:输出图像,可以是原始图片,也可以是None
color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
flags:绘图功能的标识设置

zhang_sift=cv2.drawKeypoints(zhang,kp,None,flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)
cv2.imshow('zhang_sift', zhang_sift)
cv2.waitKey(0)

五、总结

        OpenCV进阶涉及图像高级处理、特征提取、角点检测与模板匹配等。通过深入学习,可掌握图像分析与理解的精髓,为计算机视觉应用奠定坚实基础。

后续会对进阶篇做一些完善,还会补充一些opencv进阶操作,感谢支持!

本篇文章为OpenCV进阶教程,想学基础篇的朋友可前往 OpenCV入门教程 !!! 

想要实操的同学可前往-项目实战--OpenCV--信用卡识别

                                                    --OpenCV--小金鱼图像提取裁剪

;