python - 如何使用 OpenCV 获得金属光泽物体的轮廓

标签 python image opencv image-processing computer-vision

我试图找到金属光泽物体的轮廓,如下图所示:

enter image description here

我使用 OpenCV 的 Canny 来获取图像的轮廓;但是,结果(下图)确实绘制了原始图像的完整轮廓。它在右下角有一个很大的突破。

enter image description here

我恳请任何类型的资源可以帮助我完善我的轮廓,使其连续并且(非常接近)与原始图像的形状相似。

最佳答案

在 Python/OpenCV 中,您可以通过以下方式实现:

  • 读取输入
  • 转换为 HSV 颜色空间并提取饱和度 channel (因为灰色没有饱和度,而绿色有)
  • 模糊图像以减轻噪音
  • 阈值
  • 应用形态学填充 Shiny 物体的内部孔
  • 找到轮廓并过滤最大的(尽管应该只有一个)
  • 在输入图像上绘制轮廓
  • 保存结果

  • 输入:

    enter image description here
    import cv2
    import numpy as np
    
    # read input
    img = cv2.imread('shiny.jpg')
    
    # convert to hsv and get saturation channel
    sat = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)[:,:,1]
    
    # do a little Gaussian filtering
    blur = cv2.GaussianBlur(sat, (3,3), 0)
    
    
    # threshold and invert to create initial mask
    mask = 255 - cv2.threshold(blur, 100, 255, cv2.THRESH_BINARY)[1]
    
    # apply morphology close to fill interior regions in mask
    kernel = np.ones((15,15), np.uint8)
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
    
    
    # get outer contours from inverted mask and get the largest (presumably only one due to morphology filtering)
    cntrs = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
    result = img.copy()
    area_thresh = 0
    for c in cntrs:
        area = cv2.contourArea(c)
        if area > area_thresh:
            area = area_thresh
            big_contour = c
    
    # draw largest contour
    cv2.drawContours(result, [big_contour], -1, (0,0,255), 2)
    
    
    # write result to disk
    cv2.imwrite("shiny_mask.png", mask)
    cv2.imwrite("shiny_outline.png", result)
    
    # display it
    cv2.imshow("IMAGE", img)
    cv2.imshow("MASK", mask)
    cv2.imshow("RESULT", result)
    cv2.waitKey(0)
    

    阈值和过滤蒙版:

    enter image description here

    结果:

    enter image description here

    另一种方法是在绿色上使用 cv2.inRange() 来设置阈值。

    关于python - 如何使用 OpenCV 获得金属光泽物体的轮廓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60198096/

    相关文章:

    javascript - Node.js 服务器不显示图像

    c++ - 高斯平滑输出未对齐

    python - 使用opencv使用fourcc编解码器h264和h265从帧中保存视频

    python - 如何捕获 pyqt closeEvent 并最小化对话框而不是退出?

    python - Perfplot bench() raises "TypeError: ufunc ' isfinite' not supported for the input types, and the input types"

    c++ - 提取图像中的激光线(使用 OpenCV)

    javascript - extjs - 如何通过响应的一部分设置 Ext.Img 的数据?

    python - 检索 pandas 中 MultiIndex 的一级值

    Python 网络抓取请求遵循重定向

    python-2.7 - openCV imwrite 写入 0 kb 图像帧