OpenCV

计算机视觉和图像处理

一、OpenCV简介

1.1 简介

OpenCV是⼀个计算机视觉处理开源软件库,⽀持与计算机视觉和机器学习相关的众多算法。

1.2 OpenCV部署

  1. 创建虚拟环境
    在Anaconda终端中创建虚拟环境OpenCV_env
conda create --name OpenCV_env

在这里插入图片描述

  1. 激活虚拟环境
conda activate OpenCV_env

在这里插入图片描述

  1. 安装OpenCV

安装OpenCV之前需要先安装numpy, matplotlib

pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述

如果我们要利用SIFT和SURF算法进行特征提取时,还需安装:

pip install opencv-contrib-python -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述

  1. 查看是否安装成功
import cv2
cv2.__version__

在这里插入图片描述

1.3 OpenCV模块

  • core模块实现了最核心的数据结构及其基本运算,如绘图函数、数组操作相关函数等。
  • highgui模块实现了视频与图像的读取、显示、存储等接口。
  • imgproc模块实现了图像处理的基础方法,包括图像滤波、图像的几何变换、平滑、阈值分割、形态学处理、边缘检测、目标检测、运动分析和对象跟踪等。
  • features2d模块用于提取图像特征以及特征匹配,nonfree模块实现了一些专利算法,如sift特征。
  • objdetect模块实现了一些目标检测的功能,经典的基于Haar、LBP特征的人脸检测,基于HOG的行人、汽车等目标检测,分类器使用CascadeClassification(级联分类)和Latent SVM等。

二、OpenCV基本操作

2.1 图像的基本操作

2.1.1 图像的IO操作

# 读取图像
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt

#以灰度图的方式读取图像
img = cv.imread("dog.jpg",0)
# 显示图像
# Jupyter Notebook 是一个基于 Web 的交互式计算环境,不支持传统的 GUI 窗口显示
# cv.imshow('image',img)
# cv.waitKey(0)
plt.imshow(img,cmap='gray')

在这里插入图片描述

# 以彩色图的方式读取图像
img1 = cv.imread("dog.jpg",1)
# img1[:,:,::-1]将BGR图像转换为RGB图像
plt.imshow(img1[:,:,::-1])

使用cv.imread()读取的图像是BGR,而matplot使用是的RGB图像
在这里插入图片描述

img.shape

在这里插入图片描述

# 图像保存
cv.imwrite('dog1.jpg',img)

在这里插入图片描述

2.1.2 绘制几何图像

# 创建图像
img = np.zeros((512,512,3),np.uint8)
# 直线的起点、终点、颜色、宽度
cv.line(img,(0,0),(512,512),(255,0,0),5)
# 圆形的圆心、半径、颜色、填充、宽度
cv.circle(img,(250,250),130,(0,255,0),-1,5)
# 矩形的左上角、右下角、颜色、宽度
cv.rectangle(img,(50,50),(450,450),(0,0,255),5)
# 图像中添加文字  文本、位置、字体、字体大小、颜色、宽度
cv.putText(img,"OpenCV",(130,250),cv.FONT_HERSHEY_COMPLEX,2,(255,0,255),2)
plt.imshow(img[:,:,::-1])
plt.show()

在这里插入图片描述

2.1.3 获取并修改图像的像素点

img2 = np.zeros((250,250,3),np.uint8)
plt.imshow(img2[:,:,::-1])

在这里插入图片描述

# 获取位置(50,200)的像素点
img2[50,200]

在这里插入图片描述

#获取位置(50,100)蓝色通道的强度值,0表示蓝色,1表示绿色,2表示红色
img2[50,100,0]

在这里插入图片描述

# 修改位置(50,100)的像素值
img2[50,100] = [255,0,0]
plt.imshow(img2[:,:,::-1])

在这里插入图片描述

2.1.4 获取图像的属性

img2.shape

在这里插入图片描述

img2.size

在这里插入图片描述

img2.dtype

在这里插入图片描述

2.1.5 图像通道的拆分和合并

# 通道拆分
b,g,r = cv.split(img1)
plt.imshow(b,cmap='gray')

在这里插入图片描述

# 通道合并
img3 = cv.merge((b,g,r))
plt.imshow(img3[:,:,::-1])

在这里插入图片描述

2.1.6 色彩空间的改变

# 将BGR通道图像转变为HSV通道图像
img3 = cv.cvtColor(img1,cv.COLOR_BGR2HSV)
plt.imshow(img3[:,:,::-1])

在这里插入图片描述

# 将BGR通道图像变为GRAY通道图像
img4 = cv.cvtColor(img1,cv.COLOR_BGR2GRAY)
plt.imshow(img4,cmap='gray')

在这里插入图片描述

2.2 算数操作

2.2.1 图像的加法

