OpenCV学习Day09霍夫圆检测、轮廓提取

霍夫圆检测代码:

#-*- coding: UTF-8 -*-
'''
 实现PEPB快速排版:ctl+alt+l

霍夫圆变换原理:
            1、从平面到极坐标转换三个参数C(x0,y0,r)其中x0,y0是圆心;
            2、假设平面坐标的任意一个圆上的点,转换到极坐标中,C(x0,y0,r)处有最大值,该点为圆心,反推其半径,检测为圆
            (在一个圆上C,选任意个点,以这些点作为圆心绘制圆,这些圆会交于一点,该点为圆C的圆心)
霍夫圆检测对噪声敏感,所以先对图像做中值滤波
基于效率,OpenCV中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:
    1、检测边缘,发现可能的圆心
    2、基于第一步的基础上从候选圆心开始计算最佳半径大小
'''
import cv2 as cv
import numpy as np


def detectCircleDemo(image):
    dst = cv.pyrMeanShiftFiltering(image,2,110 )  # 因为霍夫圆检测最噪声敏感,故因通过边缘滤波去噪
    #sigmaSpace:尽量取小,那么“和”就小一点,主要的差异就保留下来;sigmaColor:尽量取大,目的将小的差异模糊掉,噪声去掉

    cimage = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)  # 转为灰度图像
    circles = cv.HoughCircles(cimage, cv.HOUGH_GRADIENT, 1, 90, param1=100, param2=20, minRadius=0, maxRadius=60)
    '''
    第二个参数默认,因为检测圆的方法,OpenCV2.*.*版本之中只有霍夫梯度法
    第三个参数可以设置为1就行--默认参数,步长
    第四个参数:非常重要!!是圆心与圆心之间的距离,这是一个经验值。这个大了,那么多个圆就是被认为一个圆
    第五个参数 就设为默认值就OK
    第六个参数是根据你的图像中的圆大小设置,当这张图片中的圆越小,那么此值就设置应该被设置越小。当设置的越小,那么检测出的圆越多,在检测较大的圆时则会产生很多噪声。所以要根据检测圆的大小变化。
    第七个和第八个参数 是你检测圆 最小半径和最大半径是多少。这个值也是为了进一步筛选检测出的圆
    '''
    circles = np.uint16(np.around(circles))#转化为整数
    for i in circles[0, :]:
        cv.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)#画圆:中心点位置;半径;颜色;宽度
        cv.circle(image, (i[0], i[1]), 2, (0, 0, 255), 2)#画圆心:实质是一个小圆,此处设为一个半径为2个像素的小圆
    cv.imshow("circles", image)


src = cv.imread("E:\OpenCVTests/timg (3).jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
detectCircleDemo(src)

cv.waitKey(0)
cv.destroyAllWindows()

运行结果:为使圆检测结果准确,需要根据不同的图像调整各个API的参数在这里插入图片描述在这里插入图片描述
轮廓提取代码:

# -*- coding: UTF-8 -*-
import cv2 as cv
import numpy as np


# 轮廓查找
def edgeDemo(image):
    blurred = cv.GaussianBlur(image, (3, 3), 0)  # 降低噪声,因为Canny对噪声敏感
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
    # 梯度值计算
    xgrad = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
    ygrad = cv.Sobel(gray, cv.CV_16SC1, 0, 1)  # 第三个参数为处理图像的深度,此处应该用整数型
    # edgeOutPut=cv.Canny(gray,50,150)-----亦可使用本方法
    edgeOutPut = cv.Canny(xgrad, ygrad, 50, 150)
    return edgeOutPut


def contoursDemo(image):
    dst = cv.GaussianBlur(image, (3, 3),0)  # 高斯模糊,去噪点
    gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)  # 二值化
    cv.imshow("binaryImage", binary)
    #binary = edgeDemo(image)
    contous, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    #函数cv2.findContours()有三个参数。第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。
    #而返回值根据OpenCV版本不同也不一样,但这俩个版本都会返回一个元组。OpenCV2.x版本第一个元素是轮廓,而在OpenCV3.x中第二个才是轮廓。这个轮廓是一个列表,每个列表元素代表着一个轮廓。
    #本代码段使用的是OpenCV2.x版本
    for i, contou in enumerate(contous):  # 容器循环
        cv.drawContours(image, contous, i, (0, 0, 255), 2)  # 最后一个参数为-1时,填充
            #第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成,
            #第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,
            #第四个参数color为轮廓的颜色
            #第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部
        print(i)
    cv.imshow("detectContour", image)


src = cv.imread("E://OpenCVTests//timg (3).jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
contoursDemo(src)

cv.waitKey(0)
cv.destroyAllWindows()


运行结果:依次为原图、二值化图、查找轮廓结果
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值