在计算机视觉任务中,颜色空间转换图像几何变换是两大基础且高频的操作 —— 前者用于精准分割特定颜色目标(如交通信号灯、物体追踪),后者用于调整图像的尺寸、位置和视角(如文档矫正、图像拼接)。本文将通过 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'):breakcv2.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 npcap = 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, 50M = 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'):breakcap.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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94770.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94770.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/94770.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[HFCTF2020]EasyLogin

文章目录TRYWP总结TRY 注册admin报错username wrong。 随便注册一个用户点击GetFlag,permission deny。 猜测可能是需要admin权限。 看cookie发现有: sses:aok:eyJ1c2VybmFtZSI6ImEiLCJfZXhwaXJlIjoxNzU2NDU1NjczMTAxLCJfbWF4QWdlIjo4NjQwM…

Java接口和抽象类的区别,并举例说明

Java接口和抽象类是面向对象编程中实现抽象的两种机制,它们在语法、设计目的和使用场景上有显著区别:一、核心区别‌定义方式‌抽象类:使用abstract class声明,可包含抽象方法和具体方法45。接口:使用interface声明&am…

docker-相关笔记

1: 导入镜像 docker load -i myimage.tar# 导出镜像 docker save myimage:latest > myimage.tar # 导入镜像 docker load -i myimage.tardocker load -i <文件> 功能&#xff1a;用于导入通过 docker save 命令导出的镜像归档文件&#xff08;通常是 .tar 格式&#…

自然语言提取PDF表格数据

自然语言提取PDF表格数据PDF v8.2的文档解决方案与OpenAI实现了无缝的AI集成&#xff0c;可将非结构化PDF转换为可用数据。MESCIUS 推出的 PDF 文档解决方案 (DsPdf) 是一款软件开发工具包&#xff0c;它提供了 .NET Core 库和一个 JavaScript PDF 查看器&#xff0c;用于处理和…

飞牛Nas每天定时加密数据备份到网盘,基于restic的Backrest笔记分享

1. 前言 受前辈“RAID≠备份”的经验&#xff0c;也考虑到硬盘故障时 RAID 重建步骤繁琐&#xff0c;我干脆放弃阵列&#xff0c;直接单盘运行。 重要数据则加密后上传至大厂云盘&#xff1a;一方面文件对外不可读&#xff0c;规避扫描和谐&#xff1b;另一方面依靠大厂的数据安…

C#连接SQL-Server数据库超详细讲解以及防SQL注入

C#连接SQL Server数据库完整指南&#xff0c;整合了ADO.NET原生连接与Entity Framework Core两种实现方式。这篇文件详细介绍C#代码连接数据库的通用操作数据库链接功能 数据库的增删改查操作1 配置全局数据库链接字符串 App.config2 获取数据库链接字符串先在App.config配置连…

Pico2‑ICE FPGA 开发板:从开箱到跑通示例的全历程

FPGA 和 MCU 结合的开发板不多&#xff0c;而 Pico2‑ICE 则把小巧、灵活和易上手完美结合。搭载 RP2350 双核 RISC-V MCU Lattice iCE40UP5K FPGA&#xff0c;配合官方 SDK&#xff0c;你可以一步步跑通各种示例&#xff0c;从 LED 到 VGA&#xff0c;再到 MCU 与 FPGA 协作应…

Java图形图像处理【Swing图像拖拽】【五】

Java图形图像处理【Swing图像拖拽】 18.3.3 Swing图像对象拖拽功能 18.3.3 Swing图像对象拖拽功能 上文讨论的是java.awt.dnd包中提供的拖拽API接口&#xff0c;也可称之为AWT组件的拖拽功能。下面我们要讨论的是Swing框架的拖拽功能&#xff1a;Swing组件也提供了对拖拽功能的…

状态模式与几个经典的C++例子

1. 状态模式定义与核心思想 状态模式解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。通过将状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。 核心思想: 状态抽象:将对象的每个状态都封装到一个独立的类中。 委托代替条件判断:…

SyncBackPro 备份及同步软件中的脚本功能简介

脚本提供了一种灵活而简单的方法来自动执行任务和扩展应用程序的功能。脚本是一个小程序&#xff0c;能够自定义和控制备份作业。例如&#xff0c;用户可以编写脚本来复制、重命名或删除特定文件、自定义用户界面或更改配置文件设置。SyncBackPro 的脚本功能类似于 Microsoft O…

