人脸图像数据增强

news2025/1/13 13:32:32

为什么要做数据增强

在计算机视觉相关任务中,数据增强(Data Augmentation)是一种常用的技术,用于扩展训练数据集的多样性。它包括对原始图像进行一系列随机或有规律的变换,以生成新的训练样本。数据增强的主要目的是增加模型的泛化能力、提高模型的鲁棒性,并减轻过拟合的风险。以下是进行数据增强的几个重要原因:

  1. 增加数据样本数量:数据增强可以通过生成变体来增加训练样本的数量。这对于具有有限标记样本的任务非常重要,因为更多的数据样本有助于提高模型的性能。

  2. 泛化能力:数据增强可以引入多样性,使模型能够更好地泛化到新的、未见过的数据。这有助于模型在真实世界的各种情况下表现良好,而不仅仅是在训练时的数据分布中表现良好。

  3. 鲁棒性:通过对数据进行多样性的变换,模型可以更好地处理因噪声、光照变化、旋转、缩放等因素引起的图像变化。这提高了模型在复杂环境中的稳健性。

  4. 降低过拟合风险:数据增强可以减轻模型过拟合的风险,因为它迫使模型不仅仅学会记住训练数据,还要学会对数据的变化做出反应。这有助于提高模型对新数据的适应能力。

  5. 类别平衡:在多类别分类任务中,某些类别的样本数量可能较少。数据增强可以帮助平衡各个类别的样本数量,以防止模型偏向于出现频率较高的类别。

  6. 节省标注成本:在某些情况下,收集和标记大量的训练数据可能非常昂贵和耗时。通过数据增强,您可以使用较少的标记样本来训练模型,同时保持性能。

常见的数据增强技术包括图像翻转、旋转、缩放、裁剪、颜色变换、加噪声等。选择哪些数据增强技术以及如何应用它们通常取决于具体任务和数据集的特点。数据增强在许多计算机视觉任务中都被广泛使用,包括图像分类、目标检测、分割、人脸识别等。通过增强数据的多样性,可以提高模型的性能并使其更适应复杂的现实世界场景。

人脸图像数据增强

对于人脸图像数据增强,有多种方法可以提高模型的鲁棒性和性能。以下是一些常见的人脸图像数据增强方法:

  1. 旋转和翻转: 随机旋转或翻转图像,以改变人脸的角度和方向,使模型更具鲁棒性。
  2. 缩放和裁剪: 随机调整图像的大小并进行裁剪,以模拟不同尺度和视角下的人脸。
  3. 亮度和对比度调整: 修改图像的亮度、对比度和色彩平衡,以增加模型的鲁棒性。
  4. 噪声添加: 向图像中添加随机噪声,以模拟真实世界中的图像变化。
  5. 颜色扭曲: 扭曲图像的颜色通道,使图像对于不同的照明条件更具鲁棒性。
  6. 遮挡和变形: 在图像中添加遮挡物或变形,以增加模型对于不完整或变形人脸的处理能力。
  7. 人脸关键点扰动: 对图像中的人脸关键点进行随机扰动,以改变面部特征的位置。
  8. 风格迁移: 将不同图像的风格应用到人脸图像上,以增加多样性。
  9. 镜像对称: 镜像对称图像,以生成左右对称的人脸数据。
  10. 增加噪声数据: 引入合成噪声数据,以增加模型对于嘈杂环境下的鲁棒性。

这些增强方法可以单独使用,也可以组合使用。

实现

以下是个人实现的一些人脸增强方式,不会对原始人脸数据造成太大的干扰,进而不会引入脏数据:

  • 旋转:范围在(-20°, 20°) 表示向左向右旋转
def rotate_image(image):
        rows, cols, _ = image.shape
        angle = random.randint(-20, 20)
        M = cv2.getRotationMatrix2D((cols/2, rows/2), angle, 1)
        rotated_image = cv2.warpAffine(image, M, (cols, rows))
        return rotated_image
  • 翻转:只水平翻转
