图像处理 数据增强方法

2017-02-08 15:18:13 qq_29133371 阅读数 9578
# -*- coding:utf-8 -*-
"""数据增强
   1. 翻转变换 flip
   2. 随机修剪 random crop
   3. 色彩抖动 color jittering
   4. 平移变换 shift
   5. 尺度变换 scale
   6. 对比度变换 contrast
   7. 噪声扰动 noise
   8. 旋转变换/反射变换 Rotation/reflection
   author: XiJun.Gong
   date:2016-11-29
"""

from PIL import Image, ImageEnhance, ImageOps, ImageFile
import numpy as np
import random
import threading, os, time
import logging
import cv2
logger = logging.getLogger(__name__)
ImageFile.LOAD_TRUNCATED_IMAGES = True


class DataAugmentation:
    """
    包含数据增强的八种方式
    """


    def __init__(self):
        pass

    @staticmethod
    def openImage(image):
        return Image.open(image, mode="r")

    @staticmethod
    def randomRotation(image, mode=Image.BICUBIC):
        """
         对图像进行随机任意角度(0~360度)旋转
        :param mode 邻近插值,双线性插值,双三次B样条插值(default)
        :param image PIL的图像image
        :return: 旋转转之后的图像
        """
        random_angle = np.random.randint(1, 360)
        return image.rotate(random_angle, mode)
        #return image.rotate(180, mode)
 
    @staticmethod
    def randomFlip(image):
        #图像翻转(类似于镜像,镜子中的自己)
        #FLIP_LEFT_RIGHT,左右翻转
        #FLIP_TOP_BOTTOM,上下翻转
        #ROTATE_90, ROTATE_180, or ROTATE_270.按照角度进行旋转,与randomRotate()功能类似
        return image.transpose(Image.FLIP_LEFT_RIGHT)
   
    @staticmethod
    def Tranform(image):
        #t图像变换
        #im.transform(size, method, data) ⇒ image

        #im.transform(size, method, data, filter) ⇒ image
        #1:image.transform((300,300), Image.EXTENT, (0, 0, 300, 300)) 
        #   变量data为指定输入图像中两个坐标点的4元组(x0,y0,x1,y1)。
        #   输出图像为这两个坐标点之间像素的采样结果。
        #   例如,如果输入图像的(x0,y0)为输出图像的(0,0)点,(x1,y1)则与变量size一样。
        #   这个方法可以用于在当前图像中裁剪,放大,缩小或者镜像一个任意的长方形。
        #   它比方法crop()稍慢,但是与resize操作一样快。
        #2:image.transform((300,300), Image.AFFINE, (1, 2,3, 2, 1,4))
        #   变量data是一个6元组(a,b,c,d,e,f),包含一个仿射变换矩阵的第一个两行。
        #   输出图像中的每一个像素(x,y),新值由输入图像的位置(ax+by+c, dx+ey+f)的像素产生,
        #   使用最接近的像素进行近似。这个方法用于原始图像的缩放、转换、旋转和裁剪。
        #3: image.transform((300,300), Image.QUAD, (0,0,0,500,600,500,600,0))
        #   变量data是一个8元组(x0,y0,x1,y1,x2,y2,x3,y3),它包括源四边形的左上,左下,右下和右上四个角。
        #4: image.transform((300,300), Image.MESH, ())
        #   与QUAD类似,但是变量data是目标长方形和对应源四边形的list。
        #5: image.transform((300,300), Image.PERSPECTIVE, (1,2,3,2,1,6,1,2))
        #   变量data是一个8元组(a,b,c,d,e,f,g,h),包括一个透视变换的系数。
        #   对于输出图像中的每个像素点,新的值来自于输入图像的位置的(a x + b y + c)/(g x + h y + 1),
        #   (d x+ e y + f)/(g x + h y + 1)像素,使用最接近的像素进行近似。
        #   这个方法用于原始图像的2D透视。
        return image.transform((300,300), Image.EXTENT, (0, 0, 300, 300))

    @staticmethod
    def randomCrop(image):
        """
        对图像随意剪切,考虑到图像大小范围(68,68),使用一个一个大于(36*36)的窗口进行截图
        :param image: PIL的图像image
        :return: 剪切之后的图像

        """
        image_width = image.size[0]
        image_height = image.size[1]
        crop_win_size = np.random.randint(40, 68)
        random_region = (
            (image_width - crop_win_size) >> 1, (image_height - crop_win_size) >> 1, (image_width + crop_win_size) >> 1,
            (image_height + crop_win_size) >> 1)
        return image.crop(random_region)

    @staticmethod
    def randomColor(image):
        """
        对图像进行颜色抖动
        :param image: PIL的图像image
        :return: 有颜色色差的图像image
        """
        random_factor = np.random.randint(0, 31) / 10.  # 随机因子
        color_image = ImageEnhance.Color(image).enhance(random_factor)  # 调整图像的饱和度
        random_factor = np.random.randint(10, 21) / 10.  # 随机因子
        brightness_image = ImageEnhance.Brightness(color_image).enhance(random_factor)  # 调整图像的亮度
        random_factor = np.random.randint(10, 21) / 10.  # 随机因1子
        contrast_image = ImageEnhance.Contrast(brightness_image).enhance(random_factor)  # 调整图像对比度
        random_factor = np.random.randint(0, 31) / 10.  # 随机因子
        return ImageEnhance.Sharpness(contrast_image).enhance(random_factor)  # 调整图像锐度

    @staticmethod
    def randomGaussian(image, mean=0.2, sigma=0.3):
        """
         对图像进行高斯噪声处理
        :param image:
        :return:
        """

        def gaussianNoisy(im, mean=0.2, sigma=0.3):
            """
            对图像做高斯噪音处理
            :param im: 单通道图像
            :param mean: 偏移量
            :param sigma: 标准差
            :return:
            """
            for _i in range(len(im)):
                im[_i] += random.gauss(mean, sigma)
            return im

        # 将图像转化成数组
        img = np.asarray(image)
        img.flags.writeable = True  # 将数组改为读写模式
        width, height = img.shape[:2]
        img_r = gaussianNoisy(img[:, :, 0].flatten(), mean, sigma)
        img_g = gaussianNoisy(img[:, :, 1].flatten(), mean, sigma)
        img_b = gaussianNoisy(img[:, :, 2].flatten(), mean, sigma)
        img[:, :, 0] = img_r.reshape([width, height])
        img[:, :, 1] = img_g.reshape([width, height])
        img[:, :, 2] = img_b.reshape([width, height])
        return Image.fromarray(np.uint8(img))

    @staticmethod
    def saveImage(image, path):
        image.save(path)


