Python_图像处理

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

2021-11-16  本文已影响0人  梦想橡皮擦

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

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

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

20210118203424794[1].png

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

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

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()

调整了半天数值,也没有发现一个比较好的效果,故放弃。

20210118204228642[1].png

检索之后,一个新的函数映入橡皮擦视线。

inRange()函数实现二值化

该函数的语法格式为:

dst = cv2.inRange(hsv, lowerb, upperb, dst=None)

函数目的是将介于[lowerb, upperb]间的像素值变成 255,其他变为 0。
参数说明如下:

正常读入的 BGR 图像,需要提前转换成 HSV 格式,代码如下

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

正式编码之前,先获取一下衣服的红色 RGB 值。用画图工具操作即可。

这里会用到 HSV 色彩空间 的图像,这部分具体后面细说,本案例先应用起来。

HSV 即 Hue(色调),Saturation(饱和度)和 Value(亮度)三个 channel


20210118205636762[1].png

对照上述表格,我们现在要找的是红色的衣服,那么选择的数字如下

20210118205913267[1].png

红色框中是 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()

运行之后的效果如下图所示,有点丑,技术能力还是不过关

20210118213511244[1].png

第二步,二值化优化

有了第一步的经验,可以继续后面的操作了,猜想使用 inRange 函数实现二值化操作中参数设置的不好,所以做了下面一个滑动条的案例。

先看一下最终实现的效果,目标只要裙子部分显示成白色。

20210119132448282[1].gif

代码如下,初学阶段,还有很多不明白的地方,只能先写出如下代码了,希望有更好办法的大佬,提供一下相关资料,或者学习方向,感谢:

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()

拿橡皮擦举例的这个图而言,最终得到的参数如下:


20210119132744852[1].png

以上数据代入刚才的程序,得到的换装效果如下:


20210119132845638[1].png

核心部分代码:

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">58</font> / 100 天。
如果你有想要交流的想法、技术,欢迎在评论区留言。


如果你想跟博主建立亲密关系,可以关注同名公众号 <font color="red">梦想橡皮擦</font>,近距离接触一个逗趣的互联网高级网虫。
博主 ID:梦想橡皮擦,希望大家<font color="red">点赞</font>、<font color="red">评论</font>、<font color="red">收藏</font>。

上一篇下一篇

猜你喜欢

热点阅读