OpenCV 核心技术:颜色检测与几何变换实战

发布于:2025-08-31 ⋅ 阅读:(25) ⋅ 点赞:(0)

在计算机视觉任务中,颜色空间转换图像几何变换是两大基础且高频的操作 —— 前者用于精准分割特定颜色目标(如交通信号灯、物体追踪),后者用于调整图像的尺寸、位置和视角(如文档矫正、图像拼接)。本文将通过 6 段实战代码,系统解析 HSV 颜色检测、图像缩放、平移、旋转、仿射变换和透视变换的原理与应用。

一、HSV 颜色空间:精准检测特定颜色(以蓝色为例)

RGB(或 BGR)颜色空间虽直观,但受光照影响大(如亮度变化会导致像素值剧烈波动),而HSV 颜色空间(色相 H、饱和度 S、明度 V)更符合人眼对颜色的感知,且能有效分离颜色信息与亮度信息,是颜色分割的首选。

1. 代码实现:实时检测摄像头中的蓝色物体

import cv2
import numpy as np

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

while True:
    # 读取一帧图像
    ret, frame = cap.read()
    if not ret:  # 防止摄像头读取失败
        break

    # 1. 将BGR图像转换为HSV图像(OpenCV默认BGR格式)
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # 2. 定义HSV空间中蓝色的范围(需根据实际场景调试)
    # H:色相(0-179),S:饱和度(0-255),V:明度(0-255)
    lower_blue = np.array([110, 50, 50])   # 蓝色下限
    upper_blue = np.array([130, 255, 255]) # 蓝色上限

    # 3. 生成颜色掩码:在范围內的像素设为255(白色),否则为0(黑色)
    mask = cv2.inRange(hsv, lower_blue, upper_blue)

    # 4. 掩码与原图像进行按位与:只保留原图像中蓝色区域
    res = cv2.bitwise_and(frame, frame, mask=mask)

    # 显示结果
    cv2.imshow('Original Frame', frame)  # 原图像
    cv2.imshow('Blue Mask', mask)        # 颜色掩码
    cv2.imshow('Detected Blue', res)     # 检测结果

    # 按q键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

2. 关键技术解析

函数 / 操作 作用与原理
cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 将 BGR 格式转换为 HSV 格式,分离颜色(H)、纯度(S)、亮度(V)信息,避免光照干扰。
cv2.inRange(hsv, lower, upper) 生成二值掩码:筛选出 HSV 值在[lower, upper]范围内的像素,实现颜色分割。
cv2.bitwise_and(frame, frame, mask=mask) 按位与操作:仅保留原图像中掩码为 255(白色)的区域,即目标颜色区域。

3. 实用技巧

  • HSV 范围调试:不同场景下颜色的 HSV 范围不同,可通过「先获取目标颜色的 HSV 值」再微调范围(如用cv2.cvtColor转换单个像素的 BGR 到 HSV)。
  • 抗干扰优化:可对掩码进行形态学操作(如cv2.erode腐蚀、cv2.dilate膨胀),去除小噪声点。

二、图像缩放:调整图像尺寸

图像缩放是预处理的基础操作,用于统一图像尺寸(如神经网络输入要求固定大小)或优化显示效果。OpenCV 提供两种缩放方式:按比例缩放指定目标尺寸缩放

1. 代码实现:两种缩放方式

import cv2
import numpy as np

# 读取图像
img = cv2.imread('ocv01.jpg')
if img is None:  # 防止图像读取失败
    print("无法读取图像")
    exit()

# 方式1:按比例缩放(fx=水平比例,fy=垂直比例)
# interpolation=INTER_CUBIC:双三次插值(放大时效果最优,速度较慢)
res1 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)

# 方式2:指定目标尺寸(宽,高)
height, width = img.shape[:2]  # 获取原图像尺寸(高,宽)
res2 = cv2.resize(img, (2*width, 2*height), interpolation=cv2.INTER_CUBIC)

# 显示对比
while True:
    cv2.imshow('Original (640x480)', img)    # 原图像
    cv2.imshow('Scaled by Ratio (1280x960)', res1)  # 按比例放大2倍
    cv2.imshow('Scaled by Size (1280x960)', res2)   # 按指定尺寸放大2倍

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

2. 插值方法选择

缩放的核心是「插值算法」(通过已有像素计算新像素值),需根据缩放方向选择:

插值方法 适用场景 特点
cv2.INTER_NEAREST 快速预览、对精度要求低 速度最快,效果最差(锯齿)
cv2.INTER_LINEAR 默认选项 速度与效果平衡
cv2.INTER_CUBIC 图像放大(如 4K 放大到 8K) 效果最优,速度较慢
cv2.INTER_AREA 图像缩小(如 1080P 缩到 720P) 保留细节,避免模糊

三、图像几何变换:改变位置与视角

几何变换通过矩阵运算改变图像像素的空间位置,包括平移、旋转、仿射变换、透视变换,适用于图像矫正、视角转换等场景。

1. 平移:沿 x/y 轴移动图像

平移是最简单的几何变换,通过「平移矩阵」实现像素位置偏移。

