2018-04-11 00:35:51 qq_36969386 阅读数 370
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2623 人正在学习 去看看 贾志刚

    课上作业要求利用C里面的自带类库对图像做一个高斯噪声的生成,记录一下大概的原理和步骤。


    首先是对高斯函数的理解

   

    这个函数是一个高斯概率密度的分布表达式,表示为X~N(μ,σ²),其中μ表示均值,σ²表示方差,当μ=0,σ²=1时为标准正态分布。

    而高斯噪声是要求生成的噪声的概率密度函数符合高斯分布。我觉得可以理解为所有的噪声采样服从高斯分布的一种噪声。有关高斯噪声和高斯白噪声的理解参考

   hudalikm的一篇有关高斯噪声的文章文章

    高斯噪声的生成就是在图像所有像素上添加一个噪声信号:

        n(x,y)=o(x,y)+g(x,y)

    其关键是如何生成这个g(x,y)。当然x和y只是表示图像像素的坐标,对原像素值加上一个高斯采样值就可以生成一个高斯噪声。计算机中生成高斯采样的方法有很多,这里我使用的是比较常用的Box-Muller方法。该方法原理涉及到统计学的各种问题(反正我看一遍没太看懂),但实现过程非常简单。

    原理的话在白马负金羁的文章中有介绍

    使用方法是首先生成两个数a,b为在[0,1]的均匀分布随机采样;

    根据box-muller方法,对a,b做如下运算可以得到服从高斯分布的两个随机数

    使用任何一个都可以,我觉得这是二维的高斯采样,然后咱们在这里只需要选择任何一维都可以。

    最终生成的噪声点为

    n(x,y)=o(x,y)+(μ+N*σ);

    

接下来是利用CImage对图像进行处理阶段了


关于如何使用Cimage类的介绍,这里我参考了self_mind 的关于Cimage类的介绍 里面介绍的很详细。

下面我放上我的代码和效果图

宏定义和main函数部分

#include <atlimage.h>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define MU 0			//均值
#define SIGMA 2			//方差
#define k 16
#define PI 3.1415926

using namespace std;
int addNoise(const CImage& input, CImage& noise);
double guass();
int makeNoise(CImage input);
int addNoise(const CImage& input, CImage& noise);
int main() {
	CString ImagePath = "E:\\1myRobotFile\\公式算法项目\\CameraCalibration\\input.jpg";
	CImage image, noise;
	//读入图片
	image.Load(ImagePath);
	makeNoise(image);

	cout << "successd" << endl;
	system("pause");

}
接下来是高斯噪声生成函数
double guass()
{
	//生成0-1的随机数
	double x1, x2;
	//生成0-1两个随机数
	x1 = rand() / ((double)RAND_MAX);
	x2 = rand() / ((double)RAND_MAX);
	if (x1 < 1e-100)
		x1 = 1e-100;
	x1 = (-2) * log(x1);
	x2 = x2 * PI * 2;
	double g = MU + (sqrt(x1) * cos(x2)) * SIGMA;

	//double g = MU + (sqrt(x1) * sin(x2)) * SIGMA;

	return g;
}

最后是输出高斯噪声模版和高斯噪声叠加图像

