《OpenCV》——边缘检测、轮廓检测

文章目录

边缘检测

  • 在图像中,边缘通常是指那些像素值发生急剧变化的地方。这种变化可以是从亮到暗(如物体的阴影边界),也可以是从暗到亮(如光照下物体的轮廓),或者是在不同颜色区域之间的过渡。
  • 边缘包含了图像中物体形状的重要信息。通过提取边缘,可以大大减少图像中的数据量,同时保留物体的关键结构特征。这对于后续的图像分析任务,如目标识别、图像分割和形状匹配等非常有帮助。例如,在自动驾驶汽车中,边缘检测可以帮助识别道路、车辆和行人的轮廓,从而为驾驶决策提供依据。

sobel算子

sobel算子

python 复制代码
# cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
# 参数:
# src:输入图像
# ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度
# dx,dy:当组合为dx=1,dy=0时求x方向的一阶导数,当组合为dx=0,dy=1时求y方向的一阶导数(如果同时为1,通常效果不佳)
# ksize:(可选参数)Sobel算子的大小,必须是1,3,5或者7,默认为3。
yuan = cv2.imread('yuan.png')
cv2.imshow('yuan',yuan)
cv2.waitKey(0)
# # x方向上的边缘
yuan_x = cv2.Sobel(yuan,-1,dx=1,dy=0)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(0)
# x方向上的边缘,包括负数信息(右端),但显示不出来,因为范围是(0~255)
yuan_x_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0)#默认uint8改为float64,可保存负数
cv2.imshow('yuan_x_64',yuan_x_64)
cv2.waitKey(0)
# #x方向上的边缘,包括负数信息,进行取绝对值的操作,右端的负值信息就可以显示出来了
yuan_x_full = cv2.convertScaleAbs(yuan_x_64)#转换为绝对值,负数转换为正数
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(0)
# # y方向上的边缘
yuan_y = cv2.Sobel(yuan,-1,dx=0,dy=1)
cv2.imshow('yuan_y',yuan_y)
cv2.waitKey(0)
# y方向上的边缘,包括负数信息(下端),但显示不出来,因为范围是(0~255)
yuan_y_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
yuan_y_full = cv2.convertScaleAbs(yuan_y_64)#转换为绝对值,负数转换为正数
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(0)
# #如果同时使用x,y方向的结果如何呢?(不建议使用)
yuan_xy = cv2.Sobel(yuan,-1,dx=1,dy=1)
cv2.imshow('yuan_xy',yuan_xy)
cv2.waitKey(100000)
# #使用图像加权运算组合x和y方向的2个边缘。
yuan_xy_full = cv2.addWeighted(yuan_x_full,1,yuan_y_full,1,0)
cv2.imshow('yuan_xy_full',yuan_xy_full)
cv2.waitKey(0)

读取图像观看效果 sobel算子

