Jud*_*nga 7 python opencv image-processing
正如您所看到的,图像中有一些嘈杂的绿色轮廓。这是迄今为止我使用 OpenCV 和 Python 的最新输出。我还是个初学者,所以我需要你的帮助。
假设我要创建一个全新的脚本并提供该图像并“清理”图像,我将如何做?
Here is a rather simple approach.
Dominant colors like red, green, blue and yellow can be segmented pretty easily when analyzed in LAB color space. LAB space has 3 channels, out of which only 2 are color channels while 1 is a brightness channel:
Observing the plot above:
在相应的通道中应用合适的阈值可以使我们轻松分割这些颜色。
我们将使用上述信息作为解决当前问题的基础:
1. 执行基本屏蔽:
->将图像转换为 LAB 空间
->阈值 a 通道以隔离绿色背景
->使用二进制掩码掩蔽原始图像
img = cv2.imread('green_background.jpg')
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_channel = lab[:,:,1]
th = cv2.threshold(a_channel,127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
masked = cv2.bitwise_and(img, img, mask = th) # contains dark background
m1 = masked.copy()
m1[th==0]=(255,255,255) # contains white background
Run Code Online (Sandbox Code Playgroud)
2. 去除边框上的绿色阴影:
->转换蒙版图像 LAB 空间
->标准化 a 通道mlab[:,:,1]以使用 [0-255] 逆二进制阈值之间的整个强度范围
->来选择带有绿色边框的区域
mlab = cv2.cvtColor(masked, cv2.COLOR_BGR2LAB)
dst = cv2.normalize(mlab[:,:,1], dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
Run Code Online (Sandbox Code Playgroud)
上图是边界周围有暗像素的 a 通道。
threshold_value = 100
dst_th = cv2.threshold(dst, threshold_value, 255, cv2.THRESH_BINARY_INV)[1]
Run Code Online (Sandbox Code Playgroud)
上面是分割绿色阴影区域的阈值图像。
在 a 通道中,绿色代表范围 [0-255] 的下限,而红色代表上限。我们将所选像素的 a 通道中的强度值设置为 127:
mlab2 = mlab.copy()
mlab[:,:,1][dst_th == 255] = 127
Run Code Online (Sandbox Code Playgroud)
现在,在上图中,我们看不到人物周围的黑色边框。
将图像转换为 BGR,并将阈值图像中较暗 (0) 的像素设置为彩色图像中的白色 (255, 255, 255)
img2 = cv2.cvtColor(mlab, cv2.COLOR_LAB2BGR)
img2[th==0]=(255,255,255)
Run Code Online (Sandbox Code Playgroud)
生成的图像看起来没有太大变化,所以这里是放大的比较:
步骤 2 之前:
第 2 步之后:
边界周围嘈杂的绿色轮廓得到了一定程度的改善。您可以尝试改变threshold_value并进行实验。
人脸上的绿色阴影仍然存在。需要复杂的方法来消除这些。希望这种方法有所帮助。
这是 @Jeru Luke 使用 Python/OpenCV 的答案的变体。它在 LAB 色彩空间中执行相同的阈值处理,但我只是使用模糊和 A 通道上灰度值输入范围一半的拉伸来进行抗锯齿。它的优点是减少一些绿色并使结果平滑,以便它可以平滑地融入任何背景图像。
调整 rescale_intensity 中的模糊西格玛值和/或输入剪辑值,以调整平滑度和绿色显示量。
输入:
import cv2
import numpy as np
import skimage.exposure
# load image
img = cv2.imread('greenscreen.jpg')
# convert to LAB
lab = cv2.cvtColor(img,cv2.COLOR_BGR2LAB)
# extract A channel
A = lab[:,:,1]
# threshold A channel
thresh = cv2.threshold(A, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# blur threshold image
blur = cv2.GaussianBlur(thresh, (0,0), sigmaX=5, sigmaY=5, borderType = cv2.BORDER_DEFAULT)
# stretch so that 255 -> 255 and 127.5 -> 0
mask = skimage.exposure.rescale_intensity(blur, in_range=(127.5,255), out_range=(0,255)).astype(np.uint8)
# add mask to image as alpha channel
result = img.copy()
result = cv2.cvtColor(img,cv2.COLOR_BGR2BGRA)
result[:,:,3] = mask
# save output
cv2.imwrite('greenscreen_thresh.png', thresh)
cv2.imwrite('greenscreen_mask.png', mask)
cv2.imwrite('greenscreen_antialiased.png', result)
# Display various images to see the steps
cv2.imshow('A',A)
cv2.imshow('thresh', thresh)
cv2.imshow('blur', blur)
cv2.imshow('mask', mask)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)
阈值图像:
遮罩图像(用于 Alpha 通道):
结果:
在图像上使用Canny 边缘检测。然后根据它的外观使用形态扩张( cv.dilate()) 使边缘变厚一点。然后去除图像绿色通道的边缘或降低绿色通道的亮度。或者使像素透明。
这篇文章阐述了以下方法:
1.) 将绿色像素转换为透明度。基本上使用 HSV 颜色空间中的过滤规则。
2.) 在头发和一些边界像素上,颜色与绿色混合。为了减少这个问题,这些像素被过滤和平衡以减少它们的绿色比例。
3.) 对所有边界像素应用渐变透明度。
| 归档时间: |
|
| 查看次数: |
16235 次 |
| 最近记录: |