OpenCV 简介

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,包含超过2500种优化算法,广泛应用于图像处理、物体检测、人脸识别、AR/VR等领域。支持C++、Python、Java等语言,跨平台(Windows、Linux、macOS、Android、iOS)。

核心功能

  • 图像处理:滤波、边缘检测、色彩空间转换(如RGB转灰度)。
  • 特征检测:SIFT、SURF、ORB等算法。
  • 目标检测:Haar级联、YOLO、SSD等预训练模型。
  • 视频分析:光流估计、背景减除。
  • 机器学习:集成SVM、KNN等算法,支持模型训练与推理。

本节小编将带领大家步入OpenCV的学习,这在ROS学习的过程中也是必不可少的关键。

先别着急开始OpenCV的学习,小编先来讲述一下摄像头情况异常的处理方法。

摄像头情况异常的处理方法

前车之鉴,如果虚拟机上面的可连接设备没有显示摄像头,建议重新装一遍虚拟机,因为可能存在安装的文件丢失,小编在此处卡住了很久T▽T。

(正常情况)

先给出测试摄像头能否正常工作的操作流程,如下:

用终端编辑器(nano)创建代码文件

# 创建并编辑 camera_test.py 文件
nano camera_test.py
import cv2

# 核心:调用系统默认摄像头(0 对应 /dev/video0)
cap = cv2.VideoCapture(0)

# 优化参数:适配大多数摄像头
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)    # 宽度
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)   # 高度
cap.set(cv2.CAP_PROP_FPS, 30)             # 帧率
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)       # 减少卡顿

# 检查摄像头是否成功打开
if not cap.isOpened():
    print("错误:无法连接摄像头!请检查硬件/权限")
    exit()

print("摄像头连接成功 → 按 ESC 键退出")

# 循环读取并显示画面
while True:
    # 读取一帧画面:ret=是否成功,frame=画面数据
    ret, frame = cap.read()
    
    if ret:
        # 显示画面窗口(窗口名:Camera (OpenCV))
        cv2.imshow("Camera (OpenCV)", frame)
    
    # 关键:按 ESC 键(键码 27)退出循环
    if cv2.waitKey(1) & 0xFF == 27:
        break

# 释放摄像头资源 + 关闭所有窗口(必须执行)
cap.release()
cv2.destroyAllWindows()

粘贴完成后,按 Ctrl+O 保存 → 按 Enter 确认文件名 → 按 Ctrl+X 退出 nano。

# 执行 Python 代码
python3 camera_test.py

执行完成后即可看到正常的画面。

(异常情况)

1. 摄像头被占用?查占用进程并结束

# 查看占用 /dev/video0 的进程 ID
fuser /dev/video0

# 结束占用进程(替换 <PID> 为上一步输出的数字)
sudo kill -9 <PID>

2. 画面黑屏 / 读取失败?测试摄像头硬件

# 安装摄像头测试工具 Cheese
sudo apt install cheese -y

# 打开 Cheese 测试摄像头
cheese
  • 若 Cheese 能显示画面,说明硬件正常,问题出在代码 / OpenCV 参数;
  • 若 Cheese 也黑屏,说明摄像头未正确识别,需重新检查硬件 / VMware 直通。

3.多摄像头切换?指定设备编号

# 先查所有摄像头设备
ls /dev/video*
# 比如输出 /dev/video0 /dev/video1 → 调用第二个摄像头:
python3 -c "import cv2; cap=cv2.VideoCapture(1); print(cap.isOpened())"

关键指令:

  • 验证硬件:ls /dev/video*

  • 临时赋权:sudo chmod 777 /dev/video0(777满权)
  • 运行代码:python3 camera_test.py

案例1(读取彩色图像+改成灰度图)

读取彩色图像

因为OpenCV的使用不需要创建工作空间,所有我们可以直接在一个文件夹中开始编辑python文件。

