【问题标题】:How to detect contours touching the border?如何检测接触边界的轮廓?
【发布时间】:2020-05-24 20:15:17
【问题描述】:

我正在编写一个程序,该程序可以使用 Python 和 OpenCV 检测 3D 打印机粉床中的不一致。到目前为止,我所做的是使用边缘检测创建蒙版图像,然后再次执行边缘检测并排除任何接触边界的轮廓。这很好用,但是我也想检测接触边界的轮廓。我尝试了各种方法,但似乎没有达到我想要的结果。 This article 似乎和我有同样的问题并提供了答案,但它是用 C++ 编码的,我不完全理解。

例如,这是一个轮廓与边框接触的图像:image

这是执行边缘检测后的图像:image。如您所见,图像的边界包含在我要检测的轮廓中。请注意,边框并不总是正方形,而是可以是任何多边形。

【问题讨论】:

    标签: python opencv


    【解决方案1】:

    这是在 Python/OpenCV 中执行此操作的一种方法。

    • 读取输入
    • 转换为灰色
    • 阈值
    • 获取白色像素的边界
    • 裁剪输入到这些边界以移除黑色边框
    • 对裁剪后的图像设置阈值以隔离较亮的区域
    • 应用形态来清理它
    • 获取轮廓及其边界框
    • 测试边界框是否接触到裁剪图像的 4 个边中的任何一个
    • 在输入图像上绘制轮廓边界框
    • 保存结果


    输入:

    import cv2
    import numpy as np
    
    # load image as grayscale
    img = cv2.imread('streak.png')
    
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # threshold 
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
    
    # get bounds of white pixels
    white = np.where(thresh==255)
    xmin, ymin, xmax, ymax = np.min(white[1]), np.min(white[0]), np.max(white[1]), np.max(white[0])
    print(xmin,xmax,ymin,ymax)
    
    # crop the gray image at the bounds
    crop = gray[ymin:ymax, xmin:xmax]
    hh, ww = crop.shape
    
    # do adaptive thresholding
    thresh2 = cv2.adaptiveThreshold(crop, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, 1.1)
    
    # apply morphology
    kernel = np.ones((1,7), np.uint8)
    morph = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel)
    kernel = np.ones((5,5), np.uint8)
    morph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel)
    
    # invert
    morph = 255 - morph
    
    # get contours (presumably just one) and its bounding box
    contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    for cntr in contours:
        x,y,w,h = cv2.boundingRect(cntr)
    
    # draw bounding box on input
    bbox = img.copy()
    cv2.rectangle(bbox, (x+xmin, y+ymin), (x+xmin+w, y+ymin+h), (0,0,255), 1)
    
    # test if contour touches sides of image
    if x == 0 or y == 0 or x+w == ww or y+h == hh:
        print('region touches the sides')
    else:
        print('region does not touch the sides')
    
    # save resulting masked image
    cv2.imwrite('streak_thresh.png', thresh)
    cv2.imwrite('streak_crop.png', crop)
    cv2.imwrite('streak_bbox.png', bbox)
    
    # display result
    cv2.imshow("thresh", thresh)
    cv2.imshow("crop", crop)
    cv2.imshow("thresh2", thresh2)
    cv2.imshow("morph", morph)
    cv2.imshow("bbox", bbox)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    


    找到边界的阈值图像:

    裁剪输入:

    形态清洁第二阈值:

    输入上区域轮廓的边界框:

    消息打印:

    region touches the sides
    


    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-23
      • 1970-01-01
      • 1970-01-01
      • 2020-06-17
      • 1970-01-01
      • 2020-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多