def makeDir(path):
    try:
        if not os.path.exists(path):
            if not os.path.isfile(path):
                # os.mkdir(path)
                os.makedirs(path)
            return 0
        else:
            return 1
    except Exception, e:
        print str(e)
        return -2


def imageOps(func_name, image, des_path, file_name, times=5):
    #funcMap = {"randomRotation": DataAugmentation.randomRotation,
    #           "randomCrop": DataAugmentation.randomCrop,
    #           "randomColor": DataAugmentation.randomColor,
    #           "randomGaussian": DataAugmentation.randomGaussian
    #           "randomFlip":DataAugmentation.randomFlip,
    #           }
    funcMap = {
               "Tranform":DataAugmentation.Tranform
               }
    if funcMap.get(func_name) is None:
        logger.error("%s is not exist", func_name)
        return -1

    for _i in range(0, times, 1):
        new_image = funcMap[func_name](image)
        DataAugmentation.saveImage(new_image, os.path.join(des_path, func_name + str(_i) + file_name))


#opsList = {"randomFlip","randomRotation", "randomCrop", "randomColor", "randomGaussian"}
opsList = { "Tranform"}

def threadOPS(path, new_path):
    """
    多线程处理事务
    :param src_path: 资源文件
    :param des_path: 目的地文件
    :return:
    """
    if os.path.isdir(path):
        img_names = os.listdir(path)
    else:
        img_names = [path]
    for img_name in img_names:
        print img_name
        tmp_img_name = os.path.join(path, img_name)
        if os.path.isdir(tmp_img_name):
            if makeDir(os.path.join(new_path, img_name)) != -1:
                threadOPS(tmp_img_name, os.path.join(new_path, img_name))
            else:
                print 'create new dir failure'
                return -1
                # os.removedirs(tmp_img_name)
        elif tmp_img_name.split('.')[1] != "DS_Store":
            # 读取文件并进行操作
            image = DataAugmentation.openImage(tmp_img_name)
            threadImage = [0] * 5
            _index = 0
            for ops_name in opsList:
                threadImage[_index] = threading.Thread(target=imageOps,
                                                       args=(ops_name, image, new_path, img_name,))
                threadImage[_index].start()
                _index += 1
                time.sleep(0.2)