# 读取图像
img_sun = cv.imread('sun.jpg')
img_tree = cv.imread('tree.jpg')
plt.imshow(img_tree[:,:,::-1])

在这里插入图片描述

plt.imshow(img_sun[:,:,::-1])

在这里插入图片描述

# 查看图像形状
img_sun.shape,img_tree.shape

在这里插入图片描述
形状相同才能进行相加

# 缩小图形形状
img_sun = cv.resize(img_sun,(350,251))
img_sun.shape

在这里插入图片描述

# 加法操作
img_cvadd = cv.add(img_sun,img_tree)
img_add = img_sun+img_tree
fig,axes = plt.subplots(1,2,figsize=(10,8))
axes[0].imshow(img_cvadd[:,:,::-1])
axes[0].set_title("cv中的加法")
axes[1].imshow(img_add[:,:,::-1])
axes[1].set_title("直接相加")
plt.show()

在这里插入图片描述

2.2.2 图像的混合

# 读取图像
img_sun = cv.imread('sun.jpg')
img_tree = cv.imread('tree.jpg')

# 缩小图形形状
img_sun = cv.resize(img_sun,(350,251))

# 图像混合,gamma参数会影响最终图像的亮度
img5 = cv.addWeighted(img_sun,0.3,img_tree,0.7,0)

# 图像的显示
plt.imshow(img5[:,:,::-1])
plt.show()

在这里插入图片描述

三、OpenCV图像处理

3.1 图像的几何变换

3.1.1 几何变化

3.1.2 形态学操作

3.1.3 图像平滑

3.1.4 灰度直方图

3.1.5 直方图均衡化

3.2 图像的形态学操作

3.3 图像的平滑方法

3.4 直方图

3.5 边缘检测

3.6 模板匹配和霍夫变换的应用

3.7 图像变化-傅里叶变换

3.8 轮廓检测

3.9 图像分割

四、图像的特征提取与描述

  1. 图像特征要有区分性,容易被比较。一般认为角点、斑点等是比较好的图像特征
  2. 特征检测:找到图像中的特征
  3. 特征描述:对特征及其周围的区域描述

4.1 Harris角点检测

Harris角点检测的思想是通过图像的局部的小窗口观察图像,角点的特征是窗口沿任意方向移动都会导致图像灰度明显变化。

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 对棋盘进行角点检测
qipan = cv.imread("qipan.jpg")

gray = cv.cvtColor(qipan,cv.COLOR_BGR2GRAY)
gray = np.float32(gray)
# Harris角点检测
# 2,blockSize计算每个像素的角点响应时考虑的窗口大小
# 3,Sobel 算子用于计算图像的梯度,进而用于计算角点响应。
# 0.04,用于平衡角点检测的灵敏度
dst = cv.cornerHarris(gray,2,3,0.04)
# 设置阈值,选择 dst 中角点响应值大于阈值的像素位置
qipan[dst > 0.001*dst.max()] = [0,255,0]

plt.figure(figsize=(10,8))
plt.imshow(qipan[:,:,::-1])
plt.show()

在这里插入图片描述

4.2 Shi-Tomasi角点检测

tv = cv.imread("tv.jpg")
gray = cv.cvtColor(tv,cv.COLOR_BGR2GRAY)

# 提取角坐标
conners = cv.goodFeaturesToTrack(gray,1000,0.01,10)
# 绘制角点
for i in conners:
    # 将坐标展平为一维
    x,y = i.ravel()
    x,y = int(x),int(y)
    cv.circle(tv,(x,y),3,(0,255,0),-1)

plt.figure(figsize=(10,8))
plt.imshow(tv[:,:,::-1])
plt.show()

在这里插入图片描述

4.3 sift算法

通过多尺度空间检测极值点作为关键点,确保尺度不变性;再对关键点邻域进行方向赋值,确保旋转不变性,从而实现对图像特征的稳定提取。

tv = cv.imread("tv.jpg")

gray = cv.cvtColor(tv,cv.COLOR_BGR2GRAY)

