weixin_46782903 2022-02-14 21:55 采纳率: 100%
浏览 96
已结题

如何用Python+opencv检测此图像中的所有圆?

我用了cv.HoughCircles函数,但不会选择合适的参数,效果不好。
原图:

img


结果:

img

{

```

```import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

def show(img):
if img.ndim == 2:
plt.imshow(img,cmap='gray')
else:
plt.imshow(cv.cvtColor(img,cv.COLOR_BGR2RGB))
plt.show()

img=cv.imread('C:/Users/1/Desktop/img/test.jpg')
gray=cv.cvtColor(img, cv.COLOR_BGR2GRAY)

dst = cv.equalizeHist(gray)#应用直方图均衡化
gaussian = cv.GaussianBlur(dst,(9,9),0)
#利用Canny进行边缘检测
GrayImage = cv.Canny(gaussian, 20,180, apertureSize=3)
ret, th1 = cv.threshold(GrayImage, 127, 255, cv.THRESH_TOZERO) # 固定阈值二值化
th2 = cv.adaptiveThreshold(th1, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 3, 5)
th3 = cv.adaptiveThreshold(th2, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 3, 5)
kernel = np.ones((6, 9), np.uint8)
erosion = cv.erode(th3, kernel, iterations=1) # 腐蚀处理
dilation = cv.dilate(erosion, kernel, iterations=1) # 膨胀处理
imgray = cv.Canny(erosion, 3, 8) # Canny算子边缘检测

circles = cv.HoughCircles(imgray, cv.HOUGH_GRADIENT, 1, 40, param1=100, param2=6, minRadius=8,maxRadius=10)

circles = np.uint16(np.around(circles))
P = circles[0] # 去掉circles数组一层外括号
for i in P:
cv.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 5)
cv.circle(img, (i[0], i[1]), 5, (0, 0, 255), 3)

show(img)
}

我参考了一些博主的文章,链接:https://blog.csdn.net/SouthWooden/article/details/98741985

  • 写回答

3条回答 默认 最新

  • 默凉 2022-02-15 10:41
    关注

    废话不多说,直接上代码

    img

    import cv2
    import numpy as np
    
    
    def cv_show(neme, img):
        cv2.imshow(neme, img)  
        cv2.waitKey(0)  
        cv2.destroyAllWindows()  
    
    
    image = cv2.imread('1.jpg')
    img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # Canny 边缘检测(图像、min值、max值)
    edges = cv2.Canny(img, 7, 12)
    ret, thresh1 = cv2.threshold(edges, 127, 255, cv2.THRESH_BINARY)
    
    # 膨胀操作
    kernel1 = np.ones((5, 5), np.uint8)
    # 换个封装函数,膨胀      当前载入 腐蚀后--膨胀
    erosion = cv2.dilate(thresh1, kernel1, iterations=1)
    
    kernel = np.ones((3, 3))
    # 腐蚀操作
    sb = cv2.erode(erosion, kernel, iterations=1)
    
    cv_show("s", thresh1)
    cv_show("name", erosion)
    cv_show('sda', sb)
    
    # 轮廓查询
    contours, hierarchy = cv2.findContours(sb, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    
    for i in range(len(contours)):
        # 轮廓外接圆
        (x, y), radius = cv2.minEnclosingCircle(contours[i])
        center = (int(x), int(y))
        radius = int(radius)
    
        # 轮廓区域
        # 轮廓面积
        area = cv2.contourArea(contours[i])
        if 300 <= area < 2000:
            image = cv2.circle(image, center, radius, (0, 0, 255), 1)
    
    cv_show('sad', image)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • ilmss 2022-02-15 09:31
    关注

    可以检测圆,后边有说明。

    import cv2
    import numpy as np
    
    
    __author__ = "boboa"
    
    
    def detect_circles_demo(image):
        dst = cv2.pyrMeanShiftFiltering(image, 10, 100)  # 均值偏移滤波
        cimage = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
        circles = cv2.HoughCircles(cimage, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=40, minRadius=0, maxRadius=0)
        # 整数化,#把circles包含的圆心和半径的值变成整数
        circles = np.uint16(np.around(circles))
        for i in circles[0, :]:
            # 画出外边圆
            cv2.circle(image, (i[0], i[1]), i[2], (0, 255, 0), 2)
            # 画出圆心
            cv2.circle(image, (i[0], i[1]), 2, (0, 0, 255), 3)
        cv2.imshow("circles", image)
    
    
    if __name__ == "__main__":
        img = cv2.imread("image/circles.jpg")
        cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
        cv2.imshow("input image", img)
        detect_circles_demo(img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    

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

    参数:
      image:输入图像,必须是灰度图像
      method:检测方法,常用CV_HOUGH_GRADIENT
      dp:检测内侧圆心的累加器图像的分辨率于输入图像之比的倒数,如dp=1,累加器和输入图像具有相同的分辨率,如果dp=2,累计器便有输入图像一半那么大的宽度和高度
      minDist: 两个圆心之间的最小距离
      param1: 是method方法的参数,在CV_HOUGH_GRADIENT表示传入canny边缘检测的阈值
      param2:对当前唯一的方法霍夫梯度法cv2.HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值
    它越小,就越可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了
    minRadius:默认值0,圆半径的最小值

      maxRadius:默认值0,圆半径的最大值

    cv2.circle是画圆函数(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img

    参数:img:源图像

       center:圆心坐标

       radius:圆的半径

       color:设定圆的颜色

       thickness:如果是正数,表示圆轮廓的粗细程度。如果是负数,表示要绘制实心圆

       lineType:圆线条的类型

       shift:圆心坐标和半径值中的小数位数

    评论
  • youcans_ 人工智能领域优质创作者 2022-02-15 09:23
    关注

    图像中的圆直径基本一致,比较好处理。
    (1)检查一下 固定阈值二值化 的参数"127"是否合适,在该语句后显示一下二值化图像即可;
    (2)主要是 HoughCircles 中的最大、最小半径 minRadius、maxRadius 参数设置是否合适
    从运行结果来看设置的小了,可以适当增大,保证要找的圆的半径值在 minRadius、maxRadius 之间。

    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 2月16日
  • 已采纳回答 2月15日
  • 修改了问题 2月15日
  • 赞助了问题酬金5元 2月14日
  • 展开全部

悬赏问题

  • ¥15 Tpad api账户 api口令
  • ¥30 ppt进度条制作,vba语言
  • ¥15 stc12c5a60s2单片机测光敏ADC
  • ¥15 生信simpleaffy包下载
  • ¥15 请教一下simulink中S函数相关问题
  • ¥15 在二层网络中,掩码存在包含关系即可通信
  • ¥15 端口转发器解析失败不知道电脑设置了啥
  • ¥15 Latex算法流程图行号自定义
  • ¥15 关于#python#的问题:我在自己的电脑上运行起来总是报错,希望能给我一个详细的教程,(开发工具-github)
  • ¥40 基于51单片机实现球赛计分器功能