# 导入OpenCV库,用于图像处理相关操作
import cv2

# 读取指定路径的图片,以彩色模式读取,将图片数据存储到img变量中
img = cv2.imread("cat.png", cv2.IMREAD_COLOR)

# 创建名为'image'的窗口,并显示img对应的图片内容
cv2.imshow('image', img)

# 等待用户按下任意按键,参数0表示无限等待直到按键触发
cv2.waitKey(0)

# 关闭OpenCV创建的所有窗口
cv2.destroyAllWindows()

# 将img对应的图片数据,以new_image.jpg为文件名保存到当前目录
cv2.imwrite('new_image.jpg', img)

注意,要自己找到一张图片并命名为cat.png放到存python文件的文件夹中。

(小编在源码中直接调用cat.png,故而放入平行结构),运行python文件结果如图:

改成灰度图

只需将python文件中的代码修改一行,

# 读取指定路径的图片,以灰度图模式读取,将图片数据存储到img变量中
img = cv2.imread("cat.png", cv2.IMREAD_GRAYSCALE)

运行python文件结果如图:

案例2(查看图片属性)

# 导入numpy库,用于数值计算和数组操作
import numpy as np 
# 导入OpenCV库,用于图像处理
import cv2
# 读取图片
img = cv2.imread('cat.png', cv2.IMREAD_COLOR)
print("===============打印一下图像的属性====================")
print("图像对象的类型:", type(img))
print("图像形状(高度, 宽度, 通道数):", img.shape)
print("图像宽度:{} pixels".format(img.shape[1]))
print("图像高度:{} pixels".format(img.shape[0]))
print("通道数:{}".format(img.shape[2]))
print("图像分辨率:{} 像素".format(img.shape[0] * img.shape[1]))
print("数据类型:{}".format(img.dtype))
# 打印图像分辨率(总像素数 = 高度×宽度)

运行python文件结果如图:

案例3(可调节的 HSV 轨迹条)

通过 OpenCV实时读取摄像头画面,搭配可调节的 HSV 轨迹条,可视化筛选画面中指定颜色的区域

import cv2
import numpy as np 

# 定义空回调函数(轨迹条必须绑定回调函数,此处无实际操作)
def nothing(x):
    pass  # 补全函数体,避免语法错误

# 打开摄像头(0表示默认摄像头)
cap = cv2.VideoCapture(0) 

# 创建名为"HsvBars"的窗口,用于放置HSV阈值调节轨迹条
cv2.namedWindow("HsvBars")

# 创建6个轨迹条,分别对应:低H、低S、低V、高H、高S、高V
cv2.createTrackbar("LH","HsvBars",0,179, nothing)
cv2.createTrackbar("LS","HsvBars",0,255, nothing)
cv2.createTrackbar("LV","HsvBars",0,255, nothing)
cv2.createTrackbar("UH","HsvBars",179,179, nothing)
cv2.createTrackbar("US","HsvBars",255,255, nothing)
cv2.createTrackbar("UV","HsvBars",255,255, nothing)

# 补全实时读取摄像头、处理图像的核心逻辑
while True:
    # 逐帧读取摄像头画面
    ret, frame = cap.read()
    if not ret:
        print("摄像头读取失败!")
        break
    
    # 将BGR格式转为HSV格式(便于颜色筛选)
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    
    # 获取轨迹条当前的数值
    lh = cv2.getTrackbarPos("LH", "HsvBars")
    ls = cv2.getTrackbarPos("LS", "HsvBars")
    lv = cv2.getTrackbarPos("LV", "HsvBars")
    uh = cv2.getTrackbarPos("UH", "HsvBars")
    uv = cv2.getTrackbarPos("UV", "HsvBars")
    us = cv2.getTrackbarPos("US", "HsvBars")
    
    # 定义HSV颜色范围(低阈值和高阈值)
    lower_hsv = np.array([lh, ls, lv])
    upper_hsv = np.array([uh, us, uv])
    
    # 生成掩膜(筛选指定颜色区域)
    mask = cv2.inRange(hsv, lower_hsv, upper_hsv)
    
    # 按位与操作,提取原图像中对应颜色的区域
    res = cv2.bitwise_and(frame, frame, mask=mask)
    
    # 显示原画面、掩膜、结果画面
    cv2.imshow("frame", frame)
    cv2.imshow("mask", mask)
    cv2.imshow("res", res)
    
    # 按ESC键退出(ESC键码为27)
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break