if __name__ == '__main__':
    threadOPS("D:\datasets\dataArgument\JPEGImages",
              "D:\datasets\dataArgument\Dealed_JPEGImages")


PIL:http://effbot.org/imagingbook/image.htm#tag-Image.Image.transform

2019-06-28 09:58:26 AugustMe 阅读数 2272

深度学习模型训练时通常都需要大量的训练集,我们在做图像相关的应用时同样需要进行图像数据增加,下面我将给大家总结10种图像数据增强常用的方式

1、水平翻转
随机的对图片进行水平翻转,这个参数适用于水平翻转不影响图片语义的时候。

2、竖直翻转
随机的对图片进行竖直翻转,这个参数适用于竖直翻转不影响图片语义的时候。

3、随机翻转角度
设置一个0~180的度数,用来指定随机旋转图片的角度。

4、随机水平平移
用来指定水平方向随机移动的程度。

5、随机竖直平移
用来指定竖直方向随机移动的程度。

6、随机错切变换
在某方向上,按照一定的比例对图形的每个点到某条平行于该方向的直线的有向距离做放缩得到的平面图形。

7、随机放大
对图片进行随机的放大。

8、颜色抖动
改变图片的颜色,通过对颜色通道的数值偏移,改变图片的整体的颜色。

9、rescale
rescale的作用是对图片的每个像素值均乘上这个放缩因子,这个操作在所有其它变换操作之前执行,在一些模型当中,直接输入原图的像素值可能会落入激活函数的饱和区,因此设置放缩因子为1/255,把像素值放缩到0和1之间有利于模型的收敛,避免神经元饱和。图片经过rescale之后,保存到本地的图片用肉眼看是没有任何区别的。

10、fill_mode
fill_mode为填充模式,如前面提到,当对图片进行平移、放缩、错切等操作时,图片中会出现一些缺失的地方,就由fill_mode中的参数确定。包括:“constant”、“nearest”(默认)、“reflect”和“wrap”。

通常来说我们不会只使用单一的数据增加方法,而是会多种方式结合使用

以上只是常用的几种图像数据增强方法,还有更好的其他方法,请结合自身项目。

引用:
https://mp.weixin.qq.com/s?__biz=MzUxOTgxMjkwNA==&mid=2247485619&idx=1&sn=d3a30397462861bf8b01c2570e9b8388&chksm=f9f2aaf4ce8523e25b7691bdb2e2e0526580f4c14ca307089017f21a3ff82232857039ac319d&mpshare=1&scene=1&srcid=11238ugMfOHeYBHXLTfT0llT&key=fe048f5ad4fa1bcf827d20099e0f30a24b151eaee46d0b492d027be2f0e420506744d70e6e8e97982b4cf9efdde30378cf048d45208189d545c91723f9cd1bd9a8a48a13e0a20c1a5bf72644e2bb575c&ascene=1&uin=MjE3OTYwMjg2Mw%3D%3D&devicetype=Windows+10&version=62060833&lang=zh_CN&pass_ticket=apm0Olp6oFmGwJatwtCpRNrEa36m9QcJSdkodK2aDwPRHUFGGRA79xznbiIxDOjZ

