OpenCV 的几种查找图像中轮廓边缘的方法
创作时间:
作者:
@小白创作中心
OpenCV 的几种查找图像中轮廓边缘的方法
引用
CSDN
1.
https://blog.csdn.net/xulibo5828/article/details/139394245
在计算机视觉和图像处理领域,边缘检测是一项基础且重要的技术,用于识别图像中的物体边界和轮廓。OpenCV作为一款强大的开源计算机视觉库,提供了多种边缘检测方法,每种方法都有其特点和适用场景。本文将详细介绍OpenCV中常用的几种边缘检测方法,包括Sobel、Scharr、Canny、Laplacian等算子,以及如何使用自定义卷积核和基于直方图的方法进行边缘检测。
原始图片:
1、Sobel算子
Sobel算子结合了高斯平滑和微分,用于计算图像的梯度,从而突出显示边缘。
import cv2
# 读取图像
image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
# 使用Sobel算子查找水平和垂直边缘
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 叠加水平和垂直边缘
edges = cv2.addWeighted(cv2.convertScaleAbs(sobel_x), 0.5, cv2.convertScaleAbs(sobel_y), 0.5, 0)
# 显示结果
cv2.imshow("Original Image", image)
cv2.imshow("Edges", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数原型:
sobel = cv2.Sobel(src, ddepth, dx, dy, ksize, scale, delta, borderType)
参数说明:
- src: 输入图像(单通道,例如灰度图)。
- ddepth: 输出图像的深度(例如cv2.CV_64F表示64位浮点数)。
- dx: x方向上的导数阶数(0表示没有导数,1表示一阶导数)。
- dy: y方向上的导数阶数(与dx类似)。
- ksize: Sobel核的大小,必须是1, 3, 5或7等奇数。
- scale: 可选值,缩放导数结果,以便调整图像亮度(默认值为1)。
- delta: 可选值,在存储之前添加到结果中的值(默认值为0)。
- borderType: 边界类型,用于确定图像边界(默认值为cv2.BORDER_DEFAULT)。
2、Scharr算子
Scharr算子是一种改进的Sobel算子,适用于增强边缘检测的精度,在正常的Sobel核的尺寸上有更好的性能。
scharr_x = cv2.Scharr(src, ddepth, dx, dy, scale, delta, borderType)
参数说明:
- 与cv2.Sobel()相同,只是ksize参数被硬编码为3。
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
# 使用Scharr算子计算x和y方向上的梯度
grad_x = cv2.Scharr(image, cv2.CV_64F, 1, 0)
grad_y = cv2.Scharr(image, cv2.CV_64F, 0, 1)
# 将梯度取绝对值并转换为8位图像
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
# 合并x方向和y方向的梯度
scharr = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
# 显示图像
cv2.imshow('Scharr Edge Detection', scharr)
cv2.waitKey(0)
cv2.destroyAllWindows()
3、Canny算子
Canny边缘检测是一种多级边缘检测算法,效果较为显著,常用来检测图像中的明显边缘。
函数原型:
edges = cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradient)
参数说明:
- image: 输入图像,通常是灰度图。
- threshold1: 较低的阈值,用于边缘检测的滞后阈值过程。
- threshold2: 较高的阈值。
- apertureSize: Sobel算子的大小,默认值为3。
- L2gradient: 可选参数,用于计算图像梯度幅值的标志。如果为True,则使用更精确的L2范数计算梯度,否则使用L1范数。
import cv2
# 读取图像并转换为灰度图
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# 使用Canny边缘检测
edges = cv2.Canny(image, 100, 200)
# 显示图像
cv2.imshow('Canny Edge Detection', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
4、Laplacian算子
Laplacian算子是一种二阶导数算子,用于检测图像中的边缘。
laplacian = cv2.Laplacian(src, ddepth, ksize, scale, delta, borderType)
参数说明:
- src: 输入图像。
- ddepth: 输出图像的深度。
- ksize: Laplacian算子的大小,必须是正奇数。
- scale: 可选参数,用于缩放导数值,默认值为1。
- delta: 可选参数,在存储之前添加到结果中的值,默认值为0。
- borderType: 边界模式,默认值为cv2.BORDER_DEFAULT。
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# 使用Laplacian边缘检测
laplacian = cv2.Laplacian(image, cv2.CV_64F)
# 将结果转换为8位图像
laplacian = cv2.convertScaleAbs(laplacian)
# 显示图像
cv2.imshow('Laplacian Edge Detection', laplacian)
cv2.waitKey(0)
cv2.destroyAllWindows()
5、Prewitt算子
Prewitt算子是另一种一阶导数算子,可以检测水平和垂直边缘。虽然OpenCV没有直接提供cv2.prewitt()函数,但可以使用cv2.filter2D函数自定义Prewitt核来实现。
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
# 定义Prewitt核
prewitt_kernel_x = np.array([[1, 0, -1],
[1, 0, -1],
[1, 0, -1]])
prewitt_kernel_y = np.array([[1, 1, 1],
[0, 0, 0],
[-1, -1, -1]])
# 使用Prewitt核进行边缘检测
grad_x = cv2.filter2D(image, cv2.CV_64F, prewitt_kernel_x)
grad_y = cv2.filter2D(image, cv2.CV_64F, prewitt_kernel_y)
# 计算梯度幅值
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
prewitt = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
# 显示图像
cv2.imshow('Prewitt Edge Detection', prewitt)
cv2.waitKey(0)
cv2.destroyAllWindows()
6、Roberts Cross算子
罗伯特交叉算子是一种简单且快速的边缘检测算子,适用于检测图像的对角边缘。OpenCV中没有直接提供罗伯特交叉算子,但可以通过自定义卷积核实现。
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# 定义Roberts核
roberts_kernel_x = np.array([[1, 0],
[0, -1]])
roberts_kernel_y = np.array([[0, 1],
[-1, 0]])
# 使用Roberts核进行边缘检测
grad_x = cv2.filter2D(image, cv2.CV_64F, roberts_kernel_x)
grad_y = cv2.filter2D(image, cv2.CV_64F, roberts_kernel_y)
# 计算梯度幅值
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
roberts = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
# 显示图像
cv2.imshow('Roberts Edge Detection', roberts)
cv2.waitKey(0)
cv2.destroyAllWindows()
7、自定义卷积核
还可以通过自定义卷积核来进行边缘检测。
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
# 定义自定义卷积核
custom_kernel = np.array([[-1, -1, -1],
[-1, 7, -1],
[-1, -1, -1]])
# 使用自定义卷积核进行边缘检测
custom_edges = cv2.filter2D(image, cv2.CV_64F, custom_kernel)
# 将结果转换为8位图像
custom_edges = cv2.convertScaleAbs(custom_edges)
# 显示图像
cv2.imshow('Custom Kernel Edge Detection', custom_edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
8、基于直方图的边缘检测
基于直方图的方法,通过分析图像的灰度直方图来检测边缘。
import cv2
import numpy as np
# 读取图像并转换为灰度图
image = cv2.imread('image.png', cv2.IMREAD_GRAYSCALE)
# 计算图像的直方图
hist = cv2.calcHist([image], [0], None, [256], [0, 256])
# 找到直方图的峰值
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(hist)
# 使用峰值作为阈值进行二值化处理
_, binary = cv2.threshold(image, max_loc[1] - 30, 255, cv2.THRESH_BINARY)
# 显示图像
cv2.imshow('Histogram Based Edge Detection', binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
9、自适应阈值
自适应阈值可以在照明不均匀的情况下检测边缘。
函数原型:
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
参数说明:
- src:输入图像,应为灰度图像(单通道)。
- maxValue:指定在满足条件时给输出像素赋予的最大值(通常为255)。
- adaptiveMethod:自适应方法。可选值有:
- cv2.ADAPTIVE_THRESH_MEAN_C:基于邻域均值的自适应阈值化方法。
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C:基于邻域加权均值的自适应阈值化方法。
- thresholdType:阈值类型,应为cv2.THRESH_BINARY或cv2.THRESH_BINARY_INV。
- blockSize:指定用于计算阈值的邻域大小,一般为奇数。
- C:从计算的平均值或加权平均值中减去的常数。
import cv2
# 读取图像并转换为灰度图
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# 自适应阈值
adaptive_threshold = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
# 显示图像
cv2.imshow('Adaptive Threshold Edge Detection', adaptive_threshold)
cv2.waitKey(0)
cv2.destroyAllWindows()
10、阈值化(cv2.threshold)
简单的全局阈值化方法,通过固定的阈值来二值化图像以检测边缘。
import cv2
# 读取图像并转换为灰度图
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# 全局阈值化
_, threshold = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
# 显示图像
cv2.imshow('Global Threshold Edge Detection', threshold)
cv2.waitKey(0)
cv2.destroyAllWindows()
热门推荐
“5G+心理健康试点项目”取得阶段性成果,12项创新应用助力全民心理健康服务
黄芪山楂可以一起泡水饮吗?
大兴安岭至张家界五日深度游全攻略:路线、景点推荐与旅行贴士
四年级数学期末冲刺,真题刷起来!
FaceTime高风险原因揭秘:你真的了解吗?
和平精英身法训练秘籍,让你秒变高手!
《和平精英》新手必学:14种身法技巧详解
智慧煤矿用电安全监控系统:技术革新与应用实践
日照必打卡:万平口5大入口特色全解,东夷小镇深度游
传统文化遇现代理念,<归来的村庄>演绎乡村振兴新篇
从上访不断到产业兴旺,白坡乡党委书记王天生的治理之路
<啊,父老乡亲>折射农村治理困境,重庆城口探索破解之道
十大不含淀粉的主食:减肥者一定要看看!
快递业务量突破1500亿件,释放中国消费潜力,引领零售新变局
杭州清河坊街春节攻略:南宋古街里的年味打卡指南
古代宫女选拔竟如此严苛?
MATLAB直线拟合在经济学中的趋势分析:经济趋势分析和预测
跟着阿洁玩转兰州两日游
兰州中山桥:百年传奇背后的秘密
兰州特色休闲活动推荐:打卡黄河母亲雕塑、中山桥、兰州博物馆、白塔山公园、兰州夜市
高效时间管理:9位成功人士的实用经验分享
呼伦贝尔草原:冰臼火山林与湿地湖泊共生的自然奇观
《三国演义》主题曲:滚滚长江东逝水
杨洪基版《三国演义》主题曲:一首唱响28年的英雄赞歌
心血管疾病预防新突破:柔性电子与AI赋能可穿戴血压监测
制定计划、学会放松:六大实用技巧应对职场压力
《死神》星十字骑士团女团:美少女战士的战斗传奇
一文看懂保险文书和保险合同的关键!
重拾友情,从一句问候开始
破译“智胜”关键之策:多重耐药革兰阴性菌感染的挑战与期冀