Python opencv图像处理基础总结(六) 直线检测 圆检测 轮廓发现

简介: 我还有改变的可能性一想起这一点我就心潮澎湃

一、直线检测


使用霍夫直线变换做直线检测,前提条件:边缘检测已经完成


# 标准霍夫线变换cv2.HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None)


  • image:经过边缘检测的输出图像,8位,单通道二进制源图像。
  • rho:距离步长
  • theta:角度步长
  • threshold:阈值,只有大于该值的点才有可能被当作极大值,即至少有多少条正弦曲线交于一点才被认为是直线。


# 统计概率霍夫线变换cv2.HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None)


  • 经过边缘检测的输出图像,8位,单通道二进制源图像。
  • rho:参数极径 r ,以像素值为单位的分辨率,这里一般使用 1 像素。
  • theta:参数极角theta, 以弧度为单位的分辨率,这里使用 1 度。
  • threshold:检测一条直线所需最少的曲线交点
  • minLineLength:线的最短长度,比这个线短的都会被忽略。
  • maxLineGap:两条线之间的最大间隔,如果小于此值,这两条线就会被看成一条线。


代码如下:


importcv2importnumpyasnp# 标准霍夫线变换defline_detection_demo(image):
# 灰度图像gray=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 提取边缘edges=cv2.Canny(gray, 50, 150, apertureSize=3)
lines=cv2.HoughLines(edges, 1, np.pi/180, 160)
forlineinlines:
rho, theta=line[0]  # line[0]存储的是点到直线的极径和极角,其中极角是弧度表示的a=np.cos(theta)     # theta是弧度b=np.sin(theta)
x0=a*rhoy0=b*rhox1=int(x0+1000* (-b))  # 直线起点横坐标y1=int(y0+1000*a)     # 直线起点纵坐标x2=int(x0-1000* (-b))  # 直线终点横坐标y2=int(y0-1000*a)     # 直线终点纵坐标cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow("image_lines", image)
# 统计概率霍夫线变换defline_detect_possible_demo(image):
gray=cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
edges=cv2.Canny(gray, 50, 150, apertureSize=3)
lines=cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=50, maxLineGap=10)
forlineinlines:
x1, y1, x2, y2=line[0]
cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow("line_detect_possible", image)
if__name__=="__main__":
src=cv2.imread(r"./test/041.png")
cv2.imshow("image", src)
line_detection_demo(src)
line_detect_possible_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()


运行效果如下:



二、圆检测


  • 霍夫圆变换的基本原理和霍夫线变换原理类似,只是点对应的二维极径、极角空间被三维的圆心和半径空间取代。在标准霍夫圆变换中,原图像的边缘图像的任意点对应的经过这个点的所有可能圆在三维空间用圆心和半径这三个参数来表示,其对应一条三维空间的曲线。对于多个边缘点,点越多,这些点对应的三维空间曲线交于一点的数量越多,那么他们经过的共同圆上的点就越多,类似的我们也就可以用同样的阈值的方法来判断一个圆是否被检测**到,这就是标准霍夫圆变换的原理, 但也正是在三维空间的计算量大大增加的原因,**标准霍夫圆变化很难被应用到实际中。
  • OpenCV实现的是一个比标准霍夫圆变换更为灵活的检测方法——霍夫梯度法,该方法运算量相对于标准霍夫圆变换大大减少。其检测原理是依据圆心一定是在圆上的每个点的模向量上,这些圆上点模向量的交点就是圆心,霍夫梯度法的第一步就是找到这些圆心,这样三维的累加平面就又转化为二维累加平面。第二步是根据所有候选中心的边缘非 0 像素对其的支持程度来确定半径。注:模向量即是圆上点的切线的垂直线。