# 释放摄像头资源,关闭所有窗口
cap.release()
cv2.destroyAllWindows()

运行python文件结果如图:

调节HSV轨迹条,结果如图:

案例4(色彩空间转换)

这段代码的核心作用是:读取本地一张名为cat.png的图片,将其分别转换成灰度图、HSV 色彩空间格式,然后在三个独立窗口中分别显示原图、灰度图、HSV 图。简单来说,就是对单张图片做「色彩空间转换」并可视化展示,是 OpenCV 图像处理的基础操作。

# 导入OpenCV库(计算机视觉处理的核心库)
import cv2

# 读取本地图片文件"cat.png",返回的img是BGR格式的图像矩阵
# 注意:图片文件需放在代码同级目录,否则需填写完整路径(如"/home/abot/Desktop/cat.png")
img = cv2.imread('cat.png')

# 将BGR格式的原图转换为灰度图(单通道)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 将BGR格式的原图转换为HSV色彩空间(常用于颜色筛选)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 创建名为"image"的窗口,显示原始BGR图片
cv2.imshow('image', img)

# 创建名为"gray"的窗口,显示灰度图
cv2.imshow('gray', gray)

# 创建名为"hsv"的窗口,显示HSV格式图片
cv2.imshow('hsv', hsv)

# 等待用户按下任意按键后关闭窗口(参数0表示无限等待)
cv2.waitKey(0)

# 关闭所有由OpenCV创建的显示窗口,释放资源
cv2.destroyAllWindows()

案例5(video)

这是一个功能完整、注释详细、开箱即用的 OpenCV 视频处理脚本,涵盖了「读取摄像头 / 视频文件、实时显示、保存视频、按键控制」等核心功能,新手也能轻松理解和使用。

# 导入OpenCV库(核心图像处理)和numpy库(数值计算)
import cv2
import numpy as np