def flip_image(image):
        return cv2.flip(image, 1)
  • 缩放:范围是原先的(0.8, 1.2)之间
def scale_image(image, scale_factor):
        scale_factor = random.uniform(0.8, 1.2)
        rows, cols, _ = image.shape
        new_size = (int(cols * scale_factor), int(rows * scale_factor))
        scaled_image = cv2.resize(image, new_size)
        return scaled_image
  • 改变亮度对比度
def adjust_brightness_contrast(image):
        alpha = random.uniform(0.5, 1.5)
        beta = random.randint(10, 50)
        return cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
  • 改变颜色
def color_distortion(image, color_matrix):
    	# color_matrix = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]])
        return cv2.transform(image, color_matrix)
  • 加椒盐噪声
def salt_and_pepper_noise(image, salt_prob=0.01, pepper_prob=0.01):
        noisy_image = image.copy()
        total_pixels = image.size
        num_salt = int(total_pixels * salt_prob)
        salt_coords = [np.random.randint(0, i-1, num_salt) for i in image.shape]
        noisy_image[salt_coords[0], salt_coords[1]] = 255
        num_pepper = int(total_pixels * pepper_prob)
        pepper_coords = [np.random.randint(0, i-1, num_pepper) for i in image.shape]
        noisy_image[pepper_coords[0], pepper_coords[1]] = 0
        return noisy_image
  • 直方图均衡化
def equalizeHist_image(image):
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        return cv2.equalizeHist(image)
  • 自适应直方图均衡化
def clahe_image(image):
        b, g, r = cv2.split(image)
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(5, 5))
        clahe_b = clahe.apply(b)
        clahe_g = clahe.apply(g)
        clahe_r = clahe.apply(r)
        return cv2.merge((clahe_b, clahe_g, clahe_r))
  • 油画与非真实感渲染
def detailEnhance_image(image):
        return cv2.detailEnhance(image, None, 20, 0.8)
  • 局部区域亮度调整
def illumination_change(image):
        img_zero = np.zeros(image.shape, dtype=np.uint8)
        return cv2.illuminationChange(image, mask=img_zero, alpha=0.2, beta=0.4)
  • 人脸中心点加强或者变暗
def enhance_reduce(image, strength=100):
        # strength > 0 enhance, strength < 0 reduce
        x, y, _ = image.shape
        radius = np.random.randint(10, int(min(x, y)), 1)
        pos_x = np.random.randint(0, (min(x, y)-radius), 1)
        pos_y = np.random.randint(0, (min(x, y)-radius), 1)
        pos_x = int(pos_x[0])
        pos_y = int(pos_y[0])
        radius = int(radius[0])
        for j in range(pos_y-radius, pos_y+radius):
            for i in range(pos_x-radius, pos_x+radius):
                distance = math.pow((pos_x-i), 2) + math.pow((pos_y-j), 2)
                distance = np.sqrt(distance)
                if distance < radius:
                    result = 1 - distance/radius
                    result = result*strength
                    if strength > 0:
                        image[i, j, 0] = min((image[i, j, 0]+result), 255)
                        image[i, j, 1] = min((image[i, j, 1]+result), 255)
                        image[i, j, 2] = min((image[i, j, 2]+result), 255)
                    else:
                        image[i, j, 0] = max((image[i, j, 0]+result), 0)
                        image[i, j, 1] = max((image[i, j, 1]+result), 0)
                        image[i, j, 2] = max((image[i, j, 2]+result), 0)
        image = image.astype(np.uint8)
        return image
  • 遮盖
def mask(image, low=10, high=50):
        x, y, _ = image.shape
        mask_size = np.random.randint(low, high, 1)
        pos_x = np.random.randint(low, (min(x, y)-high), 1)
        pos_y = np.random.randint(low, (min(x, y)-high), 1)
        pos_x = int(pos_x[0])
        pos_y = int(pos_y[0])
        mask_size = int(mask_size[0])
        image[pos_x:pos_x+mask_size, pos_y:pos_y+mask_size] = 0
        return image

