当前位置: 首页 > news >正文

OpenCV 图像处理实战:从图像金字塔到直方图分析

OpenCV 图像处理实战:从图像金字塔到直方图分析

在计算机视觉领域,OpenCV 是一款功能强大的开源库,提供了丰富的图像处理函数。本文将围绕一段 OpenCV 实战代码,详细讲解图像金字塔(上采样与下采样)、图像直方图计算以及掩码操作的实现过程与原理,帮助大家快速掌握这些核心图像处理技术。

一、准备工作:环境与图像

在开始之前,需确保已安装所需的 Python 库:OpenCV(cv2)、Matplotlib(绘图)和 NumPy(数值计算)。可通过以下命令安装:

pip install opencv-python matplotlib numpy

代码中用到了 3 张测试图像:mywife.jpg(用于图像金字塔操作)、love.jpg(用于直方图分析)、phone.png(用于掩码与直方图结合操作)。建议将图像与代码放在同一目录下,或在cv2.imread()中填写完整图像路径。

二、核心技术 1:图像金字塔(上采样与下采样)

图像金字塔是一种多尺度表示方法,通过 “下采样”(缩小图像)和 “上采样”(放大图像)构建不同分辨率的图像序列。但需注意:下采样会丢失图像信息,再对下采样图像上采样无法完全复原原图。

1.1 下采样(pyrDown):缩小图像

下采样通过cv2.pyrDown()实现,核心步骤是:先对图像进行高斯滤波(去除高频噪声),再删除图像的偶数行和偶数列,最终图像尺寸变为原图像的 1/2(宽和高均减半)。

代码解析

# 读取灰度图像(cv2.IMREAD_GRAYSCALE表示灰度模式)face = cv2.imread('mywife.jpg', cv2.IMREAD_GRAYSCALE)cv2.imshow('face', face) # 显示原图cv2.waitKey(0) # 等待按键(0表示任意键关闭窗口)# 第一次下采样:尺寸变为原图1/2face_down_1 = cv2.pyrDown(face)cv2.imshow('down_1', face_down_1)cv2.waitKey(0)# 第二次下采样:尺寸变为down_1的1/2(原图的1/4)face_down_2 = cv2.pyrDown(face_down_1)cv2.imshow('down_2', face_down_2)cv2.waitKey(0)

运行效果:连续按任意键,会依次显示 “原图→1/2 尺寸图→1/4 尺寸图”,图像逐渐变小,但视觉上仍保持基本轮廓(因高斯滤波平滑了边缘)。

1.2 上采样(pyrUp):放大图像

上采样通过cv2.pyrUp()实现,核心步骤是:先将图像的宽和高各扩大 2 倍(新增行 / 列填充 0),再对图像进行高斯滤波(平滑填充的空白区域)。但由于下采样已丢失信息,上采样无法恢复原图细节。

代码解析

# 对原图直接上采样:尺寸变为原图2倍face_up_1 = cv2.pyrUp(face)cv2.imshow('up_1', face_up_1)cv2.waitKey(0)# 第二次上采样:尺寸变为up_1的2倍(原图的4倍)face_up_2 = cv2.pyrUp(face_up_1)cv2.imshow('up_2', face_up_2)cv2.waitKey(0)# 关键对比:对下采样图像上采样(无法复原)face_down_1_up = cv2.pyrUp(face_down_1) # down_1(1/2)→ up后(原图尺寸)face_down_2_up = cv2.pyrUp(face_down_2) # down_2(1/4)→ up后(1/2尺寸)cv2.imshow('down_1_up', face_down_1_up) # 与原图对比,明显模糊cv2.imshow('down_2_up', face_down_2_up)cv2.waitKey(0)

核心结论:face_down_1_up的尺寸与原图相同,但因下采样时丢失了高频细节(如边缘、纹理),上采样后图像会模糊,无法完全复原原图。

1.3 拉普拉斯金字塔:提取图像残差

为了保留下采样丢失的信息,可通过 “拉普拉斯金字塔” 计算 “残差图像”(原图与 “下采样 + 上采样” 图像的差值)。残差图像包含了下采样丢失的高频细节,可用于图像复原或融合。

代码解析

# 计算残差(拉普拉斯金字塔层)L0 = face - face_down_1_up # 原图与down_1_up的差值(保留原图高频细节)L1 = face_down_1 - face_down_2_up # down_1与down_2_up的差值# 显示残差图像(暗部为0,亮部为丢失的细节)cv2.imshow('L0', L0)cv2.imshow('L1', L1)cv2.waitKey(0)# 尝试复原:残差 + 下采样上采样图像fuyuan = face_down_1_up + L0 # down_1_up(模糊图)+ L0(残差)→ 接近原图cv2.imshow('fuyuan', fuyuan)cv2.waitKey(0)

