我正在构建一个Web应用程序,该应用程序需要从具有白色背景的图像(或至少从与之形成对比的背景)“检测”服装。
我具有以下功能,该功能应该将图像中的所有像素替换为白色像素,这些像素的RGB值与图像中心的像素相差70%以上。
def crop(self, image_data):
'''"Crops" image by changing all RGB values to [255, 255, 255] if they differ more than
70% from the pixel in the center of the image.
'''
image_data.setflags(write=1)
height, width, channels = image_data.shape
new_image_data = np.full((height, width, 3), 255)
middle_pixel = image_data[(height // 2), (width // 2)]
middle_pixel_avg = np.mean(middle_pixel)
difference_limit = middle_pixel_avg * 0.7
for row in range(height):
for col in range(width):
pixel_avg = np.mean(image_data[row, col])
if (abs(middle_pixel_avg - pixel_avg) <= difference_limit):
new_image_data[row, col] = image_data[row, col]
return new_image_data
效率极低,大约需要30秒才能运行在iPhone上拍摄的常规图像。这也是可怕的,似乎是检测图像背景的完全错误的方法。
首先,我想知道如何使我的这项功能更有效。其次,我想知道是否有更好,更可靠的方法?
答案 0 :(得分:1)
我认为您可以将OpenCV用于功能的大部分部分。例如,一旦在中心的3x3区域中对强度进行了采样(一个像素可能不足以代表织物的“平均”强度),则可以使用此结果对图像的灰度版本进行阈值处理使用cv2.threshold()函数,该函数可以使python循环更快。最终,您可以使用此蒙版提取前景。
以下是这种实现的框架:
import cv2
import numpy as np
def remove_background(image):
"""
Remove the light background from an image of a dark fabric.
"""
image_intensity = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
assert (image.shape[:2] == image_intensity.shape[:2])
height, width, channels = image.shape
dst = np.zeros((height, width, 3))
center_x = height // 2
center_y = width // 2
center_intensity = image_intensity[center_x:center_x+3, center_y:center_y+3]
center_intensity_avg = np.mean(center_intensity)
threshold = 3 * center_intensity_avg
_, thresholded = cv2.threshold(image_intensity, threshold, 255, cv2.THRESH_BINARY)
mask = cv2.cvtColor(thresholded, cv2.COLOR_GRAY2BGR)
result = cv2.add(image, mask)
return threshold, result
image = cv2.imread("./data/BuGgK.jpg", cv2.IMREAD_COLOR)
threshold, result = remove_background(image)
cv2.imwrite('./out/result.png', result)
如果结构中的某些色块低于阈值,它们将变为透明。为避免这种情况,您可以提取轮廓,然后去除“太小”以至不能整块衣服的轮廓。您也可以对图像进行预处理,以除去会产生孔的衣架(图像的上部)。