# 实例化shif
sift = cv.xfeatures2d.SIFT_create()
# 角点检测:kp角点的信息包括坐标,方向等   des角点描述
kp, des = sift.detectAndCompute(gray,None)
# 绘制角点
cv.drawKeypoints(tv,kp,tv,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

plt.figure(figsize=(10,8))
plt.imshow(tv[:,:,::-1])
plt.show()

在这里插入图片描述

4.4 fast检测算法

若一个像素周围有一定数量的像素与该点像素值不同,则认为其为角点

tv = cv.imread("tv.jpg")

# 实例化fast对象
fast = cv.FastFeatureDetector_create(threshold=30)
# 检测关键的
kp = fast.detect(tv,None)
# 绘制关键点,默认开启非极大值抑制,抑制候选角点的重叠
img1 = cv.drawKeypoints(tv,kp,None,(0,0,255))

# 关闭非极大值抑制
fast.setNonmaxSuppression(0)
kp = fast.detect(tv,None)
img2 = cv.drawKeypoints(tv,kp,None,(0,0,255))

plt.figure(figsize=(10,8))
plt.subplot(121)
plt.imshow(img1[:,:,::-1])
plt.title("开启非极大值抑制")
plt.subplot(122)
plt.imshow(img2[:,:,::-1])
plt.title("关闭非极大值抑制")
plt.show()

在这里插入图片描述

4.5 orb角点检测

tv = cv.imread("tv.jpg")

# 实例化ORB
# nfeatures设置要检测的最大特征点数量
orb = cv.ORB_create(nfeatures=200)
# 角点检测 
kp,des = orb.detectAndCompute(tv,None)
# 绘制角点
cv.drawKeypoints(tv,kp,tv,(0,255,0))

plt.figure(figsize=(5,4))
plt.imshow(tv[:,:,::-1])
plt.show()

在这里插入图片描述

五、视频操作

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

5.1 视频读写

video_ying = cv.VideoCapture("赵丽颖.mp4")
# 查看是否捕获成功
video_ying.isOpened()

在这里插入图片描述

# 判断是否读取成功
while(video_ying.isOpened()):
    # 获取每一帧图像
    ret,frame = video_ying.read()
    if ret == True:
        cv.imshow("frame",frame)
    # 每一帧间隔50秒,按q退出
    if cv.waitKey(50) & 0xFF == ord('q'):
        break
# 释放VideoCapture对象,关闭视频文件
video_ying.release()
# 关闭OpenCV所创建的窗口
cv.destroyAllWindows()

5.2 视频保存

# 读取视频
cap = cv.VideoCapture("赵丽颖.mp4")

# 获取图像的属性(宽度和高度),并将其转换为整数
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))

# 创建保存视频的对象,设置编码格式,帧率,图像的宽度和高度
out = cv.VideoWriter('outpy.avi', cv.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (frame_width, frame_height))

# 循环读取视频中的每一帧图像
while True:
    # 获取视频中的每一帧图像
    ret, frame = cap.read()    
    # 如果读取成功,将每一帧图像写入到输出文件中
    if ret == True:
        out.write(frame)
    else:
        break

# 释放资源
cap.release()
out.release()
cv.destroyAllWindows()

5.3 视频追踪

目标:追踪视频中的小柯基

5.3.1 meanshift算法

简单,迭代次数少。但不能适应运动目标的形状和大小的变化

import cv2 as cv
import numpy as np
# 视频捕获
video_dog = cv.VideoCapture('dog.mp4')

# 获取第一帧图像,并指定目标位置
ret, frame = video_dog.read()

# 目标位置(行,高,列,宽)
r, h, c, w = 140, 230, 300, 150
track_window = (c, r, w, h)

# 指定目标的感兴趣区域
roi = frame[r:r+h, c:c+w]

# 计算直方图
# 转换色彩空间(HSV)
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)

# 去除低亮度的值(色调,饱和度,亮度)
mask = cv.inRange(hsv_roi, np.array((0, 100, 52)), np.array((180, 255, 255)))

# 计算直方图
# [0] 只计算第一个通道,即色调(hue)通道的直方图
# [180] 定义直方图bin数量
# [0,180] 计算从0到180之间的色调值的直方图
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])

# 归一化
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)

# 目标追踪
# 设置窗口搜索终止条件:最大迭代次数,窗口中心漂移最小值
term_crit = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)

while True:
    # 获取每一帧图像
    ret, frame = video_dog.read()
    if ret:
        # 算直方图的反向投影,生成一个概率图 dst,指示当前帧中哪些区域最可能包含目标。
        hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
        dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

        # 进行Meanshift追踪
        ret, track_window = cv.meanShift(dst, track_window, term_crit)

        # 追踪的位置绘制在视频上,并进行显示
        x, y, w, h = track_window
        img2 = cv.rectangle(frame, (x, y), (x + w, y + h), 255, 2)
        cv.imshow('frame', img2)

        if cv.waitKey(65) & 0xFF == ord('q'):
            break
    else:
        break

video_dog.release()
cv.destroyAllWindows()

5.3.2 camshift算法

camshift算法可以适应目标大小形状的改变,具有较好的追踪效果。但当背景色和目标颜色接近时,容易使目标的区域变大。

import cv2 as cv
import numpy as np

video_dog = cv.VideoCapture('dog.mp4')

# 获取第一帧图像,并指定目标位置
ret, frame = video_dog.read()

# 目标位置
r, h, c, w = 170, 150, 350, 90
track_window = (c, r, w, h)

# 指定目标区域
roi = frame[r:r+h, c:c+w]