运行效果:残差图像(L0、L1)中,亮区域对应原图中边缘、纹理等高频细节;复原后的图像(fuyuan)与原图几乎一致,证明残差图像成功保留了丢失的信息。

三、核心技术 2:图像直方图分析

图像直方图是反映图像像素灰度分布的工具,通过统计每个灰度值(0-255)的像素数量,可直观了解图像的亮度、对比度等特征。OpenCV 的cv2.calcHist()和 Matplotlib 的plt.hist()均可计算直方图。

3.1 灰度图像直方图(两种方法)

以love.jpg为例,分别用 Matplotlib 和 OpenCV 计算灰度图像的直方图。

方法 1:Matplotlib plt.hist ()
# 读取灰度图像love = cv2.imread('love.jpg', cv2.IMREAD_GRAYSCALE)# 将图像展平为1维数组(ravel():多维数组→1维)a = love.ravel()# 绘制直方图:bins=256(灰度级0-255)plt.hist(a, bins=256)plt.title('Gray Image Histogram (Matplotlib)')plt.xlabel('Gray Level')plt.ylabel('Pixel Count')plt.show()
方法 2:OpenCV cv2.calcHist ()
# 计算直方图:[love](输入图像)、[0](通道索引,灰度图仅1通道)# None(无掩码)、[16](直方图 bins 数量,合并灰度级)、[0,256](灰度范围)love_hist = cv2.calcHist([love], [0], None, [16], [0,256])# 绘制直方图(OpenCV计算结果需用plt.plot())plt.plot(love_hist)plt.title('Gray Image Histogram (OpenCV, bins=16)')plt.xlabel('Binned Gray Level')plt.ylabel('Pixel Count')plt.show()

对比说明:plt.hist()直接对展平后的像素数组统计,bins=256 时可显示每个灰度级的分布;cv2.calcHist()支持指定 bins 数量(如 16),将 256 个灰度级合并为 16 组,直方图更简洁。

3.2 彩色图像直方图

彩色图像包含 B(蓝)、G(绿)、R(红)3 个通道,需分别计算每个通道的直方图并绘制。

代码解析

# 读取彩色图像(cv2.imread()默认返回BGR格式,非RGB)img = cv2.imread('love.jpg')color = ('b', 'g', 'r') # 对应B、G、R通道# 遍历3个通道,计算并绘制直方图for i, col in enumerate(color):# i:通道索引(0=B,1=G,2=R)hister = cv2.calcHist([img], [i], None, [256], [0,256])plt.plot(hister, color=col) # 按通道颜色绘制plt.title('Color Image Histogram (BGR)')plt.xlabel('Gray Level')plt.ylabel('Pixel Count')plt.show()

注意事项:OpenCV 读取的彩色图像默认是 BGR 格式,而 Matplotlib 显示时默认 RGB 格式,但此处仅绘制直方图,通道顺序不影响统计结果,只需确保color元组与通道索引对应即可。

四、核心技术 3:掩码(mask)与直方图结合

掩码(mask)是一种 “区域选择” 工具,通过创建与图像尺寸相同的二进制数组(0 表示 “排除”,255 表示 “保留”),可仅对图像的指定区域进行处理(如计算直方图、滤波等)。

4.1 创建掩码与区域选择

以phone.png为例,创建掩码并选择手机图像的中间区域:

代码解析

# 读取手机灰度图像phone = cv2.imread('phone.png', cv2.IMREAD_GRAYSCALE)cv2.imshow('phone', phone)cv2.waitKey(0)# 创建全黑掩码(尺寸与phone相同,uint8类型)mask = np.zeros(phone.shape[:2], np.uint8)# 将掩码的[50:350, 100:470]区域设为255(白色,表示保留该区域)mask[50:350, 100:470] = 255cv2.imshow('mask', mask) # 显示掩码:中间白色区域为选中区域cv2.waitKey(0)

掩码原理:mask的尺寸与原图一致,像素值为 255 的区域会被 “保留”,0 的区域会被 “排除”。通过调整[50:350, 100:470]的坐标,可选择不同的目标区域。

4.2 掩码与图像结合(bitwise_and)

通过cv2.bitwise_and()函数,可将掩码应用到原图,仅保留掩码选中的区域:

# 按掩码提取区域:仅保留mask为255的像素phone_mask = cv2.bitwise_and(phone, phone, mask=mask)cv2.imshow('phone_mask', phone_mask) # 显示:仅中间区域有图像,其余为黑cv2.waitKey(0)

函数作用:cv2.bitwise_and(a, b, mask)对 a 和 b 进行按位与操作,但仅在 mask 为 255 的区域执行,最终实现 “区域裁剪” 效果。

4.3 掩码区域的直方图

仅计算掩码选中区域的直方图,可更精准地分析目标区域的像素分布:

