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

OpenCV--图像梯度处理,图片轮廓,边缘检测

一.图像梯度处理

  • 图像梯度处理是图像分析中的一个重要技术,用于检测图像中的边缘、纹理和结构。梯度表示图像亮度变化的方向和幅度,常用于边缘检测、特征提取和图像分割等任务。以下是 OpenCV 中常用的图像梯度处理方法及其函数。

1. 梯度计算

Sobel 算子–cv2.Sobel()`

Sobel 算子用于计算图像在水平和垂直方向的梯度。这有助于检测边缘。

函数:cv2.Sobel()

函数签名:

cv2.Sobel(src, ddepth, dx, dy, ksize, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)

参数解释:

  • src:输入图像(通常是灰度图像)。
  • ddepth:目标图像的深度,常用 cv2.CV_16S(有符号 16 位)或 cv2.CV_8U(无符号 8 位)。
  • dx:x 方向的导数阶数(0 表示不计算 x 方向的梯度)。
  • dy:y 方向的导数阶数(0 表示不计算 y 方向的梯度)。
  • ksize:Sobel 卷积核的大小(常用值为 1、3、5、7)。
  • scale:缩放系数,用于调整结果的大小(默认值 1)。
  • delta:在计算梯度值时添加的偏移量(默认值 0)。
  • borderType:边界类型,通常使用 cv2.BORDER_DEFAULT

示例代码:

import cv2
import numpy as np# 读取灰度图像
gray_image = cv2.imread('gray_image.jpg', cv2.IMREAD_GRAYSCALE)# 计算 x 方向的梯度
sobel_x = cv2.Sobel(gray_image, -1, 1, 0, ksize=3)# 计算 y 方向的梯度
sobel_y = cv2.Sobel(gray_image,-1, 0, 1, ksize=3)# 合并 x 和 y 方向的梯度
sobel_combined = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)# 显示图像
cv2.imshow('Sobel X', sobel_x)
cv2.imshow('Sobel Y', sobel_y)
cv2.imshow('Sobel Combined', sobel_combined)
cv2.waitKey(0)
cv2.destroyAllWindows()
Laplacian 算子—cv2.Laplacian()

Laplacian 算子用于计算图像的二阶导数,常用于检测边缘和角点。

函数:cv2.Laplacian()

函数签名:

cv2.Laplacian(src, ddepth, ksize=1, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)

参数解释:

  • src:输入图像(通常是灰度图像)。
  • ddepth:目标图像的深度,常用 cv2.CV_16Scv2.CV_8U
  • ksize:卷积核的大小(常用值为 1、3、5、7)。
  • scale:缩放系数(默认值 1)。
  • delta:添加的偏移量(默认值 0)。
  • borderType:边界类型(通常使用 cv2.BORDER_DEFAULT)。

示例代码:

import cv2# 读取灰度图像
gray_image = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE)# 计算 Laplacian
laplacian = cv2.Laplacian(gray_image, ksize=3)# 显示图像
cv2.imshow('Laplacian', laplacian)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. Canny 边缘检测

Canny 边缘检测算法是一种多阶段边缘检测算法,用于检测图像中的边缘。

函数:cv2.Canny()

函数签名:

cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)

参数解释:

  • image:输入的灰度图像。
  • threshold1:第一个阈值,用于低梯度强度的边缘。
  • threshold2:第二个阈值,用于高梯度强度的边缘。
  • apertureSize:Sobel 算子的孔径大小(默认值 3)。
  • L2gradient:是否使用更精确的 L2 范数来计算梯度(默认值 False)。

示例代码:

import cv2# 读取灰度图像
gray_image = cv2.imread('gray_image.jpg', cv2.IMREAD_GRAYSCALE)# Canny 边缘检测
edges = cv2.Canny(gray_image, 100, 200)# 显示图像
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

这些函数和算法提供了强大的图像梯度处理能力,可以帮助你进行各种图像分析和处理任务。

3.cv2.addWeighted() --将两幅图像进行加权融合

cv2.addWeighted() 是 OpenCV 中的一个函数,用于将两幅图像进行加权融合。它能够将两张图像按照指定的权重进行线性组合,从而得到一幅新的图像。这种操作常用于图像混合、图像叠加、以及在图像处理和计算机视觉中的各种应用。

函数签名

cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])

参数解释

  • src1: 第一幅输入图像,可以是多通道(如彩色图像)或单通道(如灰度图像)。
  • alpha: 第一幅图像的权重。该参数决定了 src1 在结果图像中所占的比例。
  • src2: 第二幅输入图像,要求与 src1 的大小和通道数相同。
  • beta: 第二幅图像的权重。该参数决定了 src2 在结果图像中所占的比例。
  • gamma: 加到最终结果上的标量值,相当于图像整体的亮度调节。
  • dst (可选): 输出的目标图像,可以与 src1src2 相同,也可以是新的图像。
  • dtype (可选): 输出图像的数据类型。通常不需要指定,默认与输入图像类型一致。

函数功能

cv2.addWeighted() 计算如下公式来进行图像融合:

[ \text{dst}(x, y) = \text{src1}(x, y) \times \alpha + \text{src2}(x, y) \times \beta + \gamma ]

其中:

  • src1(x, y)src2(x, y) 分别表示两幅图像在位置 (x, y) 处的像素值。
  • alphabeta 控制图像的融合比例。
  • gamma 控制结果图像的整体亮度。

示例代码

示例 1: 简单的图像混合
import cv2# 读取两幅图像
image1 = cv2.imread('image1.jpg')
image2 = cv2.imread('image2.jpg')# 调整图像大小使其相同
image1 = cv2.resize(image1, (400, 400))
image2 = cv2.resize(image2, (400, 400))# 线性加权融合图像
alpha = 0.7
beta = 0.3
gamma = 0
blended_image = cv2.addWeighted(image1, alpha, image2, beta, gamma)# 显示结果
cv2.imshow('Blended Image', blended_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这个示例中,我们读取了两幅图像并将其调整到相同的大小。使用 cv2.addWeighted() 函数以 0.7 和 0.3 的权重混合这两幅图像。gamma 设置为 0,表示不进行亮度调整。

示例 2: 添加亮度调整的图像融合
import cv2# 读取两幅图像
image1 = cv2.imread('image1.jpg')
image2 = cv2.imread('image2.jpg')# 调整图像大小使其相同
image1 = cv2.resize(image1, (400, 400))
image2 = cv2.resize(image2, (400, 400))# 线性加权融合图像,且添加亮度调整
alpha = 0.6
beta = 0.4
gamma = 50  # 提高亮度
blended_image = cv2.addWeighted(image1, alpha, image2, beta, gamma)# 显示结果
cv2.imshow('Blended Image with Brightness', blended_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

使用 cv2.addWeighted() 调整图像的亮度和对比度。alpha 控制对比度,beta 控制亮度。通过将同一图像作为 src1 和 src2 使用,我们可以通过调整 alpha 和 beta 来改变图像的亮度和对比度。

二.绘制图像轮廓

  • 在计算机视觉中,绘制图像轮廓是一个常见的操作,用于可视化和分析图像中的边缘和形状。OpenCV 提供了几种方法来检测和绘制图像轮廓。以下是一些常用的方法和示例代码。

  • 在OpenCV中,cv2.findContours()cv2.drawContours()是两个常用于处理图像轮廓的函数。下面对这两个函数的参数进行详细说明。

1. cv2.findContours()

函数原型:
contours, hierarchy = cv2.findContours(image, mode, method)
参数说明:
  • image: 输入图像,通常为二值化图像(像素值为0或255)。在调用此函数之前,建议使用如cv2.threshold()cv2.Canny()等函数进行图像处理,确保图像是二值的。

  • mode: 轮廓检索模式,用于指定如何获取轮廓。选项包括:

    • cv2.RETR_EXTERNAL: 只提取最外层的轮廓。
    • cv2.RETR_LIST: 提取所有的轮廓,但不建立层级关系。
    • cv2.RETR_TREE: 提取所有轮廓,并重建轮廓之间的层级关系。
    • cv2.RETR_CCOMP: 提取所有的轮廓,并组织为两级层次结构。
  • method: 轮廓逼近方法,用于指定如何近似轮廓。选项包括:

    • cv2.CHAIN_APPROX_SIMPLE: 只保留水平、垂直和斜线段,省略所有冗余点,节省内存。
    • cv2.CHAIN_APPROX_NONE: 保留所有轮廓点,更详细,但是消耗更多内存。
返回值:
  • contours: 轮廓的列表,每个轮廓都是一组点的数组。
  • hierarchy: 结构体,表示轮廓之间的层级关系,通常为一个Numpy数组。
示例代码:
import cv2
import numpy as np# 读取图像并转换为灰度图像
image = cv2.imread('image.jpg')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 使用阈值处理将图像转换为二值图像
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)# 检测轮廓
contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 在原图像上绘制轮廓
contour_image = image.copy()
cv2.drawContours(contour_image, contours, -1, (0, 255, 0), 2)  # 绿色轮廓,线宽为 2# 显示结果
cv2.imshow('Contours', contour_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. cv2.drawContours()

函数原型:
cv2.drawContours(image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel)
参数说明:
  • image: 输入图像,要在其上绘制轮廓。

  • contours: 轮廓数组,通常是从findContours得到的contours

  • contourIdx: 要绘制的轮廓索引,可以是一个整数:

    • -1表示绘制所有轮廓。
    • 其他非负整数绘制特定索引的轮廓(例如,0表示第一个轮廓)。
  • color: 轮廓颜色,通常以BGR格式表示,如(255, 0, 0)表示红色。

  • thickness: 轮廓线的厚度:可以是正整数(表示线段的厚度),或者是cv2.FILLED(用指定颜色填充轮廓内)。

  • lineType: 线型,通常使用cv2.LINE_8cv2.LINE_AA(抗锯齿线)等。

  • hierarchy: 可选参数,通常不需要。如果指定了,通常用于选择按层绘制的轮廓。

  • maxLevel: 可选参数,用于限制绘制轮廓的最大层级,通常不需要设置。

示例

import cv2
import numpy as np# 创建一个二值图像
image = np.zeros((400, 400), dtype=np.uint8)
cv2.rectangle(image, (50, 50), (350, 350), 255, -1)# 查找轮廓
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 在原图上绘制轮廓
output = np.zeros((400, 400, 3), dtype=np.uint8)
cv2.drawContours(output, contours, -1, (0, 255, 0), 3)# 显示结果
cv2.imshow('Contours', output)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 使用 cv2.fillPoly() 填充轮廓

如果你想要填充轮廓区域,可以使用 cv2.fillPoly() 函数。

示例代码:
import cv2
import numpy as np# 读取图像并转换为灰度图像
image = cv2.imread('image.jpg')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 使用阈值处理将图像转换为二值图像
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)# 检测轮廓
contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 在原图像上填充轮廓
filled_image = image.copy()
cv2.fillPoly(filled_image, contours, (0, 255, 0))  # 填充绿色区域# 显示结果
cv2.imshow('Filled Contours', filled_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

相关文章:

  • 打印一个字符串全部子序列(没有重复字面值)
  • 刷题记录第108天-求一个数的平方根(精确到小数点后五位)
  • 使用 C/C++访问 MySQL
  • repo简介
  • CUDA C++ 编程指南学习(待更)
  • ubuntu16.04安装ibus拼音 输入法
  • 使用功率器件比如MOSFET瞬态热阻曲线计算参数
  • 【myz_tools】Python库 myz_tools:Python算法及文档自动化生成工具
  • 基于NXP IMX6Q+FPGA全自动血液分析仪解决方案
  • 分布式事务和一致性
  • 基于 Konva 实现Web PPT 编辑器(一)
  • ORB-SLAM3(Failed to load image)问题解决(WSL2配置)
  • 电脑版视频剪辑软件哪个好?适合新手使用的剪辑软件!
  • 贪心算法介绍(Greedy Algorithm)
  • enhanced Input Action IA_Look中Action value引脚没有分割结构体引脚的选项
  • [NodeJS] 关于Buffer
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Laravel Mix运行时关于es2015报错解决方案
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • 阿里云购买磁盘后挂载
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 配置 PM2 实现代码自动发布
  • 译自由幺半群
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • #单片机(TB6600驱动42步进电机)
  • (leetcode学习)236. 二叉树的最近公共祖先
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (转)JAVA中的堆栈
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .net 验证控件和javaScript的冲突问题
  • .NET运行机制
  • ??javascript里的变量问题
  • []FET-430SIM508 研究日志 11.3.31
  • [20190113]四校联考
  • [Android] 修改设备访问权限
  • [Angular] 笔记 8:list/detail 页面以及@Input
  • [bug总结]: Feign调用GET请求找不到请求体实体类
  • [BZOJ1060][ZJOI2007]时态同步 树形dp
  • [C# 开发技巧]如何使不符合要求的元素等于离它最近的一个元素
  • [C#] 基于 Token 的鉴权与签名机制详解 接口对接鉴权 token、sign(a=1b=2c=3d=4)、Base64、参数加密、MD5
  • [C#]C#学习笔记-CIL和动态程序集
  • [C++][基础]1_变量、常量和基本类型
  • [CodeForces-759D]Bacterial Melee
  • [excel与dict] python 读取excel内容并放入字典、将字典内容写入 excel文件
  • [HDCTF 2023]Welcome To HDCTF 2023
  • [Hive]五、Hive 源码编译
  • [IE9] IE9 beta版下载链接
  • [Linux内核驱动]模块参数
  • [MRCTF2020]Ezpop
  • [msg_msg] corCTF2021 -- fire_of_salvation