创作大赛

六、HSV颜色空间应用实例——颜色分割提取与替换

教程汇总:python基础入门系列

通过之前的章节(四、OpenCV颜色空间——HSV颜色模型),我们已经初步认识了HSV颜色空间的特性与优势,现在就来看两个典型的应用实例,颜色分割提取 与 颜色替换。

颜色分割

通过HSV颜色空间的操作我们可以准确的对指定颜色进行分割图像,这也是后续图像处理中会用到的一种预处理手段。

下面我们就结合一个实例来看HSV颜色分割的应用: 如下图是一个穿有红色上衣的人,我们要把衣服部分的图分割出来: 通过前面几个章节的讲解我们能够想到,可以通过观察h分量的直方图来确定这个上衣红色的取值范围,以作为我们分割的界限标准。上代码:

import cv2

import numpy as np

from matplotlib import pyplot as plt

#通过OpenCV读取图片信息

img = cv2.imread('RedShirt.jpg')

# BGR图转为HSV

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 提取hsv中H通道数据

h = hsv[:, :, 0].ravel()

# 直方图显示

plt.hist(h, 180, [0, 180])

plt.show()

得到直方图如下: 根据HSV颜色空间模型可知 红色的颜色分布在0或180附近,直方图中170到180部分出现了大量数据,由此可以确定红色的H分量上下限为170-180,至于SV的界限可以先给个30-255的初始值,具体可以在提取掩模的时候调整确定。 下面通过HSV的红色界限生成mask掩模。上代码:

import cv2

import numpy as np

from matplotlib import pyplot as plt

#通过OpenCV读取图片信息

img = cv2.imread('RedShirt.jpg')

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 提取hsv中H通道数据

# h = hsv[:, :, 0].ravel()

#

# plt.hist(h, 180, [0, 180])

# plt.show()

cv2.imshow("img", img)

# HSV 的下界限

lower_red = np.array([170,30,30])

# HSV 的上界限

upper_red = np.array([180,255,255])

# 通过上下限提取范围内的掩模mask

mask = cv2.inRange(hsv, lower_red, upper_red)

cv2.imshow("mask", mask)

cv2.waitKey(0)

cv2.destroyAllWindows()

结果如下图: 可以发现,答题衣服轮廓对上了,但是有些细节不够完美,比如胳膊两侧还有些白点,这时候就要分析了,胳膊侧边的颜色更接近暗红颜色,所以可以通过提高V值的下限来滤除掉。通过不断调整测试我设定的V值在100-255。 但是发现右侧的白点已经无法通过V的调整来去除了,这个时候我们还可以采取另一种方法,对于mask这种二值化图处理,可以采用膨胀腐蚀的手段来消除独立的白点或黑点。上代码:

import cv2

import numpy as np

#通过OpenCV读取图片信息

img = cv2.imread('RedShirt.jpg')

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

cv2.imshow("img", img)

# HSV 的下界限

lower_red = np.array([170,30,90])

# HSV 的上界限

upper_red = np.array([180,255,255])

# 通过上下限提取范围内的掩模mask

mask = cv2.inRange(hsv, lower_red, upper_red)

cv2.imshow("mask", mask)

# 腐蚀与膨胀处理

# 定义

kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))#定义结构元素的形状和大小

#腐蚀图像

eroded = cv2.erode(mask,kernel)

#显示腐蚀后的图像

cv2.imshow("Eroded Image",eroded)

# #膨胀图像

dilated = cv2.dilate(eroded,kernel)

#显示膨胀后的图像

cv2.imshow("Dilated Image",dilated)

img2 = cv2.bitwise_and(img, img, mask=dilated)

cv2.imshow("img2", img2)

cv2.waitKey(0)

cv2.destroyAllWindows()

生成mask之后我们先是用腐蚀方法去除掉周边的孤立白点,但同样的衣服轮廓的白色区域边界也会被腐蚀变小,这时候可以用反向操作膨胀在填充回原来的大小 这样我们优化好的mask掩模就做好了,可以采用OpenCV的图像位运算cv2.bitwise_and()把原图与mask进行位与得到衣服的抠图:

颜色替换

通过上面的操作我们已经可以准确的分割出我们指定的颜色了,在次基础上就可以对他的颜色进行更改了,比如改成黄色,这个同样也是要在HSV颜色空间操作的,不过这次就不需要对mask进行膨胀腐蚀优化了。

import cv2

import numpy as np

def nothing(x):

pass

#通过OpenCV读取图片信息

img = cv2.imread('RedShirt.jpg')

cv2.imshow("img", img)

lower_red = np.array([170,30,30])

upper_red = np.array([180,255,255])

cv2.namedWindow('img2')

cv2.createTrackbar('H','img2',140,180,nothing)

cv2.createTrackbar('S','img2',100,180,nothing)

cv2.createTrackbar('V','img2',117,180,nothing)

rows,cols,channels = img.shape

while(1):

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

mask = cv2.inRange(hsv, lower_red, upper_red)

#将制定像素点的数据设置为0, 要注意的是这三个参数对应的值是Blue, Green, Red。

h = cv2.getTrackbarPos('H', 'img2')

s = cv2.getTrackbarPos('S', 'img2')

v = cv2.getTrackbarPos('V', 'img2')

for r in range(rows):

for c in range(cols):

if mask[r, c] == 255:

hsv.itemset((r, c, 0), hsv.item(r, c, 0) -h)

hsv.itemset((r, c, 1), hsv.item(r, c, 1) +90-s)

hsv.itemset((r, c, 2), hsv.item(r, c, 2) +90-v)

img2 = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

#将图像进行输出,使用show()也是可以显示的。

cv2.imshow("img2", img2)

k = cv2.waitKey(1)&0xFF

if k == 27: #esc exit

break

#cv2.waitKey(0)

cv2.destroyAllWindows()

通过滑动H滑条我们就可以更改衣服的颜色了,同样调节SV滑条也可以更改饱和度与明度。

同样的,我们把皮肤颜色作为颜色分割替换目标也可以更改皮肤颜色,比如改成绿巨人的肤色:

Copyright © 2088 承德书写游戏活动中心 - 剧情创作专属天地 All Rights Reserved.
友情链接