将上述合并为一个类:

import os
import cv2
import sys
import json
import math
import random
import numpy as np


class ImageAugment:
    def rotate_image(self, image):
        rows, cols, _ = image.shape
        angle = random.randint(-20, 20)
        M = cv2.getRotationMatrix2D((cols/2, rows/2), angle, 1)
        rotated_image = cv2.warpAffine(image, M, (cols, rows))
        return rotated_image

    def flip_image(self, image):
        return cv2.flip(image, 1)

    def scale_image(self, image, scale_factor):
        scale_factor = random.uniform(0.8, 1.2)
        rows, cols, _ = image.shape
        new_size = (int(cols * scale_factor), int(rows * scale_factor))
        scaled_image = cv2.resize(image, new_size)
        scaled_image = cv2.resize(scaled_image, (112, 112))
        return scaled_image

    def adjust_brightness_contrast(self, image):
        alpha = random.uniform(0.5, 1.5)
        beta = random.randint(10, 50)
        return cv2.convertScaleAbs(image, alpha=alpha, beta=beta)

    def color_distortion(self, image, color_matrix):
        return cv2.transform(image, color_matrix)

    def salt_and_pepper_noise(self, image, salt_prob=0.01, pepper_prob=0.01):
        noisy_image = image.copy()
        total_pixels = image.size
        num_salt = int(total_pixels * salt_prob)
        salt_coords = [np.random.randint(0, i-1, num_salt) for i in image.shape]
        noisy_image[salt_coords[0], salt_coords[1]] = 255
        num_pepper = int(total_pixels * pepper_prob)
        pepper_coords = [np.random.randint(0, i-1, num_pepper) for i in image.shape]
        noisy_image[pepper_coords[0], pepper_coords[1]] = 0
        return noisy_image

    def equalizeHist_image(self, image):
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        return cv2.equalizeHist(image)

    def clahe_image(self, image):
        b, g, r = cv2.split(image)
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(5, 5))
        clahe_b = clahe.apply(b)
        clahe_g = clahe.apply(g)
        clahe_r = clahe.apply(r)
        return cv2.merge((clahe_b, clahe_g, clahe_r))

    def detailEnhance_image(self, image):
        return cv2.detailEnhance(image, None, 20, 0.8)

    def illumination_change(self, image):
        img_zero = np.zeros(image.shape, dtype=np.uint8)
        return cv2.illuminationChange(image, mask=img_zero, alpha=0.2, beta=0.4)

    def enhance_reduce(self, image, strength=100):
        # strength > 0 enhance, strength < 0 reduce
        x, y, _ = image.shape
        radius = np.random.randint(10, int(min(x, y)), 1)
        pos_x = np.random.randint(0, (min(x, y)-radius), 1)
        pos_y = np.random.randint(0, (min(x, y)-radius), 1)
        pos_x = int(pos_x[0])
        pos_y = int(pos_y[0])
        radius = int(radius[0])
        for j in range(pos_y-radius, pos_y+radius):
            for i in range(pos_x-radius, pos_x+radius):
                distance = math.pow((pos_x-i), 2) + math.pow((pos_y-j), 2)
                distance = np.sqrt(distance)
                if distance < radius:
                    result = 1 - distance/radius
                    result = result*strength
                    if strength > 0:
                        image[i, j, 0] = min((image[i, j, 0]+result), 255)
                        image[i, j, 1] = min((image[i, j, 1]+result), 255)
                        image[i, j, 2] = min((image[i, j, 2]+result), 255)
                    else:
                        image[i, j, 0] = max((image[i, j, 0]+result), 0)
                        image[i, j, 1] = max((image[i, j, 1]+result), 0)
                        image[i, j, 2] = max((image[i, j, 2]+result), 0)
        image = image.astype(np.uint8)
        return image

    def mask(self, image, low=10, high=50):
        x, y, _ = image.shape
        mask_size = np.random.randint(low, high, 1)
        pos_x = np.random.randint(low, (min(x, y)-high), 1)
        pos_y = np.random.randint(low, (min(x, y)-high), 1)
        pos_x = int(pos_x[0])
        pos_y = int(pos_y[0])
        mask_size = int(mask_size[0])
        image[pos_x:pos_x+mask_size, pos_y:pos_y+mask_size] = 0
        return image