代码实现:
import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # 1. 定义平移矩阵:[[1,0,dx], [0,1,dy]],dx=水平偏移,dy=垂直偏移
    # 示例:向右偏移100像素,向下偏移50像素
    dx, dy = 100, 50
    M = np.float32([[1, 0, dx], [0, 1, dy]])

    # 2. 应用平移变换:warpAffine(输入图,矩阵,输出尺寸)
    # 输出尺寸需与原图像一致(宽,高)
    shifted_frame = cv2.warpAffine(frame, M, (frame.shape[1], frame.shape[0]))

    # 显示结果(对比原图像与平移后图像)
    cv2.imshow('Original Frame', frame)
    cv2.imshow('Shifted Frame (dx=100, dy=50)', shifted_frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

2. 旋转:绕指定点旋转图像

旋转需指定「旋转中心、旋转角度、缩放因子」,通过cv2.getRotationMatrix2D自动生成旋转矩阵,避免手动构造复杂矩阵。

代码实现:
import cv2
import numpy as np

# 读取图像
img = cv2.imread('ocv01.jpg')
if img is None:
    print("无法读取图像")
    exit()

# 获取图像尺寸(高,宽)
rows, cols = img.shape[:2]

# 1. 生成旋转矩阵
# getRotationMatrix2D(旋转中心,旋转角度,缩放因子)
# 示例:绕图像中心旋转45°,缩放为原尺寸的0.6倍
center = (cols / 2, rows / 2)  # 旋转中心(x=宽/2,y=高/2)
angle = 45                     # 旋转角度(正数=逆时针,负数=顺时针)
scale = 0.6                    # 旋转后图像的缩放因子
M = cv2.getRotationMatrix2D(center, angle, scale)

# 2. 应用旋转变换:输出尺寸设为2*cols、2*rows,避免旋转后图像被裁剪
rotated_img = cv2.warpAffine(img, M, (2 * cols, 2 * rows))

# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Rotated (45° CCW, scale=0.6)', rotated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 仿射变换:保持平行线不变的变换

仿射变换通过3 对对应点确定变换(需保证 3 点不共线),核心是「保持平行线不变」,适用于图像倾斜矫正(如倾斜的文档)。

代码实现:
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像(注意:matplotlib显示需转换为RGB格式)
img = cv2.imread('ocv01.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # BGR转RGB
rows, cols = img.shape[:2]

# 1. 定义3对对应点(原图像点 → 目标图像点)
# 原图像中3个不共线的点
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
# 目标图像中对应的3个点(可根据需求调整,实现倾斜矫正)
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])

# 2. 生成仿射变换矩阵
M = cv2.getAffineTransform(pts1, pts2)

# 3. 应用仿射变换
affine_img = cv2.warpAffine(img_rgb, M, (cols, rows))

# 用matplotlib显示对比
plt.subplot(121), plt.imshow(img_rgb), plt.title('Original')
plt.subplot(122), plt.imshow(affine_img), plt.title('Affine Transformed')
plt.show()

4. 透视变换:改变投影视角(如鸟瞰图)

透视变换通过4 对对应点确定变换(需保证 4 点构成凸四边形),核心是「打破平行线约束」,可将倾斜视角转换为正视角(如将斜拍的文档转为正拍效果)。

代码实现:
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像并转换为RGB
img = cv2.imread('ocv01.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
rows, cols = img.shape[:2]

# 1. 定义4对对应点(原图像中的四边形顶点 → 目标图像中的矩形顶点)
# 原图像中4个凸四边形顶点(如斜拍文档的四个角)
pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
# 目标图像中对应的矩形顶点(如300x300的正方形)
pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])

# 2. 生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)

# 3. 应用透视变换:输出尺寸设为300x300(与目标矩形匹配)
perspective_img = cv2.warpPerspective(img_rgb, M, (300, 300))

# 显示对比
plt.subplot(121), plt.imshow(img_rgb), plt.title('Original (Tilted)')
plt.subplot(122), plt.imshow(perspective_img), plt.title('Perspective (Top-Down)')
plt.show()

5. 仿射变换 vs 透视变换

对比维度 仿射变换(Affine) 透视变换(Perspective)
对应点数 3 对(不共线) 4 对(凸四边形)
核心特性 保持平行线不变 打破平行线约束(如近大远小)
变换矩阵维度 2x3 矩阵 3x3 矩阵
适用场景 图像倾斜矫正、平移 + 旋转组合 鸟瞰图生成、文档矫正、3D 视角转换

总结

本文覆盖的 OpenCV 核心技术,是计算机视觉任务的基石:

  1. HSV 颜色检测:解决 RGB 颜色分割受光照干扰的问题,适用于目标追踪、颜色筛选。
  2. 图像缩放:通过插值算法调整尺寸,满足统一输入、优化显示的需求。
  3. 几何变换
    • 平移 / 旋转:简单位置调整,适用于图像对齐。
    • 仿射变换:保持平行线,适用于倾斜矫正。
    • 透视变换:改变投影视角,适用于文档扫描、鸟瞰图生成。

这些技术的灵活组合,可实现更复杂的任务(如「透视矫正 + 颜色检测」实现文档中特定颜色文字的提取)。实际应用中,需注意「图像读取失败处理」「坐标与尺寸的一致性」「插值方法选择」等细节,避免常见 bug。