int makeNoise(CImage input)
{
	if (input == 0)
	{
		cout << "图片输入错误!" << endl;
		return 0;
	}

	//噪声图片的创建
	CImage gaussNoise, In;
	CString ImagePath = "E:\\1myRobotFile\\公式算法项目\\CameraCalibration\\input.jpg";
	In.Load(ImagePath);
	gaussNoise = input;
	//gaussNoise.Create(input.GetWidth(), input.GetHeight(), 8);
	//高斯噪音生成
	int r, g, b;
	for (int i = 0; i<gaussNoise.GetWidth(); i++)
	{
		for (int j = 0; j<gaussNoise.GetHeight(); j++)
		{
			r = guass();
			g = guass();
			b = guass();
			gaussNoise.SetPixelRGB(i, j, r, g, b);

		}
	}
	CString SImagePath = "E:\\1myRobotFile\\公式算法项目\\CameraCalibration\\noise.jpg";
	gaussNoise.Save(SImagePath);
	addNoise(In, gaussNoise);
}
//噪声和原图的相加
int addNoise(const CImage& input, CImage& noise)
{
	CImage addnoise;
	COLORREF pixel1;
	COLORREF pixel2;
	int r, g, b;
	if (input == 0 || noise == 0)
	{
		cout << "图片输入错误!" << endl;
		return 0;
	}
	addnoise = input;
	int w = addnoise.GetWidth();
	int h = addnoise.GetHeight();
	for (int i = 0; i < w; i++)
	{
		for (int j = 0; j<h; j++)
		{
			pixel1 = input.GetPixel(i, j);
			pixel2 = noise.GetPixel(i, j);
			/*r = GetRValue(pixel1);
			g = GetGValue(pixel1);
			b = GetBValue(pixel1);
			cout << r << "," << g << "," << b << endl;*/
			//r = GetRValue(pixel1) + GetRValue(pixel2) - 128;
			//g = GetGValue(pixel1) + GetGValue(pixel2) - 128;
			//b = GetBValue(pixel1) + GetBValue(pixel2) - 128;
			r = GetRValue(pixel1) + GetRValue(pixel2) *k;
			g = GetGValue(pixel1) + GetGValue(pixel2) *k;
			b = GetBValue(pixel1) + GetBValue(pixel2) *k;

			//cout << r << "," << g << "," << b << endl; 
			if (r>255)
			{
				r = 255;
			}
			if (g>255)
			{
				g = 255;
			}
			if (b>255)
			{
				b = 255;
			}
			if (r<0)
			{
				r = 0;

			}
			if (g<0)
			{
				g = 0;
			}
			if (b<0)
			{
				b = 0;
			}
			addnoise.SetPixelRGB(i, j, r, g, b);
		}
	}
	CString SImagePath = "E:\\1myRobotFile\\公式算法项目\\CameraCalibration\\output.jpg";
	addnoise.Save(SImagePath);

}

效果图如下

原图


噪声图像(μ=0,σ=2)

带有高斯噪声的图像

2019-11-04 20:34:42 qq_36511401 阅读数 4323
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2623 人正在学习 去看看 贾志刚

一、介绍

1、一维高斯滤波。

         \LARGE f(x)=\frac{1}{\sqrt{2\pi }\sigma }e^\frac{-(x-u)^2}{2\sigma^2 }

    a表示得到曲线的高度,u是指曲线在x轴的中心, σ指width(与半峰全宽有关,即平方差)。

2、二维高斯滤波。

        \LARGE f(x,y)=\frac{1}{2\pi \sigma ^2}e^\frac{-(x^2+y^2)}{2\sigma ^2}

二、二维高斯滤波模版

1、生成维高斯滤波模版。

public class MathUtils {
    /**
     * 获取高斯滤波模版的二维数组
     *
     * @param length 模版长度,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     * @param sigma  模版标准差,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     */
    public static double[][] getGaussTemplate(int length, double sigma) {
        double[][] gaussTemplate = new double[length][length];    // 用于存储结果
        int centerIndex = (length - 1) / 2;//模版的中心点
        double variance = sigma * sigma;//方差
        double sum = 0;
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                int xLength = j - centerIndex;//x上的距离
                int yLength = i - centerIndex;//y上的距离
                double e = Math.exp(-(xLength * xLength + yLength * yLength) / (2 * variance));
                gaussTemplate[i][j] = e / (2 * Math.PI * variance);
                sum += gaussTemplate[i][j];
            }
        }
        //占得比重
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                gaussTemplate[i][j] = gaussTemplate[i][j] / sum;
            }
        }
        //打印模版
        System.out.println(String.format("生成大小为%d,标准差为%.3f的二维高斯模版:", length, sigma));
        for (double[] doubles : gaussTemplate) {
            for (int j = 0; j < gaussTemplate.length; j++) {
                System.out.print(String.format("%8.3f", doubles[j]));
            }
            System.out.println();
        }
        return gaussTemplate;
    }
}
public static void main(String[] args) {
        //高斯滤波的模版,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
        double[][] gaussTemplate1 = FilterUtils.getGaussTemplate(3, 1.5);
        double[][] gaussTemplate2 = FilterUtils.getGaussTemplate(3, 0.75);
        double[][] gaussTemplate3 = FilterUtils.getGaussTemplate(3, 0.5);
        double[][] gaussTemplate4 = FilterUtils.getGaussTemplate(5, 2.5);
        double[][] gaussTemplate5 = FilterUtils.getGaussTemplate(5, 1.25);
        double[][] gaussTemplate6 = FilterUtils.getGaussTemplate(5, 0.833);
        double[][] gaussTemplate7 = FilterUtils.getGaussTemplate(7, 3.5);
        double[][] gaussTemplate8 = FilterUtils.getGaussTemplate(7, 1.75);
        double[][] gaussTemplate9 = FilterUtils.getGaussTemplate(7, 1.167);
    }