if __name__ == '__main__':
    ia = ImageAugment()
    image_path = sys.argv[1]
    image = cv2.imread(image_path)

    rotated_image = ia.rotate_image(image)
    flipped_image = ia.flip_image(image)
    scaled_image = ia.scale_image(image, scale_factor=1.2)
    adjusted_image = ia.adjust_brightness_contrast(image)
    color_matrix = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]])
    color_distorted_image = ia.color_distortion(image, color_matrix)
    salt_image = ia.salt_and_pepper_noise(image)
    equalize_image = ia.equalizeHist_image(image)
    clahe_image = ia.clahe_image(image)
    detailenhance_image = ia.detailEnhance_image(image)
    illumination_image = ia.illumination_change(image)
    enhance_image = ia.enhance_reduce(image, 100)
    reduce_image = ia.enhance_reduce(image, -100)
    mask_image = ia.mask(image)

    # save
    cv2.imwrite('rotated.jpg', rotated_image)
    cv2.imwrite('flipped.jpg', flipped_image)
    cv2.imwrite('scaled.jpg', scaled_image)
    cv2.imwrite('adjusted.jpg', adjusted_image)
    cv2.imwrite('colorDistorted.jpg', color_distorted_image)
    cv2.imwrite('salt.jpg', salt_image)
    cv2.imwrite('equalize.jpg', equalize_image)
    cv2.imwrite('clahe.jpg', clahe_image)
    cv2.imwrite('detailenhance.jpg', detailenhance_image)
    cv2.imwrite('illumination.jpg', illumination_image)
    cv2.imwrite('enhance.jpg', enhance_image)
    cv2.imwrite('reduce.jpg', reduce_image)
    cv2.imwrite('mask.jpg', mask_image)

结果如下:

  • origin image:
    在这里插入图片描述

  • rotate:

在这里插入图片描述

  • flip:

在这里插入图片描述

  • scale:

在这里插入图片描述

  • adjust:

在这里插入图片描述

  • colorDistorted:

在这里插入图片描述

  • salt:

在这里插入图片描述

  • equalize:

在这里插入图片描述

  • clahe:

在这里插入图片描述

  • detailenhance:

在这里插入图片描述

  • illumination:

在这里插入图片描述

  • enhance and reduce:

在这里插入图片描述

在这里插入图片描述

  • mask:

在这里插入图片描述

参考

  • https://blog.csdn.net/qq_39450134/article/details/121886296
  • https://blog.csdn.net/u011808673/article/details/90752958
  • https://www.youbiguo.com/py/273.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为杯数学建模比赛经验分享

再过一周左右,第二十届华为杯数学建模比赛就要开赛了&#xff0c;所以今天分享一下个人数学建模比赛的经验。 今天给大家分享一期关于华为杯数学建模比赛的经验分享&#xff0c;我将从以下三个方面展开说明&#xff1a; &#xff08;1&#xff09;如何准备数学建模比赛&#x…

ELK日志分析系统+ELFK(Filebeat)

本章结构&#xff1a; 1、ELK日志分析系统简介 2、Elasticsearch介绍&#xff08;简称ES&#xff09; 3、Logstash介绍 4、Kibana介绍 5、实验&#xff0c;ELK部署 一、ELK日志分析系统简介 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将 ElasticSearch、Logst…

