今天学习目标,依旧是前面知识的综合运用,基础夯实之后,才能继续深入学习
本篇博客目标,给下面这个红衣服美女,换成黄颜色衣服。
案例中用到的美女来源网络,只为学习,如有侵权,联系橡皮擦删除,女生真漂亮。
第一步,把美女的衣服选中
对于这种对比明显的图像,直接二值化,看一下红色衣服部分能否被选中出来。
import cv2 as cv
def change_clothes(src):
# 图像二值化
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
thresh, bin_img = cv.threshold(gray, 100, 255, cv.THRESH_BINARY)
cv.imshow("gray", gray)
cv.imshow("bin_img", bin_img)
if __name__ == "__main__":
src = cv.imread("./mv.jpg")
change_clothes(src)
cv.waitKey()
cv.destroyAllWindows()
复制代码
调整了半天数值,也没有发现一个比较好的效果,故放弃。
检索之后,一个新的函数映入橡皮擦视线。
inRange()函数实现二值化
该函数的语法格式为:
dst = cv2.inRange(hsv, lowerb, upperb, dst=None)
复制代码
函数目的是将介于[lowerb, upperb]
间的像素值变成 255,其他变为 0。参数说明如下:
hsv:指的是原图,但是需要注意图像格式
lowerb:指的是图像中低于这个 lowerb 的值,图像值变为 0
upperb:指的是图像中高于这个 upperb 的值,图像值变为 0
而在 lowerb ~ lowerb 之间的值变成 255
正常读入的 BGR 图像,需要提前转换成 HSV 格式,代码如下
hsv = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2HSV)
复制代码
正式编码之前,先获取一下衣服的红色 RGB 值。用画图工具操作即可。
这里会用到 HSV 色彩空间 的图像,这部分具体后面细说,本案例先应用起来。
HSV 即 Hue(色调),Saturation(饱和度)和 Value(亮度)三个 channel
对照上述表格,我们现在要找的是红色的衣服,那么选择的数字如下
红色框中是 lowerb
的值,绿色框中是 upperb
的值。
修改代码如下:
import cv2 as cv
import numpy as np
def change_clothes(src):
# 图像二值化
hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV)
# 使用 inRange()函数实现二值化
lowerb = np.array([38, 96, 80])
upperb = np.array([255, 255, 255])
dst = cv.inRange(hsv, lowerb, upperb)
rows, cols, channels = src.shape
for i in range(rows):
for j in range(cols):
if dst[i, j] == 255:
# 此处替换颜色,为 BGR 通道
src[i, j] = (0, 255, 255)
cv.imshow('src', src)
if __name__ == "__main__":
src = cv.imread("./mv.jpg")
change_clothes(src)
cv.waitKey()
cv.destroyAllWindows()
复制代码
运行之后的效果如下图所示,有点丑,技术能力还是不过关
第二步,二值化优化
有了第一步的经验,可以继续后面的操作了,猜想使用 inRange
函数实现二值化操作中参数设置的不好,所以做了下面一个滑动条的案例。
先看一下最终实现的效果,目标只要裙子部分显示成白色。
代码如下,初学阶段,还有很多不明白的地方,只能先写出如下代码了,希望有更好办法的大佬,提供一下相关资料,或者学习方向,感谢:
import cv2
import numpy as np
img = cv2.imread('mv.jpg')
def nothing(x):
pass
winName = 'getTrackbarPos'
# 新建窗口
cv2.namedWindow(winName, cv2.WINDOW_NORMAL)
cv2.createTrackbar('LowerbH', winName, 0, 10, nothing)
cv2.createTrackbar('LowerbS', winName, 43, 255, nothing)
cv2.createTrackbar('LowerbV', winName, 46, 255, nothing)
cv2.createTrackbar('UpperbH', winName, 180, 255, nothing)
cv2.createTrackbar('UpperbS', winName, 255, 255, nothing)
cv2.createTrackbar('UpperbV', winName, 255, 255, nothing)
# 转换hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
while(1):
# 函数cv2.getTrackbarPos()范围当前滑块对应的值
lowerbH = cv2.getTrackbarPos('LowerbH', winName)
LowerbS = cv2.getTrackbarPos('LowerbS', winName)
LowerbV = cv2.getTrackbarPos('LowerbV', winName)
upperbH = cv2.getTrackbarPos('UpperbH', winName)
upperbS = cv2.getTrackbarPos('UpperbS', winName)
upperbV = cv2.getTrackbarPos('UpperbV', winName)
lower_red = np.array([lowerbH, LowerbS, LowerbV])
upper_red = np.array([upperbH, upperbS, upperbV])
mask = cv2.inRange(hsv, lower_red, upper_red)
cv2.imshow(winName, mask)
if cv2.waitKey(1) == ord('q'):
break
cv2.destroyAllWindows()
复制代码
拿橡皮擦举例的这个图而言,最终得到的参数如下:
以上数据代入刚才的程序,得到的换装效果如下:
核心部分代码:
def change_clothes(src):
# 图像二值化
hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV)
# 使用 inRange()函数实现二值化
lowerb = np.array([0, 176, 91])
upperb = np.array([255, 255, 255])
dst = cv.inRange(hsv, lowerb, upperb)
rows, cols, channels = src.shape
for i in range(rows):
for j in range(cols):
if dst[i, j] == 255:
# 此处替换颜色,为 BGR 通道
src[i, j] = (0, 255, 255)
cv.imshow('src', src)
复制代码
使用的直接替换,效果不好,接下来试试相关函数。
采用 图像相加的方式,修改代码如下:
def change_clothes(src):
# 图像二值化
hsv = cv.cvtColor(src, cv.COLOR_BGR2HSV)
hsv1 = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)
# cv.imshow("hsv1",hsv1)
# 使用 inRange()函数实现二值化
lowerb = np.array([0, 176, 91])
upperb = np.array([255, 255, 255])
dst = cv.inRange(hsv, lowerb, upperb)
dst_inv = cv.bitwise_not(dst)
"""
# 颜色直接替换
rows, cols, channels = src.shape
for i in range(rows):
for j in range(cols):
if dst[i, j] == 255:
# 此处替换颜色,为 BGR 通道
src[i, j] = (0, 255, 255)
"""
# 读取一张yellow 图片
yellow = cv.imread("./yellow.png")
# 蛋黄的裙子
result1 = cv.add(yellow,yellow,mask=dst)
# 黑色的裙子
result2 =cv.add(src,1,mask=dst_inv)
ret = cv.addWeighted(result2,1,result1,0.5,10)
# ret = cv.add(result2,result1)
cv.imshow('ret', result1)
复制代码
运行之后,效果依旧不满意,看来知识储备量,还是不够,当然,我使用纯色背景尝试了一下,这个效果不错,但是换衣服颜色,还是需要继续努力学习啦。
OpenCV 尾声
1 个小时又过去了,对 Python OpenCV 相关的知识点,你掌握了吗?
空闲之余,可以订阅橡皮擦的爬虫百例课程学习爬虫知识。
想学 Python 爬虫,可以订阅橡皮擦专栏哦~
🈲🈲🈲🈲 点击发现惊喜 🈲🈲🈲🈲
如果你想跟博主建立亲密关系,可以关注同名公众号 <font color="red">梦想橡皮擦</font>,近距离接触一个逗趣的互联网高级网虫。博主 ID:梦想橡皮擦,希望大家<font color="red">点赞</font>、<font color="red">评论</font>、<font color="red">收藏</font>。
评论