# 计算掩码区域的直方图:mask参数指定仅统计选中区域phone_hist_mask = cv2.calcHist([phone], [0], mask, [256], [0,256])plt.plot(phone_hist_mask)plt.title('Histogram of Masked Area (Phone)')plt.xlabel('Gray Level')plt.ylabel('Pixel Count')plt.show()# 关闭所有OpenCV窗口cv2.destroyAllWindows()

实际意义:若需分析图像中特定物体(如手机屏幕)的亮度分布,通过掩码仅统计目标区域的直方图,可避免背景像素的干扰,结果更准确。

五、总结与拓展

本文通过一段实战代码,覆盖了 OpenCV 中 3 个核心图像处理技术:

  1. 图像金字塔:下采样(缩小 + 平滑)、上采样(放大 + 填充),以及拉普拉斯金字塔(提取残差,用于复原);
  1. 直方图分析:灰度图 / 彩色图的直方图计算,两种工具(Matplotlib/OpenCV)的对比;
  1. 掩码操作:通过二进制掩码选择区域,结合直方图实现精准的区域分析。

希望本文能帮助大家快速上手这些实用技术,后续可结合具体场景(如人脸识别、目标检测)进一步深化应用!


文章转载自:

http://bLeyiD5W.wtcyz.cn
http://LwEh18io.wtcyz.cn
http://9hZR4nkB.wtcyz.cn
http://dgYOXyd5.wtcyz.cn
http://atp2kfQ6.wtcyz.cn
http://KhVvd27y.wtcyz.cn
http://gsufa7KQ.wtcyz.cn
http://znfMuMD5.wtcyz.cn
http://HUoZP0ih.wtcyz.cn
http://E6PPKKyE.wtcyz.cn
http://19ns6if4.wtcyz.cn
http://LRTQMOhi.wtcyz.cn
http://AkrKWgcu.wtcyz.cn
http://tiHTllFg.wtcyz.cn
http://yQsUFObN.wtcyz.cn
http://SI9nYluv.wtcyz.cn
http://OHjGWsvh.wtcyz.cn
http://uknDTLtY.wtcyz.cn
http://FfbmWfFM.wtcyz.cn
http://OBrrzv4D.wtcyz.cn
http://QKPKYwgP.wtcyz.cn
http://BZgokumU.wtcyz.cn
http://wTuHXdxb.wtcyz.cn
http://EYqrdMNf.wtcyz.cn
http://Vf3u99Kh.wtcyz.cn
http://ZlFLsYSk.wtcyz.cn
http://wFD9VOoF.wtcyz.cn
http://EPl5QeZ6.wtcyz.cn
http://KAVdK0AL.wtcyz.cn
http://RPXoL92S.wtcyz.cn
http://www.dtcms.com/a/374443.html

相关文章:

  • MongoDB 安全加固:构建企业级纵深防御体系——用户权限管理与 TLS 加密配置详解
  • 为什么苹果签名经常会掉签?
  • http basic认证流程
  • Docker 存储卷(Volume)核心概念、类型与操作指南
  • 【iOS】 单例模式
  • Matlab机器人工具箱使用4 蒙特卡洛法绘制工作区间
  • 【华为OD】环中最长子串2
  • 08 docker搭建大数据集群
  • 【华为OD】微服务的集成测试
  • Tool | UI/BI类网址收录
  • 计算机视觉(opencv)——基于模板匹配的身份证号识别系统
  • 腾讯推出AI CLI工具CodeBuddy,国内首家同时支持插件、IDE和CLI三种形态的AI编程工具厂商
  • 前后端联调时出现的一些问题记录
  • 网络编程;套接字;TCP通讯;UDP通讯;0909
  • 最后一公里文件传输难题Localsend+cpolar破解
  • Windows 命令行:cd 命令3,当前目录,父目录,根目录
  • 医疗连续体机器人模块化控制界面设计与Python库应用研究(下)
  • Nginx 优化与防盗链
  • Spring Web 异步响应实战:从 CompletableFuture 到 ResponseBodyEmitter 的全链路优化
  • Linux基础命令使用
  • 第二章、PyTorch 入门笔记:从张量基本操作到线性回归实战
  • 【参数详解与使用指南】PyTorch MNIST数据集加载
  • Ruoyi-vue-plus-5.x第六篇Web开发与前后端交互: 6.4 WebSocket实时通信
  • vlan(局部虚拟网)
  • MissionPlanner架构梳理之(十)-参数编辑器
  • Hadoop Windows客户端配置与实践指南
  • 【NVIDIA-B200】 ‘CUDA driver version is insufficient for CUDA runtime version‘
  • 从源码视角全面解析 Chrome UI 布局系统及 Views 框架的定制化实现方法与实践经验
  • 9.9 ajax的请求和封装
  • CTFshow系列——PHP特性Web101-104