cv2.HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)


  • image:输入图像,8位单通道灰度图像。
  • method:圆检测方法
  • dp:参数表示累加器与原始图像相比的分辨率的反比参数。例如,如果dp = 1,则累加器具有与输入图像相同的分辨率。如果dp=2,累加器分辨率是元素图像的一半,宽度和高度也缩减为原来的一半。
  • minDist:检测到的两个圆心之间的最小距离。如果参数太小,除了真实的一个圆圈之外,可能错误地检测到多个相邻的圆圈。如果太大,可能会遗漏一些圆圈。
  • circles:检测到的圆的输出向量,向量内第一个元素是圆的横坐标,第二个是纵坐标,第三个是半径大小。
  • param1:Canny边缘检测的高阈值,低阈值会被自动置为高阈值的一半。
  • param2:圆心检测的累加阈值,参数值越小,可以检测越多的假圆圈,但返回的是与较大累加器值对应的圆圈。
  • minRadius:检测到的圆的最小半径
  • maxRadius:检测到的圆的最大半径


代码如下:


importcv2ascvimportnumpyasnp# 霍夫圆检测defdetect_circles_demo(image):
# 霍夫圆检测对噪声敏感  边缘保留滤波EPF  消除噪声dst=cv.pyrMeanShiftFiltering(image, 10, 105)  # 均值偏移滤波cimage=cv.cvtColor(dst, cv.COLOR_RGB2GRAY)
# 输入图像 方法 走步长 最小距离 边缘提取的低值circles=cv.HoughCircles(cimage, cv.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0)
circles=np.uint16(np.around(circles))     # 把circles包含的圆心和半径的值变成整数foriincircles[0, :]:
cv.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)  # 画圆cv.circle(image, (i[0], i[1]), 2, (255, 0, 0), 2)     # 画圆心cv.imshow("circles", image)
if__name__=="__main__":
src=cv.imread(r"./test/035.png")
cv.imshow('input_image', src)
detect_circles_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()


运行效果如下:


三、轮廓发现


"""    cv2.findContours(image, mode, method, contours, hierarchy, offset)        参数:            1 要寻找图像的轮廓 只能传入二值图像,不是灰度图像            2 轮廓的检索模式,有四种:                cv2.RETR_EXTERNAL  表示只检测外轮廓                cv2.RETR_LIST      检测的轮廓不建立等级关系                cv2.RETR_CCOMP     建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层                cv2.RETR_TREE      建立一个等级树结构的轮廓            3 轮廓的近似办法                cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1                cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息        返回值:            contours:一个列表,每一项都是一个轮廓,不会存储轮廓所有的点,只存储能描述轮廓的点            hierarchy:一个ndarray, 元素数量和轮廓数量一样,                 每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],                分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数 """"""        # 函数cv2.drawContours(image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel, offset)        # 第一个参数是一张图片,可以是原图或者其他。        # 第二个参数是轮廓,也可以说是cv2.findContours()找出来的点集,一个列表。        # 第三个参数是对轮廓(第二个参数)的索引,当需要绘制独立轮廓时很有用,若要全部绘制可设为-1。        # 接下来的参数是轮廓的颜色和线宽"""


代码如下:


# -*- coding: UTF-8 -*-"""@公众号      : AI庭云君@Author     : 叶庭云@CSDN       : https://yetingyun.blog.csdn.net/"""importcv2defcontours_demo(image):
dst=cv2.GaussianBlur(image, (3, 3), 0)
gray=cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
ret, thresh=cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
# 得到修改后的图像,轮廓点集  各层轮廓的索引contours, hierarchy=cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
fori, contourinenumerate(contours):
# 绘制轮廓  第几个  颜色  线宽cv2.drawContours(image, contours, i, (0, 0, 255), -1)
print(i)
cv2.imshow("detect contours", image)
if__name__=="__main__":
img=cv2.imread(r"./test/042.png")
cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
cv2.imshow("input image", img)
contours_demo(img)
cv2.waitKey(0)
cv2.destroyAllWindows()


运行效果如下:


绘制轮廓时,线宽设置为-1,实现填充,效果如下:



通过Canny算法获取二值图像,再进行轮廓发现


