写点什么

Python OpenCV 美女换装,图像处理取经之旅第 19 天

发布于: 2021 年 04 月 06 日
Python OpenCV 美女换装,图像处理取经之旅第 19 天

今天学习目标,依旧是前面知识的综合运用,基础夯实之后,才能继续深入学习


本篇博客目标,给下面这个红衣服美女,换成黄颜色衣服。


案例中用到的美女来源网络,只为学习,如有侵权,联系橡皮擦删除,女生真漂亮。


第一步,把美女的衣服选中

对于这种对比明显的图像,直接二值化,看一下红色衣服部分能否被选中出来。


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 cvimport 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 cv2import 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)# 转换hsvhsv = 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>。

发布于: 2021 年 04 月 06 日阅读数: 30
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
Python OpenCV 美女换装,图像处理取经之旅第 19 天