2、日志打印的结果。

        生成大小为3,标准差为1.500的二维高斯模版:
           0.095   0.118   0.095
           0.118   0.148   0.118
           0.095   0.118   0.095
        生成大小为3,标准差为0.750的二维高斯模版:
           0.051   0.124   0.051
           0.124   0.301   0.124
           0.051   0.124   0.051
        生成大小为3,标准差为0.500的二维高斯模版:
           0.011   0.084   0.011
           0.084   0.619   0.084
           0.011   0.084   0.011
        生成大小为5,标准差为2.500的二维高斯模版:
           0.029   0.036   0.039   0.036   0.029
           0.036   0.046   0.050   0.046   0.036
           0.039   0.050   0.054   0.050   0.039
           0.036   0.046   0.050   0.046   0.036
           0.029   0.036   0.039   0.036   0.029
        生成大小为5,标准差为1.250的二维高斯模版:
           0.009   0.022   0.031   0.022   0.009
           0.022   0.058   0.080   0.058   0.022
           0.031   0.080   0.110   0.080   0.031
           0.022   0.058   0.080   0.058   0.022
           0.009   0.022   0.031   0.022   0.009
        生成大小为5,标准差为0.833的二维高斯模版:
           0.001   0.006   0.013   0.006   0.001
           0.006   0.054   0.112   0.054   0.006
           0.013   0.112   0.230   0.112   0.013
           0.006   0.054   0.112   0.054   0.006
           0.001   0.006   0.013   0.006   0.001
        生成大小为7,标准差为3.500的二维高斯模版:
           0.013   0.016   0.018   0.019   0.018   0.016   0.013
           0.016   0.020   0.023   0.024   0.023   0.020   0.016
           0.018   0.023   0.026   0.027   0.026   0.023   0.018
           0.019   0.024   0.027   0.028   0.027   0.024   0.019
           0.018   0.023   0.026   0.027   0.026   0.023   0.018
           0.016   0.020   0.023   0.024   0.023   0.020   0.016
           0.013   0.016   0.018   0.019   0.018   0.016   0.013
        生成大小为7,标准差为1.750的二维高斯模版:
           0.003   0.007   0.011   0.013   0.011   0.007   0.003
           0.007   0.015   0.025   0.030   0.025   0.015   0.007
           0.011   0.025   0.041   0.048   0.041   0.025   0.011
           0.013   0.030   0.048   0.057   0.048   0.030   0.013
           0.011   0.025   0.041   0.048   0.041   0.025   0.011
           0.007   0.015   0.025   0.030   0.025   0.015   0.007
           0.003   0.007   0.011   0.013   0.011   0.007   0.003
        生成大小为7,标准差为1.167的二维高斯模版:
           0.000   0.001   0.003   0.004   0.003   0.001   0.000
           0.001   0.006   0.019   0.027   0.019   0.006   0.001
           0.003   0.019   0.056   0.081   0.056   0.019   0.003
           0.004   0.027   0.081   0.117   0.081   0.027   0.004
           0.003   0.019   0.056   0.081   0.056   0.019   0.003
           0.001   0.006   0.019   0.027   0.019   0.006   0.001
           0.000   0.001   0.003   0.004   0.003   0.001   0.000

3、结论。

        方差越大模版大小越大,各点和中心点的差距越大。并且模版长度length和标准差sigma之间的关系:length=6sigma(%99.74)、length=4sigma(%95)、length=2sigma(%68)。其中括号中的百分比指的是高斯模版中的数据占全部数据的百分之多少。

三、高斯滤波(带权值的均值滤波)

1、原图。高斯滤波只是在计算平均值的时候,根据距离的远近,带有权值而已。