Ubuntu修改静态IP、网关和DNS的方法总结

Ubuntu修改静态IP、网关和DNS的方法总结 ubuntu系统&#xff08;其他debian的衍生版本好像也可以&#xff09;修改静态IP有以下几种方法。&#xff08;搜索总结&#xff0c;可能也不太对&#xff09; /etc/netplan (use) Ubuntu 18.04开始可以使用netplan配置网络&#xff0…

2.4GHz、DA14530-00000FX2射频收发器/LSM6DSOTR 6 轴运动传感器/SKY66423-11射频前端 860MHz 至 930MHz

一、2.4GHz、DA14530-00000FX2射频收发器 IC DA14530是一款超低功耗蓝牙5.1 SoC。它集成了2.4 GHz CMOS收发器和ARMCortex-M0微控制器&#xff0c;具有48 kB RAM和32 kB一次性可编程&#xff08;OTP&#xff09;存储器。无线电收发器、基带处理器和合格的Bluetooth低功耗堆栈完…

Android13适配-Google官方照片视频选择器

官方照片选择器 图 1. 照片选择器提供了一个直观的界面&#xff0c;便于与您的应用分享照片。 照片选择器的界面可供浏览和搜索&#xff0c;并按日期降序向用户显示其媒体库中的文件。如隐私保护最佳实践 Codelab 中所示&#xff0c;照片选择器为用户提供了一种安全的内置授权…

代码随想录算法训练营day56|583. 两个字符串的删除操作|72. 编辑距离

583. 两个字符串的删除操作 力扣题目链接 给定两个单词 word1 和 word2&#xff0c;找到使得 word1 和 word2 相同所需的最小步数&#xff0c;每步可以删除任意一个字符串中的一个字符。 示例&#xff1a; 输入: “sea”, “eat” 输出: 2 解释: 第一步将"sea"变…

Android StateFlow初探

Android StateFlow初探 前言&#xff1a; 最近在学习StateFlow&#xff0c;感觉很好用&#xff0c;也很神奇&#xff0c;于是记录了一下. 1.简介&#xff1a; StateFlow 是一个状态容器式可观察数据流&#xff0c;可以向其收集器发出当前状态更新和新状态更新。还可通过其 …

【计算机毕业设计】基于SpringBoot+Vue的小区物业管理系统的设计与实现

博主主页&#xff1a;一季春秋博主简介&#xff1a;专注Java技术领域和毕业设计项目实战、Java、微信小程序、安卓等技术开发&#xff0c;远程调试部署、代码讲解、文档指导、ppt制作等技术指导。主要内容&#xff1a;毕业设计(Java项目、小程序等)、简历模板、学习资料、面试题…

【C++面向对象侯捷】6.复习Complex类的实现过程

2.考虑数据 3.考虑函数 3.1 考虑构造函数&#xff08;赋初值&#xff0c;初始化操作&#xff09; 3.2 考虑成员函数 3.3 后面添加的&#xff0c;friend 友元函数 4. 考虑 成员函数 实现 5. 考虑 全局函数&#xff08;非成员函数&#xff09; 【这里考虑为什么不设计为成员…

第七章 查找 四、分块查找

一、给每个区间分块&#xff0c;再建立索引表&#xff0c;表内数为块内最大值 二、使用顺序查找数 先在索引表内找对应区域&#xff0c;在通过此索引映射到对应区间&#xff0c;进行顺序查找。 三、查找效率分析&#xff08;ASL&#xff09; 查找7时&#xff0c;先顺序查找索…

Java Semaphore使用例子和流程

目录 Semaphore例子代码和输出semaphore.acquire();semaphore.release(); Semaphore semaphore : 英[ˈseməfɔː(r)] 美[ˈseməfɔːr] n. 旗语; 信号标; v. 打旗语; (用其他类似的信号系统)发信号; [例句]Semaphore was widely used at sea, before the advent of electr…

