【问题标题】:OpenCV: Remove background noise and increase signal strengthOpenCV:去除背景噪音并增加信号强度
【发布时间】:2020-10-28 18:04:22
【问题描述】:

我是 OpenCV 新手,尝试了多种方法,但仍有一些问题。 我有这样的图片:

在中心有一个集群(很难看到)。我想找到那些集群并计算它们。我为此使用了cv2.findContours,这对于这些集群具有良好亮度且背景噪声不太强的图像已经非常有效。

对于这样的图像,集群非常暗或背景噪声非常强并且看起来与实际集群非常相似的图像,我无法检测到它们。

所以我现在想做的是去除背景噪音,这样就只剩下集群了。然后我可以增加图像的亮度,并且(我认为)应该更容易识别这些集群。

背景噪音会很大!上图是一个样本,没有太多的背景噪音,但可能会更糟。 我有我知道的图像,其中没有簇(阴性对照)。里面的一切都只是背景噪音。所以我的想法是在这个阴性对照中找到主色:

from skimage import io
def getDominantColor(image):
        a = io.imread(image)[:, :, :-1]
    
        colors, count = np.unique(a.reshape(-1, a.shape[-1]), axis=0, return_counts=True)
        return colors[count.argmax()]

主色应该是背景噪音。 然后从有簇的图像中减去这个主色:

def substract(image, dominant):
    cells = cv2.imread(image)
    cells = cells[:, :, 2]
    cells = cv2.subtract(cells, dominant)

虽然这段代码不起作用...... :) 但除此之外,我想知道你们是否认为这是解决这类问题的正确方向?

简而言之,我想去除背景噪音,这样只有我感兴趣的信息才会保留在图像中。 背景噪音会很大,而且我有一些图像,我知道那里只有背景噪音,没有别的。

非常感谢您能给我的任何提示! 最好的祝福, 马丁

【问题讨论】:

    标签: python opencv image-processing


    【解决方案1】:

    这是 Python/OpenCV/Skimage 中的一种方法

     - Read the input
     - Stretch to full dynamic range
     - Apply morphology to clean the image
     - Convert to gray
     - Otsu threshold
     - Get the largest contour
     - Draw the contour outline on the stretched image
     - Extract the contour region from the stretched image and place it on a black background
     - Save the results
    

    输入:

    import cv2
    import numpy as np
    import skimage.exposure
    
    
    # read image
    img = cv2.imread('dark_image.png')
    hh, ww = img.shape[:2]
    
    # stretch dynamic range
    stretch = skimage.exposure.rescale_intensity(img, in_range='image', out_range=(0,255))
    
    # apply morphology
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (101,101))
    morph = cv2.morphologyEx(stretch, cv2.MORPH_CLOSE, kernel)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
    morph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel)
    
    # convert to grayscale
    gray = cv2.cvtColor(morph,cv2.COLOR_BGR2GRAY)
    
    # threshold
    #thresh = cv2.threshold(gray, 30, 255, cv2.THRESH_BINARY)[1]\
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
    
    # get largest contour
    contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    big_contour = max(contours, key=cv2.contourArea)
    
    # draw contour on stretched image
    result1 = stretch.copy()
    cv2.drawContours(result1, [big_contour], 0, (255,255,255), 1)
    
    # draw region on black background
    contour = np.zeros((stretch.shape[:2]), dtype=np.uint8)
    result2 = np.zeros_like(stretch)
    cv2.drawContours(contour, [big_contour], 0, 255, -1)
    result2[contour > 0] = stretch[contour > 0]
    
    # save result
    cv2.imwrite("dark_image_stretch.jpg", stretch)
    cv2.imwrite("dark_image_morph.jpg", morph)
    cv2.imwrite("dark_image_gray.jpg", gray)
    cv2.imwrite("dark_image_threshold.jpg", thresh)
    cv2.imwrite("dark_image_result1.jpg", result1)
    cv2.imwrite("dark_image_result2.jpg", result2)
    
    # view result
    cv2.imshow("stretch", stretch)
    cv2.imshow("morph", morph)
    cv2.imshow("gray", gray)
    cv2.imshow("threshold", thresh)
    cv2.imshow("result1", result1)
    cv2.imshow("result2", result2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    拉伸到全动态范围图像:

    形态清洁图像:

    灰色图像:

    阈值图像:

    拉伸图像上的轮廓轮廓:

    黑色背景上拉伸图像的轮廓区域:

    【讨论】:

    • 谢谢!这看起来很有趣。我只是在尝试,但出现以下错误:gray = cv2.cvtColor(morph, cv2.COLOR_BGR2GRAY) ... > 输入图像的不支持深度:> 'VDepth::contains(depth)' > where > 'depth ' 是 6 (CV_64F) 你知道问题出在哪里吗?我也试过 COLOR_BGRA2GRAY,同样的错误
    • 可能是 OpenCV 版本问题。它适用于我的 OpenCV 3.8 和 Python 3.7。你用的是什么版本?输入图像的 dtype 是什么? print(img.dtype)。作为猜测,请尝试cv2.cvtColor(morph.astype(np.uint8), cv2.COLOR_BGR2GRAY) 或 enCV 版本问题。它适用于我的 OpenCV 3.8 和 Python 3.7。试试cv2.cvtColor((255*morph).astype(np.uint8), cv2.COLOR_BGR2GRAY)
    • +1。你能解释一下形态部分吗?我最近在做类似的事情,除了有点原始的模糊之外,我想不出别的东西。我的意思是你为什么选择做你所做的事情等等。
    • 形态关闭将更好地合并您的中心绿色,打开将删除小的浅绿色点。如果您在关闭后放置 imshow ,您可以看到效果。对于去除小物体,形态通常比模糊更有效。收盘是一个扩张,然后是一个侵蚀。打开是一个腐蚀,然后是一个扩张。
    • @fmw42 我现在玩了一点(你的修复建议奏效了),但这确实需要很长时间。上面这只是一个示例图像。原始的是 9000x9000 像素。计算需要几分钟......这对我的用例来说太长了。您可能有其他想法吗?您如何看待使用直方图,找到最主要的颜色,然后删除这个颜色。然后我会增加剩余颜色的强度。也许这不会像您的方法那样精确,但在我的情况下也不需要 100% 的正确性。
    【解决方案2】:

    这是我之前在 Python/OpenCV 中的解决方案的另一个变体。

     - Read the input
     - Stretch to full dynamic range
     - Convert to gray
     - Threshold
     - Blur
     - Threshold again
     - Get the largest contour
     - Draw the contour outline on the stretched image
     - Extract the contour region from the stretched image and place it on a black background
     - Save the results
    

    输入:

    • 读取输入
    • 拉伸到全动态范围
    • 应用形态学清洁图像
    • 转换为灰色
    • 大津阈值
    • 获取最大轮廓
    • 在拉伸后的图像上绘制轮廓轮廓
    • 从拉伸后的图像中提取轮廓区域并将其放置在黑色背景上
    • 保存结果

    拉伸图像:

    灰色图像:

    最终阈值图像:

    结果 1:

    结果 2:

    【讨论】:

      猜你喜欢
      • 2018-07-15
      • 2020-05-03
      • 1970-01-01
      • 2012-04-27
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      相关资源
      最近更新 更多