2、代码。生成4张图片,高斯模版大小和方差分别是:(3、1)、(3、0.5)、(5、1)、(5、0.5)。

package com.zxj.reptile.test.mnist;

import com.zxj.reptile.utils.image.ImageService;
import com.zxj.reptile.utils.image.ImageUtils;

public class ImgTest {

    private static final String File_Path = "G:\\xiaojie-java-test\\img\\";

    public static void main(String[] args) {
        //高斯过滤
        String gaussSourcePath = File_Path + "滤波\\高斯滤波\\高斯噪声.jpg";
        String gaussTargetPath = File_Path + "滤波\\高斯滤波\\高斯滤波_";
        //高斯过滤 length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
        gaussFilter(sourcePath, targetPath + "3_6sigma.jpg", 3, 1.5);
        gaussFilter(sourcePath, targetPath + "3_4sigma.jpg", 3, 0.75);
        gaussFilter(sourcePath, targetPath + "3_2sigma.jpg", 3, 0.5);
        gaussFilter(sourcePath, targetPath + "5_6sigma.jpg", 5, 2.5);
        gaussFilter(sourcePath, targetPath + "5_4sigma.jpg", 5, 1.25);
        gaussFilter(sourcePath, targetPath + "5_2sigma.jpg", 5, 0.833);
        gaussFilter(sourcePath, targetPath + "7_6sigma.jpg", 7, 3.5);
        gaussFilter(sourcePath, targetPath + "7_4sigma.jpg", 7, 1.75);
        gaussFilter(sourcePath, targetPath + "7_2sigma.jpg", 7, 1.167);
    }
}
package com.zxj.reptile.utils.image;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class ImageService {
    /**
     * 高斯过滤(加权的均值过滤)
     *
     * @param sourcePath 原图像
     * @param targetPath 目标图像
     * @param grayType   灰度化方式
     * @param length     模版长度,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     * @param sigma      模版标准差,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     */
    public static void gaussFilter(String sourcePath, String targetPath, int grayType, int length, double sigma) {
        try {
            //高斯模版
            double[][] gaussTemplate = ImageUtils.getGaussTemplate(length, sigma);
            //获取原图像对象,并获取原图像的二维数组
            BufferedImage image = ImageIO.read(new File(sourcePath));
            int[][] imgArrays = ImageUtils.getTwoDimension(image);
            //生成新图像的二维数组
            imgArrays = ImageUtils.getGrayImg(imgArrays, grayType);//灰度化
            int[][] newImgArrays = ImageUtils.getGaussFilter(imgArrays, gaussTemplate);//均值过滤
            //生成新图片对象,填充像素
            BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
            ImageUtils.setTwoDimension(newImage, newImgArrays, ImageUtils.Channel_Type_1);
            //生成图片文件
            ImageIO.write(newImage, "JPEG", new File(targetPath + size + "_" + variance + ".jpg"));
            Thread.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.zxj.reptile.utils.image;

import java.awt.image.BufferedImage;

public class ImageUtils {
    /**
     * 获取高斯滤波模版的二维数组
     *
     * @param length 模版长度,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     * @param sigma  模版标准差,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     */
    public static double[][] getGaussTemplate(int length, double sigma) {
        double[][] gaussTemplate = new double[length][length];    // 用于存储结果
        int centerIndex = (length - 1) / 2;//模版的中心点
        double variance = sigma * sigma;//方差
        double sum = 0;
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                int xLength = j - centerIndex;//x上的距离
                int yLength = i - centerIndex;//y上的距离
                double e = Math.exp(-(xLength * xLength + yLength * yLength) / (2 * variance));
                gaussTemplate[i][j] = e / (2 * Math.PI * variance);
                sum += gaussTemplate[i][j];
            }
        }
        //占得比重
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                gaussTemplate[i][j] = gaussTemplate[i][j] / sum;
            }
        }
//        //打印模版
//        System.out.println(String.format("生成大小为%d,标准差为%.3f的二维高斯模版:", length, sigma));
//        for (double[] doubles : gaussTemplate) {
//            for (int j = 0; j < gaussTemplate.length; j++) {
//                System.out.print(String.format("%8.3f", doubles[j]));
//            }
//            System.out.println();
//        }
        return gaussTemplate;
    }

    /**
     * 高斯滤波
     *
     * @param imgArrays     图像二维数组
     * @param gaussTemplate 高斯滤波模版的二维数组
     */
    public static int[][] getGaussFilter(int[][] imgArrays, double[][] gaussTemplate) {
        final int imgHeight = imgArrays.length;
        final int imgWidth = imgArrays[0].length;
        int[][] newImgArrays = new int[imgHeight][imgWidth];
        //模版长度和半径
        final int filterLength = gaussTemplate.length;
        final int filterRadius = (filterLength - 1) / 2;
        //高斯过滤
        for (int h = 0; h < imgHeight; h++) {//图片第几行
            for (int w = 0; w < imgWidth; w++) {//图片第几列
                double weightTotal = 0;
                double sum = 0;
                for (int templateH = -filterRadius; templateH <= filterRadius; templateH++) {//模版第几行
                    int rowIndex = h + templateH;
                    if (rowIndex < 0 || rowIndex > imgHeight - 1) {
                        continue;
                    }
                    for (int templateW = -filterRadius; templateW < filterRadius; templateW++) {//模版第几列
                        int columnIndex = w + templateW;
                        if (columnIndex < 0 || columnIndex > imgWidth - 1) {
                            continue;
                        }
                        double weight = gaussTemplate[templateH + filterRadius][templateW + filterRadius];
                        sum += (imgArrays[rowIndex][columnIndex] * weight);
                        weightTotal += weight;
                    }
                }
                newImgArrays[h][w] = (int) (sum / weightTotal);
            }
        }
        return newImgArrays;
    }

    
    //灰度处理的方法
    public static final byte Gray_Type_Default = 0;//默认加权法
    public static final byte Gray_Type_Min = 1;//最大值法
    public static final byte Gray_Type_Max = 2;//最小值法
    public static final byte Gray_Type_Average = 3;//平均值法
    public static final byte Gray_Type_Weight = 4;//加权法
    public static final byte Gray_Type_Red = 5;//红色值法
    public static final byte Gray_Type_Green = 6;//绿色值法
    public static final byte Gray_Type_Blue = 7;//蓝色值法

    //生成的图片是几通道的
    public static final byte Channel_Type_Default = 0;//默认三通道
    public static final byte Channel_Type_1 = 1;//单通道
    public static final byte Channel_Type_3 = 3;//三通道

    /**
     * 灰度化处理
     *
     * @param imgArrays 图像二维数组
     * @param grayType  灰度化方法
     */
    public static int[][] getGrayImg(int[][] imgArrays, int grayType) throws Exception {
        final int imgHeight = imgArrays.length;
        final int imgWidth = imgArrays[0].length;
        int[][] newImgArrays = new int[imgHeight][imgWidth];
        for (int h = 0; h < imgHeight; h++) {
            for (int w = 0; w < imgWidth; w++) {
                final int[] grb = getRgb(imgArrays[h][w]);
                newImgArrays[h][w] = getGray(grb, grayType);
            }
        }
        return newImgArrays;
    }

    /**
     * 通过像素值,返回r、g、b颜色通道的值
     *
     * @param pixel 像素值
     */
    public static int[] getRgb(int pixel) {
        int[] rgb = new int[3];
        rgb[0] = (pixel >> 16) & 0xff;
        rgb[1] = (pixel >> 8) & 0xff;
        rgb[2] = pixel & 0xff;
        return rgb;
    }

    /**
     * 根据不同的灰度化方法,返回灰度值
     *
     * @param rgb      r、g、b颜色通道的值
     * @param grayType 不同灰度处理的方法
     */
    public static int getGray(int[] rgb, int grayType) throws Exception {
        if (grayType == Gray_Type_Average) {
            return (rgb[0] + rgb[1] + rgb[2]) / 3;   //rgb之和除以3
        } else if (grayType == Gray_Type_Weight || grayType == Gray_Type_Default) {
            return (int) (0.3 * rgb[0] + 0.59 * rgb[1] + 0.11 * rgb[2]);
        } else if (grayType == Gray_Type_Red) {
            return rgb[0];//取红色值
        } else if (grayType == Gray_Type_Green) {
            return rgb[1];//取绿色值
        } else if (grayType == Gray_Type_Blue) {
            return rgb[2];//取蓝色值
        }
        //比较三个数的大小
        int gray = rgb[0];
        for (int i = 1; i < rgb.length; i++) {
            if (grayType == Gray_Type_Min) {
                if (gray > rgb[i]) {
                    gray = rgb[i];//取最小值
                }
            } else if (grayType == Gray_Type_Max) {
                if (gray < rgb[i]) {
                    gray = rgb[i];//取最大值
                }
            } else {
                throw new Exception("grayType出错");
            }
        }
        return gray;
    }

    /**
     * 获取二维像素
     *
     * @param image BufferedImage图像对象
     */
    public static int[][] getTwoDimension(BufferedImage image) {
        final int imgWidth = image.getWidth();
        final int imgHeight = image.getHeight();
        int[][] imgArrays = new int[imgHeight][imgWidth];
        for (int i = 0; i < imgHeight; i++) {
            for (int j = 0; j < imgWidth; j++) {
                imgArrays[i][j] = image.getRGB(j, i);
            }
        }
        return imgArrays;
    }

    /**
     * 将二维像素填充到图像中
     *
     * @param image       BufferedImage图像对象
     * @param imgArrays   二维像素
     * @param channelType 单通道还是三通道
     */
    public static void setTwoDimension(BufferedImage image, int[][] imgArrays, int channelType) throws Exception {
        final int imgWidth = image.getWidth();
        final int imgHeight = image.getHeight();
        for (int i = 0; i < imgHeight; i++) {
            for (int j = 0; j < imgWidth; j++) {
                if (channelType == Channel_Type_1) {
                    image.setRGB(j, i, (byte) imgArrays[i][j]);
                } else if (channelType == Channel_Type_3 || channelType == Channel_Type_Default) {
                    image.setRGB(j, i, imgArrays[i][j]);
                } else {
                    throw new Exception("channelType错误");
                }
            }
        }
    }
}

