【问题标题】:How to determine whether object is embossed or debossed using OpenCV?如何使用 OpenCV 确定对象是压花还是压花?
【发布时间】:2019-09-24 18:54:21
【问题描述】:

假设我有像这样的浮雕和凹凸物体的图像

有没有办法确定上面的物体是浮雕的,而下面的物体是使用 OpenCV 凹陷的?最好使用 C++,但 Python 也可以。我在互联网上找不到任何好的资源。

【问题讨论】:

    标签: python c++ opencv image-processing computer-vision


    【解决方案1】:

    这是一种利用浮雕/凹陷图像的凹陷和凸起轮廓的方法。主要思想是:

    • 将图像转换为灰度
    • 执行形态转换
    • 使用 Canny 边缘检测查找轮廓
    • 扩张 canny 图像以将单个轮廓合并为单个轮廓
    • 执行轮廓检测以查找上半部分/下半部分的 ROI 尺寸
    • 获取顶部/底部 canny 图像的 ROI
    • 计算每一半的非零数组元素

    转为灰度并进行形态变换

    执行精明的边缘检测以查找轮廓。确定一个物体是否被压花/凹陷的关键是比较精巧的边缘。方法如下:我们查看对象,如果它的上半部比下半部有更多的轮廓/线条/像素,那么它就是凹陷的。同样,如果上半部分的像素比下半部分少,那么它就是浮雕的。

    现在我们有了精巧的边缘,我们调整图像直到所有轮廓都连接起来,这样我们就得到了一个对象。

    然后我们进行轮廓检测以获得对象的 ROI

    从这里开始,我们将每个对象分为顶部和底部部分

    现在我们有了顶部和底部的 ROI,我们在 Canny 图像中裁剪 ROI

    对于每一半,我们使用cv2.countNonZero() 计算非零数组元素。对于浮雕对象,我们得到这个

    ('top', 1085)
    ('bottom', 1899)
    

    对于凹陷的物体,我们得到这个

    ('top', 979)
    ('bottom', 468)
    

    因此,通过比较两半之间的值,如果上半部的像素比下半部少,则为浮雕。如果它有更多,它是凹陷的

    import numpy as np
    import cv2
    
    original_image = cv2.imread("1.jpg")
    image = original_image.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
    morph = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
    canny = cv2.Canny(morph, 130, 255, 1)
    
    # Dilate canny image so contours connect and form a single contour
    dilate = cv2.dilate(canny, kernel, iterations=4)
    
    cv2.imshow("morph", morph)
    cv2.imshow("canny", canny)
    cv2.imshow("dilate", dilate)
    
    # Find contours in the image
    cnts = cv2.findContours(dilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    
    contours = []
    # For each image separate it into top/bottom halfs
    for c in cnts:
        # Obtain bounding rectangle for each contour
        x,y,w,h = cv2.boundingRect(c)
    
        # Draw bounding box rectangle
        cv2.rectangle(original_image,(x,y),(x+w,y+h),(0,255,0),3)
        # cv2.rectangle(original_image,(x,y),(x+w,y+h/2),(0,255,0),3) # top 
        # cv2.rectangle(original_image,(x,y+h/2),(x+w,y+h),(0,255,0),3) # bottom
        top_half = ((x,y), (x+w, y+h/2))
        bottom_half = ((x,y+h/2), (x+w, y+h))
    
        # Collect top/bottom ROIs
        contours.append((top_half, bottom_half))
    
    for index, c in enumerate(contours):
        top_half, bottom_half = c
    
        top_x1,top_y1 = top_half[0]
        top_x2,top_y2 = top_half[1]
        bottom_x1,bottom_y1 = bottom_half[0]
        bottom_x2,bottom_y2 = bottom_half[1]
    
        # Grab ROI of top/bottom section from canny image
        top_image = canny[top_y1:top_y2, top_x1:top_x2]
        bottom_image = canny[bottom_y1:bottom_y2, bottom_x1:bottom_x2]
    
        cv2.imshow('top_image', top_image)
        cv2.imshow('bottom_image', bottom_image)
    
        # Count non-zero array elements
        top_pixels = cv2.countNonZero(top_image)
        bottom_pixels = cv2.countNonZero(bottom_image)
    
        print('top', top_pixels)
        print('bottom', bottom_pixels)
    
    cv2.imshow("detected", original_image) 
    print('contours detected: {}'.format(len(contours)))
    cv2.waitKey(0)
    

    【讨论】:

    • 很详细的解释!感谢您提醒我使用cv2.countNonZero()
    【解决方案2】:

    您可以使用的一个见解是,浮雕物体通常比凹陷物体更亮。

    我可能会进行边缘检测以找到应该形成封闭多边形的“boss-edges”,并比较封闭“bossment”的相对亮度值。必须特别小心有孔的物体,例如:字母O,但它是可行的。

    如果您知道撞击凸台的光线方向,您可能可以进行更复杂的处理。例如如果你知道光线来自左上角,你可以试着只关注左上角的边缘像素

    【讨论】:

    • 你如何比较封闭的“凸台”的相对亮度值?
    • 可以转换成HSV colorspace比较V值
    猜你喜欢
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 2022-01-15
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多