【问题标题】:Detect white background on images using python使用python检测图像上的白色背景
【发布时间】:2016-05-02 12:09:09
【问题描述】:

有没有办法使用 python 判断图像是否为白色背景,以及什么可能是获得关于这个问题的“置信度百分比”的好策略?似乎互联网上的文献并没有完全涵盖这种情况,我找不到任何严格相关的内容。

我要分析的图片是典型的电子商务网站产品图片,因此它们应该在中间有一个焦点对象,并且只在边框处有白色背景。

另一个可用的信息是对象应占据的图像空间的最大百分比。

【问题讨论】:

  • 使用 OpenCV 进行任何图像处理!
  • @linusg 你知道使用 OpenCV 的特定策略吗?
  • 看看pyimagesearch.com 的好东西。只要搜索它,你就会发现某事。那是我深入研究 OpenCV 的地方。

标签: python image-processing color-detection


【解决方案1】:

我会选择这样的。

  1. 通过将最亮、最白的像素设置为 240 而不是 255 来降低图像的对比度,这样通常在图像和产品部分中发现的白色不再是纯白色。

  2. 在您的图像周围放置一个 1 像素宽的白色边框 - 这将允许下一步中的泛洪填充“流动” 一直围绕边缘(即使 “产品” 触及框架的边缘)并“渗入” 从所有边框/边缘进入图像。

  3. 从左上角开始填充图像(在第 2 步之后必须是纯白色),并在匹配白色时允许 10-20% 的容差,以防背景为灰白色或轻微阴影,白色会从边缘流入您的图像,直到到达中心的产品。

  4. 看看你现在有多少纯白色像素 - 这些是背景像素。纯白色像素的百分比可以让您确定图像是白色背景上的产品。

我会像这样从命令行使用 ImageMagick:

convert product.jpg +level 5% -bordercolor white -border 1 \
  -fill white -fuzz 25% -draw "color 0,0 floodfill" result.jpg

我将在以下 2 张图片周围设置一个红色边框,以便您可以看到 StackOverflow 的白色背景上的边缘,并显示之前和之后的图像 - 查看生成的图像中的白色量(没有第二个,因为它没有白色背景)并且在路由器下方的阴影处查看-fuzz的效果。

之前

之后

如果您希望将其作为百分比,您可以将所有非白色像素设为黑色,然后计算白色像素的百分比,如下所示:

convert product.jpg -level 5%                                      \
   -bordercolor white -border 1                                    \
   -fill white -fuzz 25% -draw "color 0,0 floodfill" -shave 1      \
   -fuzz 0 -fill black +opaque white -format "%[fx:int(mean*100)]" info:
62

之前

之后

ImageMagick 具有 Python 绑定,因此您可以在 Python 中执行上述操作 - 或者您可以使用 OpenCV 和 Python 来实现相同的算法。

【讨论】:

  • 我会试试这个。谢谢。
【解决方案2】:

最流行的图像格式是 .png。 PNG 图像可以具有透明颜色 (alpha)。常与白色背景页面相匹配。使用pillow 很容易找出哪些像素是透明的。

一个好的起点:

from PIL import Image

img = Image.open('image.png')
img = img.convert("RGBA")

pixdata = img.load()

for y in xrange(img.size[1]):
    for x in xrange(img.size[0]):
        pixel = pixdata[x, y]
        if pixel[3] == 255:
           # tranparent....

或者如果你检查左上角的像素是否为白色就足够了:

pixel = pixdata[0, 0]
if item[0] == 255 and item[1] == 255 and item[2] == 255:
   # it's white

【讨论】:

  • 这是我无法做出的假设。我需要假设使用 jpeg 或一般情况下具有纯色背景的图像。
【解决方案3】:

这个问题可能是几年前的问题,但我最近有一个类似的任务。在这里分享我的答案可能会帮助其他遇到相同任务的人,我还可以通过让社区查看来改进我的答案。

import cv2 as cv
import numpy as np

THRESHOLD_INTENSITY = 230

def has_white_background(img):
    # Read image into org_img variable
    org_img = cv.imread(img, cv.IMREAD_GRAYSCALE)
    # cv.imshow('Original Image', org_img)

    # Create a black blank image for the mask
    mask = np.zeros_like(org_img)

    # Create a thresholded image, I set my threshold to 200 as this is the value 
    # I found most effective in identifying light colored object
    _, thres_img = cv.threshold(org_img, 200, 255, cv.THRESH_BINARY_INV)

    # Find the most significant contours
    contours, hierarchy = cv.findContours(thres_img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
    # Get the outermost contours
    outer_contours_img = max(contours, key=cv.contourArea)

    # Get the bounding rectangle of the contours
    x,y,w,h = cv.boundingRect(outer_contours_img)
    # Draw a rectangle base on the bounding rectangle of the contours to our mask
    cv.rectangle(mask,(x,y),(x+w,y+h),(255,255,255),-1)
    # Invert the mask so that we create a hole for the detected object in our mask
    mask = cv.bitwise_not(mask)

    # Apply mask to the original image to subtract it and retain only the bg
    img_bg = cv.bitwise_and(org_img, org_img, mask=mask)

    # If the size of the mask is similar to the size of the image then the bg is not white
    if h == org_img.shape[0] and w == org_img.shape[1]:
        return False

    # Create a np array of the 
    np_array = np.array(img_bg)

    # Remove the zeroes from the "remaining bg image" so that we dont consider the black part,
    # and find the average intensity of the remaining pixels
    ave_intensity = np_array[np.nonzero(np_array)].mean()

    if ave_intensity > THRESHOLD_INTENSITY:
        return True
    else:
        return False

这些是上面代码中步骤的图像:

这是原始图像。无侵犯版权之意。 (无法从unsplash找到实际图像的url)

第一步是将图像转换为灰度。

对图像应用阈值。

获取“阈值”图像的轮廓并获取轮廓。绘制轮廓只是可选的。

从轮廓中,获取外轮廓的值并找到它的边界矩形。可以选择将矩形绘制到图像上,以便您查看假设的阈值是否适合矩形中的对象。

在边界矩形之外创建一个遮罩。

最后,将蒙版减去灰度图像。剩下的是背景图像减去蒙版。

要最后判断背景是否为白色,求除图像数组的0值之外的背景图像的平均强度值。并根据一定的阈值,判断是否为白色。

希望这会有所帮助。如果您认为它仍然可以改进,或者我的解决方案存在缺陷,请在下方评论。

【讨论】:

    猜你喜欢
    • 2015-08-16
    • 2018-09-30
    • 2015-03-17
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 1970-01-01
    相关资源
    最近更新 更多