python 复制代码
zl = cv2.imread('HFC.jpg',cv2.IMREAD_GRAYSCALE)#不用灰度试试效果
zl_x_64 = cv2.Sobel(zl,cv2.CV_64F,dx=1,dy=0)#默认int8改为float64,可保存负数
zl_x_full = cv2.convertScaleAbs(zl_x_64)#转换为绝对值,负数转换为正数
zl_y_64 = cv2.Sobel(zl,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
zl_y_full = cv2.convertScaleAbs(zl_y_64)#转换为绝对值,负数转换为正数
zl_xy_sobel_full = cv2.addWeighted(zl_x_full,1,zl_y_full,1,0)
cv2.imshow('zl_xy_sobel_full',zl_xy_sobel_full)
cv2.waitKey(0)

Scharr 算子

python 复制代码
# # # #Scharr 算子  ʃaːɐ̯
# # # # cv.Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]])
# # # # src:输入图像
# # # # ddepth:输出图片的数据深度,由输入图像的深度进行选择
# # # # dx:x 轴方向导数的阶数
# # # # dy:y 轴方向导数的阶数
zl = cv2.imread('HFC.jpg',cv2.IMREAD_GRAYSCALE)
zl_x_64 = cv2.Scharr(zl,cv2.CV_64F,dx=1,dy=0)#默认int8改为float64,可保存负数
zl_x_full = cv2.convertScaleAbs(zl_x_64)#转换为绝对值,负数转换为正数
zl_y_64 = cv2.Scharr(zl,cv2.CV_64F,dx=0,dy=1)#默认int8改为float64,可保存负数
zl_y_full = cv2.convertScaleAbs(zl_y_64)#转换为绝对值,负数转换为正数
zl_xy_Scharr_full = cv2.addWeighted(zl_x_full,1,zl_y_full,1,0)
cv2.imshow('zl_xy_Scharr_full',zl_xy_Scharr_full)
cv2.waitKey(0)
# #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
# # #cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
# # # 参数说明:
# # # src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
# # # ddepth:输出图片的数据深度:
# # # ksize:计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
# # # scale:缩放比例因子,可选项,默认值为 1
# # # delta:输出图像的偏移量,可选项,默认值为 0
#
zl = cv2.imread('HFC.jpg',cv2.IMREAD_GRAYSCALE)
zl_lap = cv2.Laplacian(zl,cv2.CV_64F)
zl_lap_full = cv2.convertScaleAbs(zl_lap)#转换为绝对值,负数转换为正数
cv2.imshow('zl_lap_full',zl_lap_full)
cv2.waitKey(0)


canny边缘检测

python 复制代码
# # # canny边缘检测
# # # cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
# # # image 为输入图像。
# # # threshold1 表示处理过程中的第一个阈值。fL
# # # threshold2 表示处理过程中的第二个阈值。fH
# #
zl = cv2.imread('HFC.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow('zl',zl)
cv2.waitKey(0)
zl_canny = cv2.Canny(zl,100,150)#低,高
cv2.imshow('zl_canny',zl_canny)
cv2.waitKey(0)

轮廓检测

  • 帮助我们提取图像中的关键信息,如物体的形状、纹理、结构等

查找轮廓

python 复制代码
# 查找轮廓的API:image, contours, hierarchy = cv2.findContours(img, mode, method)#
# 参数:img:需要实现轮廓检测的原图
# mode: 轮廓的检索模式,主要有四种方式:
#    cv2.RETR_EXTERNAL:只检测外轮廓,所有子轮廓被忽略
#    cv2.RETR_LIST:检测的轮廓不建立等级关系,所有轮廓属于同一等级
#    cv2.RETR_CCOMP:返回所有的轮廓,只建立两个等级的轮廓。一个对象的外轮廓为第1级组织结构。
#                   而对象内部中空洞的轮廓为第2级组织结构,空洞中的任何对象的轮廓又是第 1 级组织结构。
# -> cv2.RETR_TREE:返回所有的轮廓,建立一个完整的组织结构的轮廓。
# method:轮廓的近似方法,主要有以下两种:
# -> cv2.CHAIN_APPROX_NONE:存储所有的轮廓点。
#    cv2.CHAIN_APPROX_SIMPLE:压缩模式,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。
# 返回:image:返回处理的原图
# contours:包含图像中所有轮廓的list对象。其中每一个独立的轮廓信息以边界点坐标(x,y)的形式储存在numpy数组中。
# hierarchy:轮廓的层次结构。一个包含4个值的数组:[Next, Previous, First Child, Parent]
#   Next:与当前轮廓处于同一层级的下一条轮廓
#   Previous:与当前轮廓处于同一层级的上一条轮廓
#   First Child:当前轮廓的第一条子轮廓
#   Parent:当前轮廓的父轮廓
# 注意:做轮廓检测前需要将图片读取为二值数据,即像素值只为0和255。
import cv2
phone = cv2.imread('phone.png')#读取原图
phone_gray = cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY)#灰度图的处理
cv2.imshow('phone_b',phone_gray)
cv2.waitKey(0)
# phone_gray=cv2.imread('phone.png',0)  #读取灰度图
ret, phone_binary = cv2.threshold(phone_gray, 120, 255, cv2.THRESH_BINARY)#阈值处理为二值
cv2.imshow('phone_binary',phone_binary)
cv2.waitKey(0)
_,contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
print(hierarchy)
print(len(contours))

轮廓的绘制

python 复制代码
# # # # 轮廓的绘制
# # # # cv2.drawContours(image, contours, contourIdx, color, thickness=None,
# # # #                  lineType=None, hierarchy=None, maxLevel=None, offset=None)
# # # # 参数含义如下:
# # # # image:要在其上绘制轮廓的输入图像。
# # # # contours:轮廓列表,通常由cv2.findContours()函数返回。
# # # # contourIdx:要绘制的轮廓的索引。如果为负数,则绘制所有轮廓。 -1
# # # # color:轮廓的颜色,以BGR格式表示。例如,(0, 255, 0)表示绿色。
# # # # thickness:轮廓线的粗细。默认值为1。
# # # # lineType:轮廓线的类型。默认值为cv2.LINE_8。
# # # # hierarchy:轮廓层次结构。通常由cv2.findContours()函数返回。
# # # # maxLevel:绘制的最大轮廓层级。默认值为None,表示绘制所有层级。
# # # # offset:轮廓点的偏移量。默认值为None。
# # #
image_copy = phone.copy()
image_copy = cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1,color=(0,255,0),thickness=3)
cv2.imshow('Contours_show', image_copy)
cv2.waitKey(0)

轮廓特征