def main():
    """
    核心功能:
    1. 可切换读取「摄像头」或「本地视频文件」
    2. 实时显示视频画面
    3. 支持按键控制(保存视频、退出、暂停/继续)
    4. 释放资源,避免内存泄漏
    """
    # ===================== 配置参数(可根据需求修改) =====================
    # 选择输入源:0=默认摄像头,也可填视频文件路径(如"test.mp4")
    INPUT_SOURCE = 0  # 改为"your_video.mp4"可读取本地视频
    # 保存视频的参数(编码格式、帧率、分辨率)
    SAVE_VIDEO = False  # 是否保存视频(True=保存,False=不保存)
    OUTPUT_VIDEO_NAME = "output_video.mp4"  # 保存的视频文件名
    FPS = 30  # 视频帧率(匹配摄像头/原视频帧率)
    WIDTH = 640  # 视频宽度
    HEIGHT = 480  # 视频高度

    # ===================== 初始化视频读取/写入 =====================
    # 打开视频源(摄像头/文件)
    cap = cv2.VideoCapture(INPUT_SOURCE)
    # 检查视频源是否打开成功
    if not cap.isOpened():
        print(f"错误:无法打开视频源 {INPUT_SOURCE}!")
        return

    # 如果需要保存视频,初始化视频写入器
    if SAVE_VIDEO:
        # 视频编码格式(MP4格式推荐使用mp4v)
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        out = cv2.VideoWriter(OUTPUT_VIDEO_NAME, fourcc, FPS, (WIDTH, HEIGHT))
        # 检查视频写入器是否初始化成功
        if not out.isOpened():
            print("错误:无法创建视频写入器!")
            cap.release()
            return

    # ===================== 实时处理视频帧 =====================
    print("视频已启动!按键说明:")
    print("  ESC键 → 退出程序")
    print("  S键   → 保存当前帧为图片")
    print("  空格  → 暂停/继续播放")
    print("  Q键   → 停止保存视频(仅开启保存时有效)")

    pause = False  # 暂停标志
    save_frame_count = 0  # 保存图片的计数(避免重名)

    while True:
        # 如果未暂停,读取一帧画面
        if not pause:
            ret, frame = cap.read()
            # 检查是否读取到画面(摄像头断开/视频播放完毕则ret=False)
            if not ret:
                print("提示:视频流已结束!")
                break

            # 调整画面分辨率(统一尺寸)
            frame = cv2.resize(frame, (WIDTH, HEIGHT))

            # 如果开启保存视频,写入当前帧
            if SAVE_VIDEO:
                out.write(frame)

        # 显示实时画面(窗口名:Video Player)
        cv2.imshow("Video Player", frame)

        # 按键控制(1ms等待,保证实时性)
        key = cv2.waitKey(1) & 0xFF

        # 按ESC键退出
        if key == 27:
            print("程序退出中...")
            break
        # 按S键保存当前帧为图片
        elif key == ord('s'):
            img_name = f"saved_frame_{save_frame_count}.png"
            cv2.imwrite(img_name, frame)
            print(f"已保存当前帧:{img_name}")
            save_frame_count += 1
        # 按空格键暂停/继续
        elif key == 32:
            pause = not pause
            status = "暂停" if pause else "继续"
            print(f"视频{status}播放")
        # 按Q键停止保存视频
        elif key == ord('q') and SAVE_VIDEO:
            SAVE_VIDEO = False
            out.release()
            print("已停止保存视频!")

    # ===================== 释放资源 =====================
    # 释放视频读取器
    cap.release()
    # 如果开启了保存视频,释放视频写入器
    if SAVE_VIDEO:
        out.release()
    # 关闭所有OpenCV窗口
    cv2.destroyAllWindows()
    print("资源已释放,程序结束!")

# 程序入口
if __name__ == "__main__":
    main()