# -*- coding: UTF-8 -*-"""@公众号      : AI庭云君@Author     : 叶庭云@CSDN       : https://yetingyun.blog.csdn.net/"""importcv2defedge_demo(image):
# 高斯模糊  降低噪声blurred=cv2.GaussianBlur(image, (3, 3), 0)
# 转为灰度图像gray=cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
# 计算x y 方向梯度grad_x=cv2.Sobel(gray, cv2.CV_16SC1, 1, 0)
grad_y=cv2.Sobel(gray, cv2.CV_16SC1, 0, 1)
edge_output=cv2.Canny(grad_x, grad_y,  50, 100)
returnedge_outputdefcontours_demo(image):
binary=edge_demo(image)
# 得到修改后的图像,轮廓点集  各层轮廓的索引contours, hierarchy=cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
fori, contourinenumerate(contours):
# 绘制轮廓  第几个  颜色  线宽cv2.drawContours(image, contours, i, (0, 0, 255), 2)
print(i)
cv2.imshow("detect contours", image)
if__name__=="__main__":
img=cv2.imread(r"./test/036.png")
cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
cv2.imshow("input image", img)
contours_demo(img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行效果如下:

目录
相关文章
|
1月前
|
算法 计算机视觉
OpenCV(三十七):拟合直线、三角形和圆形
OpenCV(三十七):拟合直线、三角形和圆形
49 0
|
1月前
|
编解码 计算机视觉
OpenCV(三十六):霍夫直线检测
OpenCV(三十六):霍夫直线检测
25 0
|
2月前
|
存储 数据库 计算机视觉
Python图像处理库:学会Pillow再也不用PS啦
Python图像处理库:学会Pillow再也不用PS啦
|
2月前
|
人工智能 Linux API
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
OpenCV这么简单为啥不学——1.1、图像处理(灰度图、模糊图片、GaussianBlur函数、提取边缘、边缘膨胀、边缘细化)
46 0
|
13天前
|
机器学习/深度学习 人工智能 算法
图像处理与分析:Python中的计算机视觉应用
【4月更文挑战第12天】Python在计算机视觉领域广泛应用,得益于其丰富的库(如OpenCV、Pillow、Scikit-image)和跨平台特性。图像处理基本流程包括获取、预处理、特征提取、分类识别及重建生成。示例代码展示了面部和物体检测,以及使用GAN进行图像生成。
|
8天前
|
数据挖掘 计算机视觉 Python
SciPy图像处理技巧:图像增强与特征提取
【4月更文挑战第17天】本文介绍了如何使用SciPy进行图像增强和特征提取。通过调整亮度、对比度和伽马校正实现图像增强,示例代码展示了相关操作。同时,利用Sobel算子进行边缘检测和Laplacian of Gaussian (LoG) 进行角点检测,以提取图像特征。虽然SciPy不是专业的图像处理库,但其数值计算能力在图像分析中仍有一定价值,可与其他图像处理库结合使用。
|
12天前
|
计算机视觉 Python
如何利用Python实现简单的图像处理功能
本文介绍了如何使用Python编程语言和相关库实现简单的图像处理功能。通过学习本文,读者将了解如何读取图像文件、调整图像大小、修改图像亮度和对比度、应用滤镜效果以及保存处理后的图像。这些技术将帮助读者快速入门图像处理领域,并为他们进一步探索更高级的图像处理技术打下基础。
|
1月前
|
机器学习/深度学习 人工智能 算法
用于图像处理的Python顶级库 !!
用于图像处理的Python顶级库 !!
24 1
|
1月前
|
算法 数据可视化 计算机视觉
使用Python实现图像处理中的边缘检测算法
图像处理中的边缘检测是计算机视觉和图像识别领域的重要技术之一。本文将介绍如何利用Python语言实现常见的边缘检测算法,包括Sobel、Canny等,并结合实例演示其在图像处理中的应用。
|
1月前
|
计算机视觉
OpenCV(三十四):轮廓外接最大、最小矩形和多边形拟合
OpenCV(三十四):轮廓外接最大、最小矩形和多边形拟合
75 0