# 计算直方图
# 转换色彩空间(HSV)
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)

# 去除低亮度的值(色调,饱和度,亮度)
mask = cv.inRange(hsv_roi, np.array((0, 100, 50)), np.array((180, 255, 255)))

# 计算直方图
# [0] 只计算第一个通道,即色调(hue)通道的直方图
# [180] 定义直方图bin数量
# [0,180] 计算从0到180之间的色调值的直方图
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])

# 归一化
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)

# 目标追踪
# 设置窗口搜索终止条件:最大迭代次数,窗口中心漂移最小值
term_crit = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)

while True:
    ret, frame = video_dog.read()
    if ret:
        # 计算直方图的反向投影,生成一个概率图 dst,指示当前帧中哪些区域最可能包含目标。
        hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
        dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

        # CamShift追踪
        ret, track_window = cv.CamShift(dst, track_window, term_crit)

        # 将追踪的位置绘制在视频上,并进行显示
        # pst矩形框的四个坐标
        pts = cv.boxPoints(ret)
        pts = np.intp(pts)
        img2 = cv.polylines(frame,[pts],True, 255,2)
        # 显示图像
        cv.imshow('frame', img2)
        
        if cv.waitKey(60) & 0xFF == ord('q'):
            break
    else:
        break

video_dog.release()
cv.destroyAllWindows()

六、人脸、眼睛检测案例

OpenCV中自带已训练好的检测器,包括面部、眼睛等,都保存在XML中,我们可以通过以下程序找到他们:

import cv2 as cv
print(cv.__file__)

在这里插入图片描述
所有的XML文件都在D:\Anaconda\Lib\site-packages\cv2\data\

6.1 人脸以及眼睛检测(图片)

img = cv.imread("liying2.jpg")
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

# 定义训练器路径
cascade_path = "D:\\Anaconda\\Lib\\site-packages\\cv2\\data\\haarcascade_frontalface_default.xml"
eye_cascade_path = "D:\\Anaconda\\Lib\\site-packages\\cv2\\data\\haarcascade_eye.xml"

# 实例化人脸级联分类器
face_cas = cv.CascadeClassifier(cascade_path)
# 实例化眼睛级联分类器
eyes_cas = cv.CascadeClassifier(eye_cascade_path)

# 人脸检测
faceRects = face_cas.detectMultiScale(gray,scaleFactor=1.05,minNeighbors=5,minSize=(20,20))
# 遍历人脸
for faceRect in faceRects:
    x,y,w,h = faceRect
    cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
    roi_color = img[x:x+w,y:y+h]
    roi_gray = gray[x:x+w,y:y+h]
    eyes = eyes_cas.detectMultiScale(roi_gray,scaleFactor=1.2, minNeighbors=5, minSize=(30, 30), maxSize=(100, 100))
    for x,y,w,h in eyes:
        cv.rectangle(roi_color,(x,y),(x+w,y+h),(255,0,0),2)

plt.figure(figsize=(7,4))
plt.imshow(img[:,:,::-1])
plt.title("检测结果")
plt.show()

在这里插入图片描述

6.2 人脸以及眼睛检测(视频)

import cv2 as cv
import matplotlib.pyplot as plt

video = cv.VideoCapture("赵丽颖.mp4")

cascade_path = "D:\\Anaconda\\Lib\\site-packages\\cv2\\data\\haarcascade_frontalface_default.xml"
eyes_cascade_path = "D:\\Anaconda\\Lib\\site-packages\\cv2\\data\\haarcascade_eye.xml"

while True:
    ret,frame = video.read()

    if ret==True:
        gray = cv.cvtColor(frame,cv.COLOR_BGR2GRAY)
        # 实例化人脸级联分类器
        face_cas = cv.CascadeClassifier(cascade_path)
        # 实例化眼睛级联分类器
        eyes_cas = cv.CascadeClassifier(eyes_cascade_path)
        # 检测人脸
        faceRects = face_cas.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=3,minSize=(60,60))
        for faceRect in faceRects:
            x,y,w,h = faceRect
            cv.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)

            roi_color = frame[y:y+h,x:x+w]
            # 定位人脸上半部分
            roi_gray = gray[y:y+int(h*0.7),x:x+w]
            
            eyes = eyes_cas.detectMultiScale(roi_gray,scaleFactor=1.3,minNeighbors=5, minSize=(20,20), maxSize=(100, 100))
            for x,y,w,h in eyes:
                cv.rectangle(roi_color,(x,y),(x+w,y+h),(255,0,0),2)
        cv.imshow("frame",frame)
        if cv.waitKey(20) & 0xFF==ord('q'):
            break
    else:
        break
video.release()
cv.destroyAllWindows()

由于运行结果是视频所以无法展示

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱敲代码的小崔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值