python 复制代码
# #轮廓特征
# # cv2.contourArea(contour[, oriented]) → retval      面积
# # contour:顶点构成的二维向量组(如轮廓列表contours中的一个轮廓)
# # oriented:定向区域标志,默认值为 False,返回面积的绝对值,Ture 时则根据轮廓方向返回带符号的数值
#
area_0 = cv2.contourArea(contours[0])
print(area_0)
area_1 = cv2.contourArea(contours[1])
print(area_1)
#
# # arcLength(InputArray curve, bool closed)              周长
# # curve,输入的二维点集(轮廓顶点),可以是 vector 或 Mat 类型。
# # closed,用于指示曲线是否封闭。
length = cv2.arcLength(contours[0],closed=True)
print(length)
# 根据面积显示特定轮廓
a_list=[]
# for i in range(len(contours)):
#     if cv2.contourArea(contours[i])>10000:
#         a_list.append(contours[i])
for i in contours:
    if cv2.contourArea(i)>10000:
        a_list.append(i)
image_copy = phone.copy()
image_copy = cv2.drawContours(image=image_copy, contours=a_list, contourIdx=-1,color=(0,255,0),thickness=3)
cv2.imshow('Contours_show_10000', image_copy)
cv2.waitKey(0)

轮廓的近似

python 复制代码
# 轮廓的近似
# approx = cv2.approxPolyDP(curve, epsilon, closed)
# 参数说明:
# curve:输入轮廓。
# epsilon:近似精度,即两个轮廓之间最大的欧式距离。该参数越小,得到的近似结果越接近实际轮廓;反之,得到的近似结果会更加粗略。
# closed:布尔类型的参数,表示是否封闭轮廓。如果是 True,表示输入轮廓是封闭的,近似结果也会是封闭的;否则表示输入轮廓不是封闭的,近似结果也不会是封闭的。
# 返回值:approx:近似结果,是一个ndarray数组,为1个近似后的轮廓,包含了被近似出来的轮廓上的点的坐标

phone = cv2.imread('phone.png')
phone_gray = cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY) #转换为灰度图
ret,phone_thresh = cv2.threshold(phone_gray,120,255,cv2.THRESH_BINARY)  #二值化

image, contours, hierarchy = cv2.findContours(phone_thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)#获取轮廓
# #
epsilon = 0.01 * cv2.arcLength(contours[0],True)        #设置近似精度
approx = cv2.approxPolyDP(contours[0], epsilon, True)   #对轮廓进行近似
print(approx.shape)
phone_new = phone.copy()
image_contours = cv2.drawContours(phone_new,[approx],contourIdx=-1,color=(0,255,0),thickness=3)#绘制轮廓
cv2.imshow('phone',phone)
cv2.waitKey(0)
cv2.imshow('image_contours',image_contours)
cv2.waitKey(0)
# # # $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
# # # 外接圆、外接矩形,...
cnt = contours[6]
(x,y),r = cv2.minEnclosingCircle(cnt)#计算轮廓的外接圆
phone_circle = cv2.circle(phone,(int(x),int(y)),int(r),(0,255,0),2)#绘制外接圆的方法
cv2.imshow('phone_circle',phone_circle)
cv2.waitKey(0)

x,y,w,h = cv2.boundingRect(cnt)#计算轮廓的最小外接矩形
phone_rectangle = cv2.rectangle(phone,(x,y),(x+w,y+h),(0,255,0),2)  #在图像上绘制矩形
cv2.imshow('phone_rectangle',phone_rectangle)
cv2.waitKey(0)
相关推荐
Maker~2 小时前
30、论文阅读:基于小波的傅里叶信息交互与频率扩散调整的水下图像恢复
论文阅读·计算机视觉
灵魂画师向阳3 小时前
【CSDN首发】Stable Diffusion从零到精通学习路线分享
人工智能·学习·计算机视觉·ai作画·stable diffusion·midjourney
jndingxin3 小时前
OpenCV相机标定与3D重建(43)用于计算矫正和重映射的变换函数initUndistortRectifyMap()的使用
opencv·3d
埃菲尔铁塔_CV算法3 小时前
BOOST 在计算机视觉方面的应用及具体代码分析(二)
c++·人工智能·算法·机器学习·计算机视觉
刘大猫264 小时前
《docker基础篇:4.Docker镜像》包括是什么、分层的镜像、UnionFS(联合文件系统)、docker镜像的加载原理、为什么docker镜像要采用这种
人工智能·算法·计算机视觉
湫ccc4 小时前
《Opencv》基础操作详解(5)
人工智能·opencv·计算机视觉
好评笔记5 小时前
多模态论文笔记——U-ViT(国内版DiT)
论文阅读·人工智能·深度学习·计算机视觉·aigc·transformer·u-vit
知来者逆5 小时前
安卓NDK视觉开发——手机拍照文档边缘检测实现方法与库封装
深度学习·计算机视觉·智能手机·扫描全能王·边缘检测
是十一月末7 小时前
Opencv查找、绘制轮廓、圆形矩形轮廓和近似轮廓
人工智能·python·opencv·计算机视觉
格林威7 小时前
Baumer工业相机堡盟LXT工业相机如何升级固件使得相机具有RDMA功能
人工智能·数码相机·算法·计算机视觉·c#