在这张图片中,由于所有的背景绿色都不是相连的,你需要对几个区域进行泛洪填充。
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()
Input:
结果:
根据需要调整低和高的颜色范围,以消除更多的绿色。
请参阅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()
结果:
附加2:
这是另一种我发现有效的去除绿屏的方法。将图像转换为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()
Result:
[h + 2, w + 2]
中使用数字2,以及如何确定floodfill中的数字? - taga