3、结果。可以跟没有权重的均值滤波进行对比,发现高斯滤波(带有权值的均值滤波)在细节上的保留效果来的更加的好些。

2016-07-31 17:27:14 Aoulun 阅读数 5690
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2623 人正在学习 去看看 贾志刚

之前有做过在图像上加高斯噪声的实验,在模拟生成随机数,以及产生高斯分布噪声时,受到了一些干扰。尤其是和高斯模糊相混淆。对于初学者来说,这些虽然是一些基本的图像处理知识,但是,眼高手低是很要不得的。只有积累足够了,才能游刃有余。因为我也是新手,希望不断的积累。

在网上有很多介绍高斯噪声的,有的是抄的,有的很随意的罗列一点公式,有的没有说明怎么做,这一点很烦。因为综述性的东西一搜一大堆,没必要再搞了。这就不是搞知识了。知识要让别人易懂,而不是搞的很玄乎,显得自己很有水平。相反,我觉得,把问题说明白了,才能让别人懂。尤其是对于程序员来说,不可能还要仔细推理,揣摩你的意思。

 

高斯模糊

高斯模糊实际上就和均值处理,中值处理相似。就是先产生一个高斯核,用这个高斯核模板去滑动处理图像的每个像素就行了。一个典型的二维高斯核模板是:

[1/16 1/8 1/16; 1/8 1/4 1/8; 1/16 1/8 1/16 ]

这个是3*3的模板。大致给个公式说明一下怎么模糊:

F(x,y)= 1/16 * f(x-1,y-1) + 1/8 * f(x-1,y) + 1/16*f(x-1,y+1) +

   1/8 * f(x,y-1) + 1/4 * f(x,y) + 1/8*f(x,y+1)  +

 1/16 * f(x+1,y-1) + 1/8 * f(x+1,y) + 1/16*f(x+1,y+1) 

F(x,y)是新生成图像在(x,y)位置的灰度值,f(x-1,y-1) 到f(x+1,y+1)是以(x,y)为中心的图像灰度值。

高斯噪声

高斯噪声和高斯模糊是很不一样的。假设一幅图像 I图像中每个像素的灰度值为I(x, y). 对图像加高斯噪声实际上就是对图像的灰度值操作。加性高斯噪声的数学公式为:

 

G(x,y) = f(x,y)  + n(x,y);

 

关键的问题是如何产生这个n(x,y)。高斯分布概率密度的数学表达式为:

 

F(x;\mu,\sigma)=\frac{1}{\sigma\sqrt{2\pi}}\int_{-\infty}^x \exp \left( -\frac{(x - \mu)^2}{2\sigma^2}\ \right)\, dx.

 