部署2.516.2版本的jenkins,同时适配jdk8

&#x1f4cc; 前言 在企业级开发中&#xff0c;我们常常面临 新老项目并存 的复杂局面&#xff1a; 老项目基于 JDK 8 开发&#xff0c;短期内无法升级&#xff1b; 新项目采用 JDK 17&#xff08;LTS&#xff09;甚至更高版本&#xff1b; 而作为 CI/CD 核心的 Jenkins&#…

Autodesk Maya 2026.2 全新功能详解:MotionMaker AI 动画、LookdevX 材质增强、USD 工作流优化

软件介绍 Autodesk Maya 2026.2是一款专业的3D计算机图形软件&#xff0c;它为数字内容创作者提供了丰富的工具集&#xff0c;以实现高质量的建模、动画、模拟和渲染。该版本带来了多项性能优化和工作流程改进&#xff0c;特别是针对生成式动画工具MotionMaker进行了重大升级&…

STM32之DMA详解

一、DMA 1. DMA的引入 在嵌入式系统或计算机系统中&#xff0c;数据的传输和处理是非常重要的操作。以下通过一个简单的示例来展示传统数据操作方式与 DMA 引入的必要性&#xff1a; int a 10; int b 20;a b;上述代码包含了变量定义、初始化以及变量数据赋值操作。在传统…

链表有环找入口节点原理

环形链表入口检测算法数学解释 数学原理假设定义: 链表头到环入口的距离为 a环入口到相遇点的距离为 b相遇点到环入口的距离为 c环的长度为 b c第一次相遇时: 慢指针走了 s a b 步快指针走了 f a b n(b c) 步&#xff0c;其中 n 是快指针在环内转的圈数由于快指针速度是…

Java 基本类型与包装类详解

Java 基本类型与包装类详解 在 Java 开发中&#xff0c;理解 基本数据类型与包装类、字符串处理、以及高精度计算类是非常核心的能力。这不仅关系到程序性能&#xff0c;还影响代码的正确性和可维护性。本文将详细讲解这些知识点&#xff0c;并给出常见的使用技巧和陷阱。 1️…

CRYPT32!CryptMsgUpdate函数分析之CRYPT32!PkiAsn1Decode函数的作用是得到pci

第一部分&#xff1a; CryptMsgUpdate( #endifIN HCRYPTMSG hCryptMsg,IN const BYTE *pbData,IN DWORD cbData,IN BOOL fFinal) {ContentInfo *pci NULL;if ((PHASE_FIRST_FINAL pcmi->dwPhase) &&(0 pcmi->dwMsgType)) {if (0 …

华为交换机S5700设置acl

1.、配置ACL1.1、定义允许的ACL规则[sw1]acl number 3001[sw1-acl-adv-3001]rule permit ip source 192.168.20.0 0.0.0.255 destination 192.168.40.1 0[sw1-acl-adv-3001]rule permit ip source 192.168.30.0 0.0.0.255 destination 192.168.40.1 01.2、定义禁止的ACL规则[sw…

在使用spring ai进行llm处理的rag的时候,选择milvus还是neo4j呢?

在使用spring ai进行llm处理的rag的时候&#xff0c;选择milvus还是neo4j呢&#xff1f; 对于Spring AI中的RAG&#xff08;Retrieval-Augmented Generation&#xff09;应用&#xff0c;选择Milvus还是Neo4j&#xff0c;主要取决于你的数据类型以及RAG流程中对数据检索的侧重点…

计算机视觉与深度学习 | 视觉里程计技术全景解析:从原理到前沿应用

视觉里程计技术全景解析:从原理到前沿应用 一、定义与核心价值 二、技术原理与分类体系 2.1 基本工作流程 2.2 主流技术路线对比 2.3 算法范式演进 三、典型应用场景 3.1 地面移动机器人 3.2 自动驾驶领域 3.3 深空探测 3.4 增强现实 四、核心技术挑战与突破路径 4.1 主要技术…

Wireshark和USRP捕获同一信号波形差异原因

一、波形差异 在前面的博客中我对比绘制了同一信号的Wireshark和USRP两种波形&#xff1a; 可以看出波形差别还是挺大的&#xff0c;尤其是在信号分布间隔方面。 我猜想Wireshark的一条数据包在物理上并不是连续的&#xff1a; 而是分组发送&#xff0c;但在Wireshark中合并在…