坚鹏:中国邮储银行金融科技前沿技术发展与应用场景第3期培训

中国邮政储蓄银行金融科技前沿技术发展与应用场景第3期培训圆满结束 中国邮政储蓄银行拥有优良的资产质量和显著的成长潜力&#xff0c;是中国领先的大型零售银行。2016年9月在香港联交所挂牌上市&#xff0c;2019年12月在上交所挂牌上市。中国邮政储蓄银行拥有近4万个营业网点…

计算机中找不到d3dcompiler47.dll怎么解决,实用解决方法推荐

d3dcompiler_47.dll是一个动态链接库文件&#xff0c;它是DirectX的一个组件。DirectX是一套用于处理多媒体数据的API&#xff0c;包括游戏和视频播放等。d3dcompiler_47.dll主要负责编译和链接顶点着色器、几何着色器和像素着色器等&#xff0c;以生成可执行文件。当DirectX无…

【Redis】深入探索 Redis 主从结构的创建、配置及其底层原理

文章目录 前言一、对 Redis 主从结构的认识1.1 什么是主从结构1.2 主从结构解决的问题 二、主从结构创建2.1 配置并建立从节点2.2.1 从节点配置文件2.2.2 启动并连接 Redis 主从节点2.2.3 SLAVEOF 命令2.2.4 断开主从关系 2.2 查看主从节点的信息2.2.1 INFO REPLICATION 命令2.…

2023年度教育部人文社会科学研究一般项目评审结果,已公布!

【SciencePub学术】 9月15日&#xff0c;教育部社科司公示了2023年度教育部人文社会科学研究一般项目评审结果&#xff0c;共3482项。 其中&#xff0c;规划基金、青年基金、自筹经费项目共3029项通过专家评审&#xff1b;西部和边疆地区项目200项&#xff0c;新疆项目20项&a…

typescript高级类型-类型兼容性

4.2类型兼容性 两种类型系统:1StructuralType System (结构化类型系统)2 NominalType System (标明类型系统)。 TS 采用的是结构化类型系统&#xff0c;也叫做 ducktyping (鸭子类型…?什么???你不明白什么叫鸭子类型? 伟大的鲁迅先生说过如果一个东西,看起来是鸭子,叫起来…

如何下载安装 SAP HANA Studio

什么是SAP HANA Studio SAP HANA Studio 是一个基于 Eclipse 的集成开发环境&#xff08;IDE&#xff09;&#xff0c;用于以 GUI 工具的形式开发和管理 SAP HANA 数据库。 SAP HANA Studio 在客户端/开发人员计算机上运行&#xff0c;​​并连接到 SAP HANA 服务器。 SAP HA…

上位机通过Modbus转Profinet网关与CGV300变频器通讯案例

上位机通过Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;与CGV300变频器通讯的案例可以实现两个不同的通信协议之间的互联互通。在这个案例中&#xff0c;上位机通过Modbus协议与Profinet网关进行通信&#xff0c;然后通过Profinet协议与CGV300变频器进行通信。 通过…

C++中的转换构造函数

在 C/C++ 中,不同的数据类型之间可以相互转换。无需用户指明如何转换的称为自动类型转换(隐式类型转换),需要用户显式地指明如何转换的称为强制类型转换。 自动类型转换示例: int a = 6;a = 7.5 + a; 编译器对 7.5 是作为 double 类型处理的,在求解表达式时,先将 a 转换…

Python Opencv实践 - 视频目标追踪MeanShift

参考资料&#xff1a; opencv/python标定时用到的几个函数意义_criteria opencv_是三水不是泗水的博客-CSDN博客 pythonOpenCV笔记&#xff08;二十六&#xff09;&#xff1a;视频追踪&#xff08;meanshift、Camshift&#xff09;_cv2.meanshift_ReadyGo!!!的博客-CSDN博客…