核心功能说明

  1. 灵活的输入源

    • 默认读取「摄像头」(INPUT_SOURCE = 0),改为视频文件路径(如 "test.mp4")即可读取本地视频;
    • 自动检查输入源是否有效,避免程序崩溃。

    ESC

    退出程序
    S 保存当前帧为图片(自动编号,避免重名)
    空格 暂停 / 继续播放视频
    Q

    停止保存视频(仅开启保存时有效)

    案例6(图像滤波)

    图像滤波本质是「对图像像素值进行邻域计算」:把每个像素的取值,替换成它和周围像素的加权平均值(或其他计算结果),从而达到去噪、平滑、增强的效果。

    • 噪声:图像中的随机干扰点(比如照片上的雪花点、摄像头的杂色);
    • 核(Kernel):滤波的「计算模板」(比如 3×3 的矩阵),决定了滤波的规则。

    OpenCV 常用滤波算法(附代码)

    以下是最常用的 6 种滤波算法,小编会逐一说明原理 + 代码 + 适用场景,最后提供整合版代码。

    1. 均值滤波(平均滤波)
    • 原理:用像素邻域的平均值替换当前像素,简单粗暴去噪,但会模糊边缘。
    • 核心函数cv2.blur()
    • 适用场景:去除均匀分布的噪声(如高斯噪声),对边缘模糊不敏感的场景。
    2. 高斯滤波
    • 原理:用高斯核(中心像素权重高、周围像素权重低)加权平均,去噪的同时保留更多边缘细节。
    • 核心函数cv2.GaussianBlur()
    • 适用场景:去除高斯噪声(摄像头常见噪声),是最常用的平滑滤波。
    3. 中值滤波
    • 原理:用像素邻域的中值替换当前像素,能有效去除椒盐噪声(黑白斑点)。
    • 核心函数cv2.medianBlur()
    • 适用场景:去除椒盐噪声(如老照片的斑点、扫描件的杂点)。
    4. 双边滤波
    • 原理:同时考虑空间距离和像素值相似度,去噪的同时保留边缘(不会模糊边缘)。
    • 核心函数cv2.bilateralFilter()
    • 适用场景:人像磨皮、保留边缘的去噪(如证件照优化)
    5. 方框滤波
    • 原理:类似均值滤波,可选择是否归一化,不归一化时易出现像素值溢出(亮斑)。
    • 核心函数cv2.boxFilter()
    • 适用场景:特殊的亮度增强场景(较少用)。
    6. 拉普拉斯滤波(边缘增强)
    • 原理:二阶导数计算,突出图像边缘(属于高通滤波,和上述低通滤波相反)。
    • 核心函数cv2.Laplacian()
    • 适用场景:边缘检测、图像锐化。

    整合版代码:filter_demo.py

    # 导入OpenCV和numpy库
    import cv2
    import numpy as np
    
    def image_filter_demo():
        """
        图像滤波演示:
        1. 读取图片并添加噪声(模拟真实场景)
        2. 分别应用6种滤波算法
        3. 对比显示原图、噪声图、各滤波结果
        """
        img = cv2.imread("cat.png")
        if img is None:
            print("错误:无法读取图片,请检查路径!")
            return
    
        # 2. 添加模拟噪声(高斯噪声+椒盐噪声,模拟真实场景)
        def add_noise(image):
            # 添加高斯噪声
            gauss = np.random.normal(0, 20, image.shape).astype(np.uint8)
            noisy_img = cv2.add(image, gauss)
            # 添加椒盐噪声
            s_vs_p = 0.5
            amount = 0.005
            out = np.copy(noisy_img)
            # 椒盐噪声:白色点
            num_salt = np.ceil(amount * image.size * s_vs_p)
            coords = [np.random.randint(0, i - 1, int(num_salt)) for i in image.shape]
            out[coords[0], coords[1], :] = 255
            # 椒盐噪声:黑色点
            num_pepper = np.ceil(amount * image.size * (1. - s_vs_p))
            coords = [np.random.randint(0, i - 1, int(num_pepper)) for i in image.shape]
            out[coords[0], coords[1], :] = 0
            return out
    
        noisy_img = add_noise(img)
    
        # 3. 应用各种滤波算法
        # 均值滤波(核大小3×3)
        blur = cv2.blur(noisy_img, (3, 3))
        # 高斯滤波(核3×3,σX=0自动计算)
        gaussian = cv2.GaussianBlur(noisy_img, (3, 3), 0)
        # 中值滤波(核大小3)
        median = cv2.medianBlur(noisy_img, 3)
        # 双边滤波(d=9,颜色相似度σ=75,空间距离σ=75)
        bilateral = cv2.bilateralFilter(noisy_img, 9, 75, 75)
        # 方框滤波(核3×3,归一化)
        box = cv2.boxFilter(noisy_img, -1, (3, 3), normalize=True)
        # 拉普拉斯滤波(边缘增强)
        laplacian = cv2.Laplacian(img, cv2.CV_64F)
        laplacian = cv2.convertScaleAbs(laplacian)  # 转换为uint8格式
    
        # 4. 显示所有结果(排版为2行4列)
        cv2.imshow("1. Original", img)
        cv2.imshow("2. Noisy Image", noisy_img)
        cv2.imshow("3. Mean Filter", blur)
        cv2.imshow("4. Gaussian Filter", gaussian)
        cv2.imshow("5. Median Filter", median)
        cv2.imshow("6. Bilateral Filter", bilateral)
        cv2.imshow("7. Box Filter", box)
        cv2.imshow("8. Laplacian (Edge)", laplacian)
    
        # 5. 按键控制(按ESC退出)
        print("所有窗口已打开,按ESC键退出!")
        cv2.waitKey(0)
        # 释放资源
        cv2.destroyAllWindows()
    
    # 程序入口
    if __name__ == "__main__":
        image_filter_demo()

    案例7(边缘检测)

    边缘检测核心概念

    边缘是图像中像素值突变的区域(比如物体轮廓、明暗交界),边缘检测的本质是通过算法识别这些像素突变点,是目标检测、轮廓提取、图像分割的基础。

    核心思路:先滤波去噪(避免噪声被误判为边缘)→ 计算像素梯度(识别突变)→ 非极大值抑制(细化边缘)→ 阈值筛选(保留有效边缘)。

    以下是最实用的 3 类边缘检测算法,从简单到进阶,附带完整演示代码。

    1. 基础梯度算子(Sobel、Scharr、Laplacian)
    • Sobel:分 X/Y 方向计算梯度,抗噪性好,最常用;
    • Scharr:Sobel 的升级版,对小尺寸核更精准;
    • Laplacian:二阶导数,对边缘更敏感,但易放大噪声。
    2. Canny 边缘检测(最优算法)

    OpenCV 中最经典、效果最好的边缘检测算法,包含 4 步:高斯滤波→梯度计算→非极大值抑制→双阈值筛选,边缘最清晰、完整。

    3. 轮廓提取(边缘检测的延伸应用)

    基于边缘检测结果,提取物体的轮廓,可用于目标定位、面积计算等。

    edge_detection.py

    # 导入核心库
    import cv2
    import numpy as np
    
    def edge_detection_demo():
        """
        边缘检测演示:
        1. 读取图片并预处理(灰度化、去噪)
        2. 分别实现Sobel、Laplacian、Canny边缘检测
        3. 提取轮廓并绘制
        4. 对比显示所有结果
        """
        # 1. 读取图片(替换为你的图片路径)
        img = cv2.imread("cat.png")
        if img is None:
            print("错误:无法读取图片,请检查路径!")
            return
        
        # 2. 预处理:灰度化 + 高斯滤波(去噪,避免边缘检测误判)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        blur = cv2.GaussianBlur(gray, (3, 3), 0)  # 高斯滤波去噪
    
        # 3. 各类边缘检测算法实现
        # --------------------- Sobel边缘检测 ---------------------
        # 计算X方向梯度(左→右边缘)
        sobel_x = cv2.Sobel(blur, cv2.CV_64F, 1, 0, ksize=3)
        sobel_x = cv2.convertScaleAbs(sobel_x)  # 转换为uint8格式
        # 计算Y方向梯度(上→下边缘)
        sobel_y = cv2.Sobel(blur, cv2.CV_64F, 0, 1, ksize=3)
        sobel_y = cv2.convertScaleAbs(sobel_y)
        # 合并X/Y方向边缘
        sobel_xy = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)
    
        # --------------------- Laplacian边缘检测 ---------------------
        laplacian = cv2.Laplacian(blur, cv2.CV_64F, ksize=3)
        laplacian = cv2.convertScaleAbs(laplacian)
    
        # --------------------- Canny边缘检测(最优) ---------------------
        # 双阈值:低阈值(50)、高阈值(150),可根据图片调整
        canny = cv2.Canny(blur, 50, 150)
    
        # --------------------- 轮廓提取(基于Canny结果) ---------------------
        # 查找轮廓:RETR_EXTERNAL=只找最外层轮廓,CHAIN_APPROX_SIMPLE=压缩轮廓点
        contours, hierarchy = cv2.findContours(canny.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # 在原图上绘制轮廓(绿色,线宽2)
        contour_img = img.copy()
        cv2.drawContours(contour_img, contours, -1, (0, 255, 0), 2)
    
        # 4. 显示所有结果(排版为2行4列)
        cv2.imshow("1. Original", img)
        cv2.imshow("2. Sobel X", sobel_x)
        cv2.imshow("3. Sobel Y", sobel_y)
        cv2.imshow("4. Sobel XY", sobel_xy)
        cv2.imshow("5. Laplacian", laplacian)
        cv2.imshow("6. Canny(最优)", canny)
        cv2.imshow("7. Contours(轮廓)", contour_img)
    
        # 5. 按键控制(按ESC退出)
        print("所有窗口已打开,按ESC键退出!")
        print("提示:Canny的双阈值(50/150)可根据图片调整,以获得最佳边缘效果")
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    # 视频实时边缘检测(可选拓展)
    def video_edge_detection():
        """实时处理摄像头/视频的边缘检测"""
        cap = cv2.VideoCapture(0)  # 0=摄像头,也可填视频路径
        if not cap.isOpened():
            print("错误:无法打开摄像头!")
            return
    
        print("实时边缘检测已启动,按ESC退出!")
        while True:
            ret, frame = cap.read()
            if not ret:
                break
            
            # 预处理+Canny边缘检测
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            blur = cv2.GaussianBlur(gray, (3, 3), 0)
            canny = cv2.Canny(blur, 50, 150)
    
            # 显示原图和边缘检测结果
            cv2.imshow("Original Video", frame)
            cv2.imshow("Canny Edge (Real-time)", canny)
    
            if cv2.waitKey(1) & 0xFF == 27:
                break
    
        cap.release()
        cv2.destroyAllWindows()
    
    # 程序入口
    if __name__ == "__main__":
        # 先运行图片边缘检测
        edge_detection_demo()
        # 如需实时视频检测,取消注释:
        # video_edge_detection()

    案例8(色彩空间)

    色彩空间核心概念

    色彩空间是用一组数值描述颜色的标准化体系,不同色彩空间适用于不同场景:

    OpenCV 色彩空间转换核心函数

    OpenCV 中所有色彩空间转换都依赖 cv2.cvtColor() 函数,语法

    dst = cv2.cvtColor(src, code)
    # src:输入图像;code:转换码(如cv2.COLOR_BGR2GRAY);dst:转换后图像

    常用转换码(OpenCV 内置):

    • BGR ↔ RGB:cv2.COLOR_BGR2RGB / cv2.COLOR_RGB2BGR
    • BGR ↔ GRAY:cv2.COLOR_BGR2GRAY / cv2.COLOR_GRAY2BGR
    • BGR ↔ HSV:cv2.COLOR_BGR2HSV / cv2.COLOR_HSV2BGR
    • BGR ↔ YCrCb:cv2.COLOR_BGR2YCrCb / cv2.COLOR_YCrCb2BGR
    • BGR ↔ HLS:cv2.COLOR_BGR2HLS / cv2.COLOR_HLS2BGR

    color_space_demo.py

    # 导入核心库
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt  # 用于RGB对比显示
    
    def color_space_conversion():
        """
        色彩空间转换演示:
        1. 读取图片并展示原始BGR格式
        2. 转换为常用色彩空间(GRAY/HSV/YCrCb/HLS/RGB)
        3. 可视化对比各色彩空间效果
        4. 实战:基于HSV筛选指定颜色(如红色)
        """
        # 1. 读取图片(OpenCV默认BGR格式)
        img = cv2.imread("cat.png")
        if img is None:
            print("错误:无法读取图片,请检查路径!")
            return
    
        # 2. 各类色彩空间转换
        # 灰度图
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # HSV(颜色筛选核心)
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        # YCrCb(肤色识别)
        ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
        # HLS
        hls = cv2.cvtColor(img, cv2.COLOR_BGR2HLS)
        # BGR转RGB(适配matplotlib显示)
        rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
        # 3. 可视化显示(OpenCV窗口)
        cv2.imshow("1. Original (BGR)", img)
        cv2.imshow("2. Grayscale (GRAY)", gray)
        cv2.imshow("3. Hue-Saturation-Value (HSV)", hsv)
        cv2.imshow("4. YCrCb (Skin Detection)", ycrcb)
        cv2.imshow("5. HLS (Outdoor Scene)", hls)
    
        # 补充:matplotlib显示RGB(对比OpenCV的BGR)
        plt.subplot(121)
        plt.imshow(img)  # 直接显示BGR(会偏色)
        plt.title("OpenCV Default (BGR)")
        plt.axis("off")
    
        plt.subplot(122)
        plt.imshow(rgb)  # 正确RGB显示
        plt.title("Converted RGB")
        plt.axis("off")
        plt.show(block=False)  # 非阻塞显示
    
        # 4. 实战:基于HSV筛选红色区域(监控/目标识别常用)
        # 红色HSV范围(分两段,因为Hue=0/180是同一种红色)
        lower_red1 = np.array([0, 43, 46])
        upper_red1 = np.array([10, 255, 255])
        lower_red2 = np.array([156, 43, 46])
        upper_red2 = np.array([180, 255, 255])
    
        # 生成红色掩膜(白色=红色区域,黑色=其他)
        mask_red1 = cv2.inRange(hsv, lower_red1, upper_red1)
        mask_red2 = cv2.inRange(hsv, lower_red2, upper_red2)
        mask_red = cv2.bitwise_or(mask_red1, mask_red2)
    
        # 提取红色区域
        red_area = cv2.bitwise_and(img, img, mask=mask_red)
        cv2.imshow("6. Red Mask (HSV筛选)", mask_red)
        cv2.imshow("7. Red Area (提取结果)", red_area)
    
        # 按键控制退出
        print("所有窗口已打开,按ESC键退出!")
        print("关键提示:HSV是颜色筛选的首选,需根据实际场景调整颜色阈值")
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        plt.close()
    
    def video_color_space():
        """实时视频色彩空间转换(监控场景)"""
        cap = cv2.VideoCapture(0)  # 0=摄像头,可替换为监控视频路径
        if not cap.isOpened():
            print("错误:无法打开摄像头/视频!")
            return
    
        print("实时色彩空间转换已启动,按ESC退出!")
        print("按键说明:1=原图 2=灰度 3=HSV 4=红色筛选")
        mode = 1  # 默认显示原图
    
        while True:
            ret, frame = cap.read()
            if not ret:
                break
    
            # 根据模式切换色彩空间
            if mode == 1:
                show_frame = frame
                title = "Original (BGR)"
            elif mode == 2:
                show_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                title = "Grayscale"
            elif mode == 3:
                show_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
                title = "HSV"
            elif mode == 4:
                # 实时筛选红色
                hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
                lower_red = np.array([0, 43, 46])
                upper_red = np.array([10, 255, 255])
                mask = cv2.inRange(hsv, lower_red, upper_red)
                show_frame = cv2.bitwise_and(frame, frame, mask=mask)
                title = "Red Detection (HSV)"
    
            # 显示结果
            cv2.imshow(title, show_frame)
    
            # 按键控制
            key = cv2.waitKey(1) & 0xFF
            if key == 27:  # ESC退出
                break
            elif key == ord('1'):
                mode = 1
            elif key == ord('2'):
                mode = 2
            elif key == ord('3'):
                mode = 3
            elif key == ord('4'):
                mode = 4
    
        cap.release()
        cv2.destroyAllWindows()
    
    # 程序入口
    if __name__ == "__main__":
        # 先运行图片色彩空间转换
        color_space_conversion()
        # 如需实时视频/监控处理,取消注释:
        # video_color_space()

    Logo

    昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链

    更多推荐