2018-09-23 10:19:50 feilong_csdn 阅读数 8227

本系列python版本:python2.7.15

本系列opencv-python版本:opencv-python3.4.2.17

本系列使用的开发环境是jupyter notebook,是一个python的交互式开发环境,测试十分方便,并集成了vim操作,安装教程可参考:windows上jupyter notebook主题背景、字体及扩展插件配置(集成vim环境)


前几篇分享多以数字图像基础知识为中心,本文分享一下在图像处理的项目中经常需要用到的,重要的图像预处理: 图像数据集增强。在实际项目中,我们经常会遇到数据集太小,数据量不够等问题,这直接导致了接下来的工作无法进行,本文便来唠一唠如何在拥有一部分图像数据的情况下扩充数据集的方式



一、数据集项目背景


本文数据集使用介绍: 数据集是基于英文手写体识别开发,因此本文图片数据集是含手写体英文的图片,标签数据是图片对应的正确的文本txt文件,因此对数据集的拓展包括两方面,一是英文手写体图片的拓展,一是英文手写体图片对应的文本txt文件的拓展,产生新数据集用于神经网络训练。展示个别图片数据如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


本文最后将提供python实现的图像数据集增强源码,功能:将图像数据集增强做成了开关形式,可以对以下图像数据集增强方式进行自动变换调节,各项之间也可累加:

  1. 旋转,旋转角度可调
  2. 缩放,分辨率可调
  3. 添加噪音,背景噪音程度可调
  4. 图像模糊,模糊程度可调
  5. 图像移动 将图像往x、y方向上按指定的数量移动图像像素
  6. 支持拓展其他新的图像数据集增强方式



二、数据集增强方法


1、图片缩放

图像缩放便是调节图片的分辨率,在【数字图像处理系列二】基本概念:亮度、对比度、饱和度、锐化、分辨率中详细介绍了图片分辨率调节,我们可以通过对图片分辨率做适当的调节,增强图像数据,同时应该增加对应的标签数据,便是图片对应的问题txt文件

利用opencv-python库resize()函数对图片分辨率进行调节,项目部分代码展示如下,可以将图像调节成任意分辨率,但在实际调节过程中,我们应保持在一定范围内,可根据实验反馈效果进行调整:

import re, cv2

CODE = 'scale'
REGEX = re.compile(r"^" + CODE + "_(?P<w_scale>[.0-9]+)_(?P<h_scale>[.0-9]+)")

class Scale:
    def __init__(self, w_scale, h_scale):
        self.code = CODE + str(w_scale) + '_' + str(h_scale)
        self.w_scale = w_scale
        self.h_scale = h_scale

    def process(self, img):
        height, width = img.shape[:2]
        return cv2.resize(img, (int(self.w_scale*width), int(self.h_scale*height)), interpolation = cv2.INTER_CUBIC)

    @staticmethod
    def match_code(code):
        match = REGEX.match(code)
        if match:
            d = match.groupdict()
            return Scale(float(d['w_scale']), float(d['h_scale']))

运行程序,将图像放大为原来的两倍效果如下:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



2、图片旋转

图像按照给定的角度旋转,这也是增强图像数据集一种常用的方式,使用opencv-python中getRotationMatrix2D()函数和warpAffine()函数,getRotationMatrix2D()函数定义如下:

cv2.getRotationMatrix2D(Point2f center, double angle, double scale)

参数含义:

  • center: (x_center,y_center) 图像中心像素坐标,也是旋转中心
  • angle: 定义图像旋转的角度
  • scale : 图像缩放因子,一般默认为1,不缩放

cv2.warpAffine()功能是做图像几何变换,函数定义如下:

cv2.warpAffine(img, M, (cols,rows))

参数含义:

  • img: 待变换的图像
  • M: 图像几何变换方式,自定义
  • (cols,rows): 输入图像的大小

核心代码展示:

def process(self, img):
    height, width = img.shape[:2]
    M = cv2.getRotationMatrix2D((width/2, height/2), self.angle, 1)
    return cv2.warpAffine(img, M, (width, height))

运行程序,将图像顺时针旋转两度效果如下:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



3、图片平移

图像平移指将图像往x、y方向上按指定的数量移动图像像素,也使用cv2.warpAffine()函数,自定义平移的方向和位移大小:

核心代码展示:

def process(self, img):
	height, width = img.shape[:2]
    trans_M = np.float32([[1, 0, self.x_trans], [0, 1, self.y_trans]])
    return cv2.warpAffine(img, trans_M, (width, height))

运行程序,将图像整体向右和下方向各移动10个像素位置效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述



4、图片模糊

图像模糊也是图像数据集增强的一种方式,图像模糊内容将在图像滤波中详细介绍,模糊技术很多,本文采用最常见的图像高斯模糊,使用的是opencv-python中cv2.GaussianBlur()函数,函数定义如下:

cv2.GaussianBlur(img, kernel, sigma)

参数含义:

  • img: 待处理图形
  • kernel: 高斯核,是正奇数,如(5,5)
  • sigma: 指定x/y方向标准差,控制模糊的程度,数值越大模糊度也高

核心代码展示如下:

def process(self, img):
    return cv2.GaussianBlur(img, (5,5), self.sigma)

运行程序,将用高斯核为(5,5),标准差=4时效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述



5、图片添加噪音

为图像添加噪音也是一种图像数据集增强方式,可以添加多种类型噪音,如椒盐噪音、高斯噪音,本例中添加常见的高斯噪音,使用skimage.util.random_noise()函数,定义如下:

skimage.util.random_noise(gray_img, mode, seed=None, clip=True, kwargs)

参数含义:
gray_img: 待处理图像灰度图
mode: str类型,添加噪音类型
seed: int类型,添加噪音随机性
clip: 为True时应用剪切,输入和输入大小相同
mean:噪音随机分布的均值
var:噪音随机分布的方差

核心代码展示:

def process(self, img):
    return random_noise(img, mode='gaussian', var=self.var)

运行程序,给图片添加方差为0.05效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述




三、源代码获取


源码和训练数据集获取请关注小编微信公众号并回复 图像增强源码 获取源码,回复手写体识别数据集 获取数据集,公众号:

在这里插入图片描述

2018-09-26 05:59:07 weixin_34378767 阅读数 1127
摘要: 还在为数据集大小发愁吗?试试数据增强方法吧。

在图像分类任务中,图像数据增强一般是大多数人会采用的方法之一,这是由于深度学习对数据集的大小有一定的要求,若原始的数据集比较小,无法很好地满足网络模型的训练,从而影响模型的性能,而图像增强是对原始图像进行一定的处理以扩充数据集,能够在一定程度上提升模型的性能。本文是我目前正在研究一项内容,总结图像数据增强的一些方法及其有效性。本研究的目的是学习如何增加训练数据集的大小,通过有限或少量数据来训练获得具有鲁棒性的卷积网络模型。

这项研究要求列出我们可以想到的所有图像增强方法,并列举出所有这些组合,以尝试和改善图像分类模型的性能。那么,能够想到的一些最简单的增强方法有翻转、平移、旋转、缩放,分离单个r、g、b三个颜色通道以及添加噪声。更激动人心的增强方法是比较热门的使用生成对抗网络模型,有时交替使用遗传算法和生成对抗网络。此外,还提出了一些创造性方法,例如将类似于Instagram中的高亮滤镜应用于图像、应用随机区域锐化滤镜,以及基于聚类技术添加平均图像等。本文将展示如何使用NumPy对图像进行扩充。

下面是上述提到的增强技术的总结及说明,如果你能想到其它任何方法来增强图像,并可以提高图像分类器的性能,请在留言区评论。

clipboard.png

原始图像

增强

所有的数据增强都是在没有OpenCV库的情况下,使用Numpy完成。

clipboard.png

翻转|Flipping

对图像进行翻转是最流行的图像数据增强方法之一。这主要是由于翻转图像操作的代码简单,以及对于大多数问题而言,对图像进行翻转操作能够提升模型的性能。下面的模型可以被认为是看到左鞋而不是右鞋,因此通过这种数据增加,模型对于看到鞋的潜在变化会变得更加鲁棒。

clipboard.png

clipboard.png

平移|Translations

很容易想象对完成检测任务的分类器进行平移增强能够提升其性能,好像这个分类模型试图检测鞋子何时在图像中而不是是否在图像中。这些平移操作将有助于它在无法看清整个鞋子的情况下认出鞋子来。

clipboard.png

左移

clipboard.png

clipboard.png

右移

clipboard.png

clipboard.png

上移

clipboard.png

clipboard.png

下移

clipboard.png

加噪|Noise

对图像加噪音是一种有趣的图像增强技术,现在我开始对这类操作变得更加熟悉。我已经看过很多关于对抗网络训练的有趣论文,当将一些噪音加入到图像后,模型无法对图像进行正确分类。我仍然在寻找能产生比下图更好的加噪方法。添加噪声可能有助于使得畸变更加明显,并使得模型更加鲁棒。

clipboard.png

加噪

clipboard.png

生成对抗网络|GAN:

我阅读了很多关于生成对抗网络的文献,文献中很多都使用生成对抗网络进行数据增强,我对此也比较感兴趣,下面是我使用MNIST数据集生成的一些图像。

clipboard.png

GAN生成图像

正如我们从上图中看到的,它们确实看起来像数字3、7和9,但实际上,将其送进数字手写体分类器中,它们并不能被识别为对应的数字。

感谢你阅读本文,希望你现在知道如何实现对基本数据进行扩充,以改进自己搭建的分类模型!

本文作者:【方向】

阅读原文

本文为云栖社区原创内容,未经允许不得转载。

2018-09-13 20:41:57 weixin_41774576 阅读数 2691

**图像数据增强方法概述**

图像数据准备对神经网络与卷积神经网络模型训练有重要影响,当样本空间不够或者样本数量不足的时候会严重影响训练或者导致训练出来的模型泛化程度不够,识别率与准确率不高!本文将会带你学会如何对已有的图像数据进行数据增强,获取样本的多样性与数据的多样性从而为训练模型打下良好基础。通读全文你将get到如何几个技能:

1.使用标准化对图像进行图像增强 深度学习训练-详解图像数据标准化与归一化

2.使用几何变换(平移、翻转、旋转)对图像进行数据增强

3.使用随机调整亮度对图像进行增强

4.使用随机调整对比度对图像进行增强

5.添加高斯噪声和椒盐噪声

6.对图像进行仿射变换

opencv2各模块功能
opencv_core:包含核心功能,尤其是底层数据结构和算法函数
opencv_imgproc : 包含图像处理函数
opencv_highgui : 包含读写图像及视频函数,以及操作图形用户界面函数
opencv_features2d : 包含兴趣点检测子,描述子和兴趣点匹配框架
opencv_calib3d : 包含相机标定,双目几何估算以及立体视觉函数
opencv_video : 包含运动估算,特征跟踪以及前景提取函数
opencv_objdetect : 包括物体检测函数,如面部识别

一、加椒盐噪声

图像模拟添加椒盐噪声是通过随机获取像素点并设置为高亮度点和低灰度点来实现的

图像添加椒盐噪声的程序如下:

//利用程序给原图像增加椒盐噪声
//图象模拟添加椒盐噪声是通过随机获取像素点斌那个设置为高亮度点来实现的
 
#include <cstdlib>
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
 
using namespace cv;
using namespace std;
 
Mat addSaltNoise(const Mat srcImage, int n);
 
 
int main()
{
	Mat srcImage = imread("2345.jpg");
	if (!srcImage.data)
	{
		cout << "读入图像有误!" << endl;
		system("pause");
		return -1;
	}
	imshow("原图像", srcImage);
	Mat dstImage = addSaltNoise(srcImage, 3000);
	imshow("添加椒盐噪声的图像", dstImage);
	//存储图像
	imwrite("salt_pepper_Image.jpg", dstImage);
	waitKey();
	return 0;
}
 
Mat addSaltNoise(const Mat srcImage, int n)
{
	Mat dstImage = srcImage.clone();
	for (int k = 0; k < n; k++)
	{
		//随机取值行列
		int i = rand() % dstImage.rows;
		int j = rand() % dstImage.cols;
		//图像通道判定
		if (dstImage.channels() == 1)
		{
			dstImage.at<uchar>(i, j) = 255;		//盐噪声
		}
		else
		{
			dstImage.at<Vec3b>(i, j)[0] = 255;
			dstImage.at<Vec3b>(i, j)[1] = 255;
			dstImage.at<Vec3b>(i, j)[2] = 255;
		}
	}
	for (int k = 0; k < n; k++)
	{
		//随机取值行列
		int i = rand() % dstImage.rows;
		int j = rand() % dstImage.cols;
		//图像通道判定
		if (dstImage.channels() == 1)
		{
			dstImage.at<uchar>(i, j) = 0;		//椒噪声
		}
		else
		{
			dstImage.at<Vec3b>(i, j)[0] = 0;
			dstImage.at<Vec3b>(i, j)[1] = 0;
			dstImage.at<Vec3b>(i, j)[2] = 0;
		}
	}
	return dstImage;
}

二、添加高斯噪声

高斯噪声是指图像概率密度函数服从高斯分布的一类噪声。

根据Box-Muller变换原理,建设随机变量U1、U2来自独立的处于(0,1)之间的均匀分布,则经过下面两个式子产生的随机变量Z0,Z1服从标准高斯分布。
这里写图片描述

上式中Z0,Z1满足正态分布,其中均值为0,方差为1,变量U1和U2可以修改为下式:

这里写图片描述

给图像添加高斯噪声的程序如下:


//给图像添加高斯噪声
#include <cmath>
#include <limits>
#include <cstdlib>
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
 
using namespace cv;
using namespace std;
 
double generateGaussianNoise(double m, double sigma);
Mat addGaussianNoise(Mat &srcImag);
 
int main()
{
	Mat srcImage = imread("2345.jpg");
	if (!srcImage.data)
	{
		cout << "读入图片错误!" << endl;
		system("pause");
		return -1;
	}
	imshow("原图像", srcImage);
	Mat dstImage = addGaussianNoise(srcImage);
	imshow("添加高斯噪声后的图像", dstImage);
	waitKey();
	return 0;
}
 
//生成高斯噪声
double generateGaussianNoise(double mu, double sigma)
{
	//定义小值
	const double epsilon = numeric_limits<double>::min();
	static double z0, z1;
	static bool flag = false;
	flag = !flag;
	//flag为假构造高斯随机变量X
	if (!flag)
		return z1 * sigma + mu;
	double u1, u2;
	//构造随机变量
	do
	{
		u1 = rand() * (1.0 / RAND_MAX);
		u2 = rand() * (1.0 / RAND_MAX);
	} while (u1 <= epsilon);
	//flag为真构造高斯随机变量
	z0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI*u2);
	z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI*u2);
	return z0*sigma + mu;
}
 
//为图像添加高斯噪声
Mat addGaussianNoise(Mat &srcImag)
{
	Mat dstImage = srcImag.clone();
	int channels = dstImage.channels();
	int rowsNumber = dstImage.rows;
	int colsNumber = dstImage.cols*channels;
	//判断图像的连续性
	if (dstImage.isContinuous())
	{
		colsNumber *= rowsNumber;
		rowsNumber = 1;
	}
	for (int i = 0; i < rowsNumber; i++)
	{
		for (int j = 0; j < colsNumber; j++)
		{
			//添加高斯噪声
			int val = dstImage.ptr<uchar>(i)[j] +
				generateGaussianNoise(2, 0.8) * 32;
			if (val < 0)
				val = 0;
			if (val>255)
				val = 255;
			dstImage.ptr<uchar>(i)[j] = (uchar)val;
		}
	}
	return dstImage;
}

图像增强方法

阅读数 1726