OpenCV笔记4:级联分类器实现嘴部检测

OpenCV

嘴部检测

"""
嘴部区域检测
1. 静态图像检测嘴部区域
    创建分类器
    加载特征文件
    检测图像
    绘制嘴部区域
    显示
2. 切换为摄像头
"""
import cv2
import numpy as np


class FaceDetect:
    def __init__(self):
        # 级联分类器
        # 创建级联分类器,当前用于检测人脸
        classifier_face = cv2.CascadeClassifier()
        classifier_mouth = cv2.CascadeClassifier()
        # 加载 特征文件
        classifier_face.load('./haarcascade_frontalface_alt.xml')
        classifier_mouth.load('./haarcascade_mcs_mouth.xml')
        self.classifier_face = classifier_face
        self.classifier_mouth = classifier_mouth
        # 初始化logo
        self.logo = cv2.imread('./fans.jpg')
        pass

    def capVideo(self):
        cap = cv2.VideoCapture(0)
        while cap.isOpened():
            # 读取一帧一帧的图像
            retval, frame = cap.read()
            if not retval:
                print('can not read frame')
                break
            # imshow 会默认创建一个窗口
            self.detect(frame)
            cv2.imshow('frame', frame)
            key = cv2.waitKey(25)
            if key == ord('z'):
                break
        cap.release()
        pass

    def detect(self, face_img):
        # 级联分类器检测人脸
        face_rects = self.classifier_face.detectMultiScale(face_img)
        # 绘制人脸区域
        for face_rect in face_rects:
            x, y, w, h = face_rect
            cv2.rectangle(face_img, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=2)
            # self.drawLogo(face_rect, face_img)
            # self.drawLogo2(face_rect, face_img)
            self.detectMouth(face_rect, face_img)

    def detectMouth(self, face_rect, face_img):
        # 检测嘴巴
        mouth_rects = self.classifier_mouth.detectMultiScale(face_img)
        face_min_x, face_min_y, face_w, face_h = face_rect
        # 方式1
        # for mouth_rect in mouth_rects:
        #     x, y, w, h = mouth_rect
        #     # 排除人脸左右区域
        #     # if x < face_min_x or x > face_min_x + face_w:
        #     #     continue
        #     # # 排除人脸上下区域
        #     # if y < face_min_y or y > face_min_y + face_h:
        #     #     continue
        #     # 排除人脸中部上面的区域
        #     if y < face_min_y + face_h * 0.6:
        #         continue
        #     cv2.rectangle(face_img, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2)
        # 方式2
        # is_right_mouth = mouth_rects[:, 0] > face_min_x
        # is_down_mouth = mouth_rects[:, 1] > face_min_y
        # is_lower_mouth = mouth_rects[:, 1] > (face_min_y + face_h * 0.6)
        # is_mouth = is_right_mouth & is_down_mouth & is_lower_mouth
        # mouth_rect = mouth_rects[is_mouth]
        idx = mouth_rects[:, 1] > (face_min_y + face_h * 0.6)
        mouth_rect = mouth_rects[idx]
        for rect in mouth_rect:
            x, y, w, h = rect
            cv2.rectangle(face_img, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2)

    def drawLogo(self, face_rect, face_img):
        x, y, w, h = face_rect
        logo = self.logo
        ratio = min(logo.shape[:2]) / max(logo.shape[:2])
        scale_logo = cv2.resize(logo, dsize=(w, round(w * ratio)))
        scale_logo_h, scale_logo_w, _ = scale_logo.shape
        # 方式1:循环
        # for row in range(scale_logo_h):
        #     for col in range(scale_logo_w):
        #         face_img[y - scale_logo_h + row, x + col] = scale_logo[row, col]
        #         pass
        # 方式2:切片
        face_img[y - scale_logo_h:y, x:x + scale_logo_w] = scale_logo

    def drawLogo2(self, face_rect, face_img):
        """
        1. 找轮廓
            - 原图:三通道彩色图
            - 灰度图(0-255)
            - 黑白二值图(0/255)
        2. 绘制轮廓
            - 绘制在背景是白色的图
        :param face_rect:
        :param face_img:
        :return:
        """
        # 参数1 被转换的图像
        # 参数2 原图转为灰度图
        logo_gray = cv2.cvtColor(self.logo, cv2.COLOR_BGR2GRAY)
        # 转为二值图
        # 参数1 灰度图
        # 参数2 阈值 小于阈值为0
        # 参数3 大于阈值为maxval
        # 参数4 类型    cv2.THRESH_BINARY   cv2.THRESH_OTSU 会自适应阈值
        # retval, logo_binary = cv2.threshold(logo_gray, 100, 255, cv2.THRESH_BINARY)
        retval, logo_binary = cv2.threshold(logo_gray, 100, 255, cv2.THRESH_OTSU)
        # 查找轮廓
        # 参数1 被查找的二值图
        # 参数2 轮廓存放的层级关系
        # 参数3 存放轮廓的方式   cv2.CHAIN_APPROX_SIMPLE 存放轮廓的拐角点
        contours, hierarchy = cv2.findContours(logo_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        # 创建一个黑色的背景图
        mask = np.zeros_like(self.logo)
        cv2.drawContours(mask, contours, 1, color=(255, 255, 255), thickness=-1)

        x, y, w, h = face_rect
        logo = self.logo
        ratio = min(logo.shape[:2]) / max(logo.shape[:2])
        scale_logo = cv2.resize(logo, dsize=(w, round(w * ratio)))
        scale_mask = cv2.resize(mask, dsize=(w, round(w * ratio)))
        scale_logo_h, scale_logo_w, _ = scale_logo.shape
        # 方式1:循环
        # for row in range(scale_logo_h):
        #     for col in range(scale_logo_w):
        #         if np.all(scale_mask[row, col] == 255):
        #             face_img[y - scale_logo_h + row, x + col] = scale_logo[row, col]
        # 方式2:切片
        idx = scale_mask == 255
        after_mask_logo = scale_logo[idx]
        face_img[y - scale_logo_h:y, x:x + scale_logo_w][idx] = after_mask_logo
        pass


if __name__ == '__main__':
    face_img = cv2.imread('./lyf.png')
    face_detect = FaceDetect()
    # face_detect.capVideo()
    face_detect.detect(face_img)
    cv2.imshow('frame', face_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

人脸原图

lyf.png

嘴部检测效果图

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/404543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

云原生之容器管理工具Portainer

1. 简介 前面文章我们讲Docker、Docker Compose和Docker Swarm都是在Linux系统上手工命令行去操作&#xff0c;在第一次安装的时候可以命令行&#xff0c;以后运维和CICD流程操作中&#xff0c;如果还要命令行去各个节点操作&#xff0c;操作就麻烦了&#xff0c;工作效…

Seata 入门知识

目录 概述 工作流程 工作模式 AT模式 TCC模式 概述 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 AT模式是阿里首推…

Linux系统运维:离线安装sar-性能监视和分析工具

目 录 一、前言 二、系统环境 三、安装sar &#xff08;一&#xff09;准备工作 1、下载 sar 工具的安装包&#xff1a; 2、将安装包传输到 CentOS 服务器 &#xff08;二&#xff09;安装工作 1、解压 2、配置安装 3、编译 4、安装 &#xff08;三&#xff0…

C# Onnx 使用onnxruntime部署实时视频帧插值

目录 介绍 效果 模型信息 项目 代码 下载 C# Onnx 使用onnxruntime部署实时视频帧插值 介绍 github地址&#xff1a;https://github.com/google-research/frame-interpolation FILM: Frame Interpolation for Large Motion, In ECCV 2022. The official Tensorflow 2…

【Flink集群RPC通讯机制(四)】集群组件(tm、jm与rm)之间的RPC通信

文章目录 1. 集群内部通讯方法概述2. TaskManager向ResourceManager注册RPC服务3. JobMaster向ResourceManager申请Slot计算资源 现在我们已经知道Flink中RPC通信框架的底层设计与实现&#xff0c;接下来通过具体的实例了解集群运行时中组件如何基于RPC通信框架构建相互之间的调…

大数据 - Spark系列《十一》- Spark累加器详解

Spark系列文章&#xff1a; 大数据 - Spark系列《一》- 从Hadoop到Spark&#xff1a;大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 大数据 - Spark系列《…

2024/02/23

使用消息队列完成两个进程间相互通信 A.c #include<myhead.h> struct msgbuf {long mtype;char mtext[1024]; }; //定义表示正文内容大小的宏 #define MSGSIZE sizeof(struct msgbuf)-sizeof(long)int main(int argc, const char *argv[]) {//创建一个key值key_t key;ke…

知乎66条高赞回答,句句醍醐灌顶!

-01- 穷人是小心翼翼地大方&#xff0c; 有钱人是大大方方地小气。 ——论如何判断一个人是真有钱还是装有钱 -02- 枕头要常晒&#xff0c; 因为里面装满了心酸的泪和发霉的梦。 ——一切终将随风而逝 -03- 人活得累&#xff0c;一是太认真&#xff0c;二是太想要。 …

第3部分 原理篇2去中心化数字身份标识符(DID)(3)

3.2.2.4. DID文档 (DID Document) 本聪老师&#xff1a;DID标识符和DID URL还都只是ID&#xff0c;必须为它附加一个基本属性才可以证明是该主体独有的。这个就是我们下面介绍的DID文档。 本聪老师&#xff1a;每个DID标识符都唯一对应一个DID文档&#xff0c;也可以说&#x…

计算机功能简介:EC, NVMe, SCSI/ISCSI与块存储接口 RBD,NUMA

一 EC是指Embedded Controller 主要应用于移动计算机系统和嵌入式计算机系统中&#xff0c;为此类计算机提供系统管理功能。EC的主要功能是控制计算机主板上电时序、管理电池充电和放电&#xff0c;提供键盘矩阵接口、智能风扇接口、串口、GPIO、PS/2等常规IO功能&#xff0c;…

docker自定义网络实现容器之间的通信

Background docker原理 docker是一个Client-Server结构的系统&#xff0c;Docker的守护进程运行在主机上。通过Socket从客户端访问。docker核心三大组件&#xff1a;image–镜像、container-容器、 repository-仓库。docker使用的cpu、内存以及系统内核等资源都是直接使用宿主…

A Novel Two-Layer DAG-based Reactive Protocol for IoT Data Reliability in Metaverse

在IOT 场景中&#xff0c;需要保证数据的完整性和可靠性。通常区块链可以用来做这件事&#xff0c;但是IoT 设备的计算能力和贷款都是有限的。 对于PBFT 要求的通信量太大。 本文提出的 two layer directed acycle graph (2LDAG) 是一种被动共识协议&#xff0c;除非有节点主动…

快速构建 Debezium MySQL Example 数据库

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

EXCEL 在列不同单元格之间插入N个空行

1、第一步数据&#xff0c;要求在每个数字之间之间插入3个空格 2、拿数据个数*&#xff08;要插入空格数1&#xff09; 19*4 3、填充 4、复制数据到D列 5、下拉数据&#xff0c;选择复制填充这样1-19就会重复4次 6、全选数据D列排序&#xff0c;这样即完成了插入空格 以…

SQL语法-DQL-测试练习

因篇幅原因&#xff0c;本篇承接此篇->第八篇&#xff1a;SQL语法-DQL-数据查询语言-CSDN博客 本篇是对于SQL语法DQL语句的练习&#xff0c;因水平和精力有限&#xff08;就不像前两篇的DDL&#xff0c;DML那样自出练习了&#xff09;直接照搬了【黑马程序员】在哔哩哔哩的…

基于卷积神经网络的图像去噪

目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 基于卷积神经网络的图像去噪 完整代码:基于卷积神经网络的图像去噪.rar资源-CSDN文库 https://download.csdn.net/download/abc9918351…

如何在java中使用 Excel 动态函数生成依赖列表

前言 在Excel 中&#xff0c;依赖列表或级联下拉列表表示两个或多个列表&#xff0c;其中一个列表的项根据另一个列表而变化。依赖列表通常用于Excel的业务报告&#xff0c;例如学术记分卡中的【班级-学生】列表、区域销售报告中的【区域-国家/地区】列表、人口仪表板中的【年…

vue3 + ts + echart 实现柱形图表

首先封装Echart一个文件 代码如下 <script setup lang"ts"> import { ECharts, EChartsOption, init } from echarts; import { ref, watch, onMounted, onBeforeUnmount } from vue;// 定义props interface Props {width?: string;height?: string;optio…

网工内推 | 信息安全售前,国企、上市公司,补贴福利多

01 中电科网络安全科技有限公司 招聘岗位&#xff1a;信息安全售前工程师 职责描述&#xff1a; 1.负责为客户提供整体信息安全规划、IT治理需求调研、现状分析、蓝图规划与实施路线设计&#xff0c;为客户提供设计方案&#xff1b; 2.承担行业信息安全发展研究、行业业务规划…

vue3 vuex

目录 Vuex 是什么 什么是“状态管理模式”&#xff1f; 什么情况下我应该使用 Vuex&#xff1f; 使用方法&#xff1a; 提交载荷&#xff08;Payload&#xff09; 对象风格的提交方式 使用常量替代 Mutation 事件类型 Mutation 必须是同步函数 在组件中提交 Mutation …