至于这个详细的解释就不说了。通过整理,大致说一下怎么生成这个n(x,y)。这个生成的方法跟上面的公式在表面上相差比较大。

具体步骤:(均值为m,方差为σ)

1).首先生成两个随机数a 和 b,大致公式为:

 

    Xi = (X(i-1) *A + C)%M

 

X(i-1)是前一个值,A,C,M是常数。可以用系统时间来得到这个X(i-1)=YY/MM/DD, 然后取小数点后第一位。可以根据需要自己定算法。反正都是伪随机。

 

2) 根据box-muller算法得到下面的具有高斯分布性质的两个数:

N = sqrt(-2*ln(a)) cos(2*PI*b) 

或者 

N = sqrt(-2*ln(a)) sin(2*PI*b) 

 

3) 图像加噪声:

F(x,y) = f(x,y) + (m + N * σ)

 

代码什么的就不贴了,很简单的。至于具体随机数怎么生成,可以再看看其他博客。这个只是一个参考。毕竟真正的随机数是很难搞的。

欢迎关注公众号

 

 

2019-11-10 20:14:57 caimouse 阅读数 156
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2623 人正在学习 去看看 贾志刚

在进行平滑滤波中,经常要测试滤波的算法是否有作用,比如模拟现实中出现一些高斯噪声,要怎么样对图像进行处理,才能达到这个目的呢?下面就来解决这个问题,这里使用np.random.normal函数来生成高斯噪声,然后再添加到归一化的图像里,最后再转换为255的灰度值进行显示。

这个例子的代码如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt

def mat2gray(img):
    A = np.double(img)
    out = np.zeros(A.shape, np.double)
    normalized = cv2.normalize(A, out, 1.0, 0.0, cv2.NORM_MINMAX)
    return out

#添加噪声到图像
def random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs):
    image = mat2gray(image)
    
    mode = mode.lower()
    if image.min() < 0:
        low_clip = -1
    else:
        low_clip = 0
    if seed is not None:
        np.random.seed(seed=seed)
        
    if mode == 'gaussian':
        noise = np.random.normal(kwargs['mean'], kwargs['var'] ** 0.5,
                                 image.shape)        
        out = image  + noise
    if clip:        
        out = np.clip(out, low_clip, 1.0)
        
    return out
#读取图片
img = cv2.imread('szu1.png',0)
#添加高斯噪声
img1 = random_noise(img,'gaussian', mean=0.1,var=0.01)
img1 = np.uint8(img1*255)
#
cv2.imshow('img', img)
cv2.imshow('img1', img1)

#
cv2.waitKey(0)
cv2.destroyAllWindows()
 

结果输出如下:

左边是原图,右边是加入高斯噪声

 

 

玩转人工智能库-深入浅出OpenCV
https://edu.csdn.net/course/detail/26616

 

Python游戏开发入门

http://edu.csdn.net/course/detail/5690
 

你也能动手修改C编译器

http://edu.csdn.net/course/detail/5582

 

2019-05-25 09:35:48 tuoshao123 阅读数 358
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2623 人正在学习 去看看 贾志刚

数字图像处理---高斯噪声

import cv2 as cv
import numpy as num
import random
#彩色图像读取
NoiseImg=cv.imread("H:\\tupian\\image\\logo.png",1)
#展示原图进行对比
cv.imshow("origin",NoiseImg)
#列表存取图像长、宽
size=NoiseImg.shape
#索引每一个像素点
for i in range(size[0]):
      for j in range(size[1]):
            for k in range(3):
                  #为每一个像素点加上随机高斯噪声
                  NoiseImg[i,j,k]=NoiseImg[i,j,k]+random.gauss(0,10)
                  #对像素进行限界处理
                  if NoiseImg[i,j,k]<0:
                        NoiseImg[i,j,k]=0
                  elif NoiseImg[i,j,k]>255:
                        NoiseImg[i,j,k]=255
            k=0
cv.imshow("change",NoiseImg)
cv.waitKey(0)
cv.destroyAllWindows

效果图对比

链接
 [

没有更多推荐了,返回首页