opencv-隐身术

目     录

一、准备工作:

 二、大致思路

三、代码实现

1、小试牛刀

2、图片隐身

3、摄像头实时隐身

4、使用Qt组件

四、总结


一、准备工作:

opencv库和PyQt5库

一张背景图和同一背景人举着红布的图

 二、大致思路

要实现的效果如下:

 图片隐身思路:

 背景图

 手持红布图

(1)先将手持红布图片格式转化为方便操作的hsv格式

(2)用背景图扣出纯色板。

(3)再根据掩膜取反,用红布背景扣出除了红布外的背景。

(4)将两张图片像素做与运算,即两张照片拼在一起

摄像头实时隐身思路:

(1)打开摄像头,然后最先读取到的图片充当背景。

(2)后面人进入摄像头范围手举着红布(红色物体),代入刚刚的图片隐身思路。

使用Qt组件:

(1)将视频放入窗口。

(2)通过按钮控制实时隐身视频。

人脸识别那篇文章详细讲解了所需的组件,此处不再赘述。

三、代码实现

1、小试牛刀

先读取一张有红色背景的图片

​
import cv2 as cv


image = cv.imread("image.jpg")  # 读取图片
cv.imshow("image", image)  # 展示图片

cv.waitKey(0)   # 参数0为等待用户操作

运行结果如下:

将图片改为hsv格式

imgHSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)  # 改为hsv格式

运行结果如下:

 利用这个hsv颜色空间扣出红色背景图,发现红色有两栏,那我们分别扣出两栏,再直接相加:

mask1 = cv.inRange(imgHSV, (0, 43, 46), (10, 255, 255))
mask2 = cv.inRange(imgHSV, (156, 43, 46), (180, 255, 255))
mask = mask1 + mask2

 运行结果如下:

 

此时我们成功扣出红色背景,接下来我们将掩膜做取反操作:

dst = cv.bitwise_not(mask)

 运行结果如下:

此时我们成功扣出人像。

2、图片隐身

(1)我们先读取背景图和手持红布图。

Red_cloth = cv.imread("redbackground.jpg")
cv.imshow("red_cloth", Red_cloth)
background = cv.imread("background.jpg")
cv.imshow("back", background)

 运行结果如下:

(2)我们读取图片后将图片转化为hsv格式,然后根据hsv颜色空间扣出红色区域。

imgHSV = cv.cvtColor(Red_cloth, cv.COLOR_BGR2HSV)  # 改为hsv格式
cv.imshow("imghsv", imgHSV)
# 取红色区域
mask1 = cv.inRange(imgHSV, (0, 43, 46), (10, 255, 255))
mask2 = cv.inRange(imgHSV, (156, 43, 46), (180, 255, 255))
mask3 = mask1 + mask2
cv.imshow("mask", mask3)

运行结果如下:

 我们再将掩膜取反试试。

# 取反操作
mask_not = cv.bitwise_not(mask3)
cv.imshow("mask_not", mask_not)

运行结果如下:

​​​​​​​

我们发现,我们只想要的是扣红布区域,但却扣出了其他一些无关的东西。

并不是代码和颜色空间有问题,只是因为旁边的物体呈暗红色,也属于红色的范围,所以也被抠出来了。此时我们只需要缩小hsv所给的红色范围,让它只包含红布的颜色范围,即可扣出红布,参数可自行慢慢调节。

mask1 = cv.inRange(imgHSV, (0, 158, 46), (10, 230, 230))
mask2 = cv.inRange(imgHSV, (156, 158, 46), (180, 230, 230))
mask3 = mask1 + mask2

 运行结果如下:

(3)我们将掩膜取反,扣出除了红布外的区域。

mask_not = cv.bitwise_not(mask3)
cv.imshow("mask_not", mask_not)

 运行结果如下:

(4)将背景图和红布掩膜做像素与运算。

image1 = cv.bitwise_and(background, background, mask=mask3)
cv.imshow("red_cloth_background", image1)

 运行结果如下:

(5)将手持红布图与取反的掩膜做像素与运算。

image2 = cv.bitwise_and(Red_cloth, Red_cloth, mask=mask_not)
cv.imshow("background", image2)

 运行结果如下:

(6)将两张图片相加。

image = cv.add(image1, image2)
cv.imshow("Stealth", image)

运行结果如下:

 我们已经成功实现图片隐身。

3、摄像头实时隐身

此部分不再展示运行结果。

(1)打开摄像头先捕获的图片作为背景

cap = cv.VideoCapture(0)

for i in range(1, 10):
    flag, frame = cap.read()
background = frame

 (2)人进入摄像头范围后,手持红布作为隐身布

cap = cv.VideoCapture(0)

flag, image = cap.read()
imgHSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)

mask1 = cv.inRange(imgHSV, (0, 158, 46), (10, 255, 255))
mask2 = cv.inRange(imgHSV, (156, 158, 46), (180, 255, 255))
mask3 = mask1 + mask2

mask_not = cv.bitwise_not(mask3)
        
image1 = cv.bitwise_and(self.background, self.background, mask=mask3)
image2 = cv.bitwise_and(image, image, mask=mask_not)
image3 = cv.add(image1, image2)

小结:摄像头隐身部分已经完成,可用esc键关闭程序,小结代码如下(可运行):

import cv2 as cv

cap = cv.VideoCapture(0)

# 刚打开摄像头读取的图片作为背景
for i in range(1, 10):
    flag, frame = cap.read()
background = frame

while True:
    flag, image = cap.read()
    # 图片转hsv格式
    imgHSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)

    # 取红色掩膜
    mask1 = cv.inRange(imgHSV, (0, 100, 46), (10, 255, 255))
    mask2 = cv.inRange(imgHSV, (156, 100, 46), (180, 255, 255))
    mask3 = mask1 + mask2

    # 掩膜取反
    mask_not = cv.bitwise_not(mask3)

    # 像素与运算
    image1 = cv.bitwise_and(background, background, mask=mask3)
    image2 = cv.bitwise_and(image, image, mask=mask_not)

    image3 = cv.add(image1, image2)
    cv.imshow("Stealth", image3)
    if cv.waitKey(40) == 27:
        break

cap.release()  # 释放内存空间

4、使用Qt组件

人脸识别那篇文章详细讲解了所需的组件,此处不再赘述。

这是部分Qt组件和定时器的代码:

from PyQt5.Qt import *
import sys


    def intiUI(self):

        self.resize(600, 600)  # 窗口大小,可自行调整参数
        self.setWindowTitle("隐身术")  # 窗口标题

        # 定时器链接槽函数
        self.timer.timeout.connect(self.Stealth)

        startbtn = QPushButton("播放", self)  # "播放"为按钮的名称
        startbtn.resize(560, 30)  # 播放按钮的大小设置函数
        startbtn.move(20, 480)  # 播放按钮的坐标位置函数
        startbtn.clicked.connect(self.on_setting_click)  # 播放按钮链接鼠标事件

        # 同理,暂停按钮如下:
        endbtn = QPushButton("暂停", self)
        endbtn.resize(560, 30)
        endbtn.move(20, 520)
        endbtn.clicked.connect(self.up_setting_click)  # 暂停按钮链接鼠标事件

        self.lab = QLabel("这里是显示视频的区域", self)  # 文本标签
        self.lab.move(220, 250)  # 标签位置


    def on_setting_click(self):
        # 刚打开摄像头读取的图片作为背景
        for i in range(1, 10):
            flag, frame = cap.read()
        self.background = frame
        self.timer.start(20)

    def up_setting_click(self):
        self.timer.stop()

    def Stealth(self):
        image3 = cv.cvtColor(image3, cv.COLOR_BGR2RGB)  # frame  opencv mat
        # mat =>  Qt 图片容器格式

        image4 = QImage(image3.data,image3.shape[1],image3.shape[0],QImage.Format_RGB888)

        pixmap = QPixmap.fromImage(image4)

        pixmap = pixmap.scaled(self.lab.size())
        self.lab.setPixmap(pixmap)
        self.lab.move(40, 40)  # 位置设置函数
        self.lab.resize(520, 390)  # 大小设置函数


if __name__ == '__main__':
    app = QApplication(sys.argv)

    setting = SettingUI()
    setting.show()

    sys.exit(app.exec())

四、总结

总代码如下:

import cv2 as cv
from PyQt5.Qt import *
import sys


cap = cv.VideoCapture(0)


class SettingUI(QWidget):
    def __init__(self):
        super(SettingUI, self).__init__()
        self.timer = QTimer()
        self.intiUI()

    def intiUI(self):

        self.resize(600, 600)  # 窗口大小,可自行调整参数
        self.setWindowTitle("隐身术")  # 窗口标题

        # 定时器链接槽函数
        self.timer.timeout.connect(self.Stealth)

        startbtn = QPushButton("播放", self)  # "播放"为按钮的名称
        startbtn.resize(560, 30)  # 播放按钮的大小设置函数
        startbtn.move(20, 480)  # 播放按钮的坐标位置函数
        startbtn.clicked.connect(self.on_setting_click)  # 播放按钮链接鼠标事件

        # 同理,暂停按钮如下:
        endbtn = QPushButton("暂停", self)
        endbtn.resize(560, 30)
        endbtn.move(20, 520)
        endbtn.clicked.connect(self.up_setting_click)  # 暂停按钮链接鼠标事件

        self.lab = QLabel("这里是显示视频的区域", self)  # 文本标签
        self.lab.move(220, 250)  # 标签位置

    def on_setting_click(self):
        # 刚打开摄像头读取的图片作为背景
        for i in range(1, 10):
            flag, frame = cap.read()
        self.background = frame
        self.timer.start(20)   

    def up_setting_click(self):
        self.timer.stop()

    def Stealth(self):
        flag, image = cap.read()
        imgHSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)
        
        # 取红色掩膜
        mask1 = cv.inRange(imgHSV, (0, 158, 46), (10, 255, 255))
        mask2 = cv.inRange(imgHSV, (156, 158, 46), (180, 255, 255))
        mask3 = mask1 + mask2

        # 掩膜取反
        mask_not = cv.bitwise_not(mask3)

        # 像素与运算
        image1 = cv.bitwise_and(self.background, self.background, mask=mask3)
        image2 = cv.bitwise_and(image, image, mask=mask_not)

        image3 = cv.add(image1, image2)

        image3 = cv.cvtColor(image3, cv.COLOR_BGR2RGB)  # frame  opencv mat

        image4 = QImage(image3.data, image3.shape[1], image3.shape[0], QImage.Format_RGB888)

        pixmap = QPixmap.fromImage(image4)

        pixmap = pixmap.scaled(self.lab.size())
        self.lab.setPixmap(pixmap)
        self.lab.move(40, 40)  # 位置设置函数
        self.lab.resize(520, 390)  # 大小设置函数


if __name__ == '__main__':
    app = QApplication(sys.argv)

    setting = SettingUI()
    setting.show()

    sys.exit(app.exec())

运行结果如下:

​​​​​​​ 

猜你喜欢

转载自blog.csdn.net/Nantainanle/article/details/132469448