我用Python中的OpenCV lib读取了一张图片。 我想知道如何将背景颜色更改为白色。我只想让有图像和白色背景的人。
例如:
我要更改为此:
我该怎么做:
import numpy as np
import cv2
my_image = r'C:\Users\Pc\Desktop\preklapanje4.jpg'
my_image = cv2.imread(my_image, 1)
cv2.imshow('img',my_image)
cv2.waitKey(0)
答案 0 :(得分:0)
在此图像中,由于未连接所有背景绿色,因此需要在多个区域中进行填充。
import cv2
import numpy as np
# load image and get dimensions
img = cv2.imread("soccer.jpg")
h, w, c = img.shape
# create zeros mask 2 pixels larger in each dimension
mask = np.zeros([h + 2, w + 2], np.uint8)
# do floodfill
result = img.copy()
cv2.floodFill(result, mask, (0,0), (255,255,255), (3,151,65), (3,151,65), flags=8)
cv2.floodFill(result, mask, (38,313), (255,255,255), (3,151,65), (3,151,65), flags=8)
cv2.floodFill(result, mask, (363,345), (255,255,255), (3,151,65), (3,151,65), flags=8)
cv2.floodFill(result, mask, (619,342), (255,255,255), (3,151,65), (3,151,65), flags=8)
# write result to disk
cv2.imwrite("soccer_floodfill.jpg", result)
# display it
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
结果:
根据需要调整低和高颜色范围,以消除更多的绿色。
请参见floodfill
添加:
这是我的评论中建议的在HSV中进行inRange阈值处理的代码。但请注意,全局阈值已影响衬衫中的一些近白色,使其变成纯白色。可以通过关闭一些大尺寸的形态或用白色填充较小的轮廓来消除其中的某些部分。
import cv2
import numpy as np
import skimage.exposure
# load image and get dimensions
img = cv2.imread("soccer.jpg")
# convert to hsv
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
# threshold using inRange
range1 = (20,80,80)
range2 = (90,255,255)
mask = cv2.inRange(hsv,range1,range2)
mask = 255 - mask
# apply morphology opening to mask
kernel = np.ones((3,3), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# antialias mask
mask = cv2.GaussianBlur(mask, (0,0), sigmaX=3, sigmaY=3, borderType = cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(mask, in_range=(127.5,255), out_range=(0,255))
result = img.copy()
result[mask==0] = (255,255,255)
# write result to disk
cv2.imwrite("soccer_mask.png", mask)
cv2.imwrite("soccer_green2white.jpg", result)
# display it
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
遮罩:
结果:
ADDITION2:
这是我发现可以有效去除绿屏的另一种方法。转换为LAB。然后取反A并将其乘以B。然后对它进行inRange()阈值处理以创建蒙版。然后使用遮罩使绿色变成白色。与以前的方法相比,它可以防止衬衫中的近白色被迫变成纯白色。但不幸的是,这后面留下了绿色。
import cv2
import numpy as np
import skimage.exposure
# load image and get dimensions
img = cv2.imread("soccer.jpg")
# convert to hsv
lab = cv2.cvtColor(img,cv2.COLOR_BGR2LAB)
L = lab[:,:,0]
A = lab[:,:,1]
B = lab[:,:,2]
# negate A
A = (255 - A)
# multiply negated A by B
nAB = 255 * (A/255) * (B/255)
nAB = np.clip((nAB), 0, 255)
nAB = np.uint8(nAB)
# threshold using inRange
range1 = 100
range2 = 160
mask = cv2.inRange(nAB,range1,range2)
mask = 255 - mask
# apply morphology opening to mask
kernel = np.ones((3,3), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# antialias mask
mask = cv2.GaussianBlur(mask, (0,0), sigmaX=3, sigmaY=3, borderType = cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(mask, in_range=(127.5,255), out_range=(0,255))
# put white where ever the mask is zero
result = img.copy()
result[mask==0] = (255,255,255)
# write result to disk
cv2.imwrite("soccer_green2white_inrange_lab.jpg", result)
# display it
cv2.imshow("nAB", nAB)
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果: