2010-12-09 14:39:00 wqvbjhc 阅读数 5167
  • 机器学习之概率与统计推断

    本课程讲解机器学习算法所需概率和统计推断知识。概率部分包括概率公理及推论、条件概率、贝叶斯公式、随机变量及其概率函数(CDF/pdf)、常用概率分布及其均值、方差;统计推断部分包括大数定律和中心极限定理、极大似然估计、贝叶斯估计,估计的评价、偏差-方差平衡。课程还会讲解假设检验的基本概念。

    20328 人正在学习 去看看 AI100讲师

灰度图像均值平滑



  图像平滑用于去除图像中的噪声。均值平滑,就是将每个像素的灰度值用其领域的平均值代替。该算法简单,速度快,但不能完全消除椒盐噪声。
  平滑模板:


1 1 1
1 1 1
1 1 1


2019-05-03 17:28:20 zaishuiyifangxym 阅读数 6381
  • 机器学习之概率与统计推断

    本课程讲解机器学习算法所需概率和统计推断知识。概率部分包括概率公理及推论、条件概率、贝叶斯公式、随机变量及其概率函数(CDF/pdf)、常用概率分布及其均值、方差;统计推断部分包括大数定律和中心极限定理、极大似然估计、贝叶斯估计,估计的评价、偏差-方差平衡。课程还会讲解假设检验的基本概念。

    20328 人正在学习 去看看 AI100讲师

目录

1 图像增强——图像平滑

1.1 图像增强简介

1.2 图像平滑

2 均值滤波

3 中值滤波

4 高斯滤波

参考资料


1 图像增强——图像平滑

1.1 图像增强简介

图像增强是对图像进行处理,使其比原始图像更适合于特定的应用,它需要与实际应用相结合。对于图像的某些特征如边缘、轮廓、对比度等,图像增强是进行强调或锐化,以便于显示、观察或进一步分析与处理。图像增强主要是一个主观过程,而图像复原大部分是一个客观过程。图像增强的方法是因应用不同而不同的,研究内容包括:

 

 

1.2 图像平滑

图像平滑是一种区域增强的算法,平滑算法有邻域平均法、中指滤波、边界保持类滤波等。在图像产生、传输和复制过程中,常常会因为多方面原因而被噪声干扰或出现数据丢失,降低了图像的质量(某一像素,如果它与周围像素点相比有明显的不同,则该点被噪声所感染)。这就需要对图像进行一定的增强处理以减小这些缺陷带来的影响。

图像平滑 有均值滤波、方框滤波、中值滤波和高斯滤波等。下面将介绍常用的均值滤波、中值滤波和高斯滤波。

为了实验方便,首先给图像加一点噪声

 

代码如下所示:

# -*- coding:utf-8 -*-
import cv2
import numpy as np

# 读取图片
img = cv2.imread("zxp.jpg", cv2.IMREAD_UNCHANGED)
img_noise=img

cv2.imshow("src", img)

rows, cols, chn = img_noise.shape


# 加噪声
for i in range(5000):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    img_noise[x, y, :] = 255


cv2.imshow("noise", img_noise)

# 等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

#保存含噪声图像
cv2.imwrite("zxp_noise.jpg", img_noise)

 

运行结果如下图所示:

 


 

2 均值滤波

均值滤波是指任意一点的像素值,都是周围 N \times M 个像素值的均值。例如下图中,红色点的像素值是其周围蓝色背景区域像素值之和除25,25=5\times5 是蓝色区域的大小。

 

均值滤波详细的计算方法如下图所示:

 

其中5\times5的矩阵称为,针对原始图像内的像素点,采用核进行处理,得到结果图像,如下图所示:

 

 

提取 1/25 可以将核转换为如下形式:

Python调用OpenCV实现 均值滤波 的函数如下:

result = cv2.blur(原始图像,核大小)
其中,核大小是以(宽度,高度)表示的元组形式。常见的形式包括:核大小(3,3)和(5,5)。

                                                                               K=\frac{1}{9}\times \left[ \begin{matrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \\ \end{matrix} \right]     

                                                                      K=\frac{1}{25}\times \left[ \begin{matrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ \end{matrix} \right]

 

(1) 核大小为 3\times3

代码如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 均值滤波
result = cv2.blur(source, (3, 3)) #可以更改核的大小

# 显示图形
titles = ['Source Image', 'Blur Image (3, 3)']
images = [source, result]
for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

 

运行结果如下图所示:

 

(2) 核大小为 5\times5

代码如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 均值滤波
result = cv2.blur(source, (5, 5)) #可以更改核的大小

# 显示图形
titles = ['Source Image', 'Blur Image (5, 5)']
images = [source, result]
for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

 

运行结果如下图所示:

 

 

(2) 核大小为 10\times10

代码如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 均值滤波
result = cv2.blur(source, (10, 10)) #可以更改核的大小

# 显示图形
titles = ['Source Image', 'Blur Image (10, 10)']
images = [source, result]
for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

 

运行结果如下图所示:

 

注:

1)随着核大小逐渐变大,会让图像变得更加模糊;

2)如果设置为核大小为(1,1),则结果就是原始图像。

 


 

3 中值滤波

在使用邻域平均法去噪的同时也使得边界变得模糊。而中值滤波是非线性的图像处理方法,在去噪的同时可以兼顾到边界信息的保留。选一个含有奇数点的窗口W,将这个窗口在图像上扫描,把窗口中所含的像素点按灰度级的升或降序排列,取位于中间的灰度值来代替该点的灰度值。计算过程如下图所示:

 

Python调用OpenCV实现 中值滤波 的函数如下:

OpenCV主要调用 medianBlur() 函数实现中值滤波。图像平滑里中值滤波的效果最好。

dst = cv2.medianBlur(src, ksize)

其中,参数:

src 表示源图像;

ksize 表示核大小。核必须是大于1的奇数,如3、5、7等。

 

(1)核大小为 3\times3

代码如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')

# 中值滤波
result = cv2.medianBlur(img, 3)#可以更改核的大小

# 显示图像
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)

# 等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

 

运行结果如下图所示:

 

(2)核大小为 5\times5

代码如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')

# 中值滤波
result = cv2.medianBlur(img, 5) #可以更改核的大小

# 显示图像
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)

# 等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

 

运行结果如下图所示:

 

(3)核大小为 7\times7

代码如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')

# 中值滤波
result = cv2.medianBlur(img, 7) #可以更改核的大小

# 显示图像
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)

# 等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

 

运行结果如下图所示:

 

注:

1)随着核大小逐渐变大,会让图像变得更加模糊;

2)核必须是大于1的奇数,如3、5、7等;

3)在代码 dst = cv2.medianBlur(src, ksize) 中 填写核大小时,只需填写一个数即可,如3、5、7等,对比均值滤波函数用法。

 


 

4 高斯滤波

为了克服简单局部平均法的弊端(图像模糊),目前已提出许多保持边缘、细节的局部平滑算法。它们的出发点都集中在如何选择邻域的大小、形状和方向、参数加平均及邻域各店的权重系数等。

图像高斯平滑也是邻域平均的思想对图像进行平滑的一种方法,在图像高斯平滑中,对图像进行平均时,不同位置的像素被赋予了不同的权重。高斯平滑与简单平滑不同,它在对邻域内像素进行平均时,给予不同位置的像素不同的权值,下图的所示的 3\times3 和 5\times5 邻域的高斯模板。

(1)核大小为 3\times3

                                                                 \frac{1}{16}\times \left[ \begin{matrix} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \\ \end{matrix} \right]=\left[ \begin{matrix} {}^{1}\!\!\diagup\!\!{}_{16}\; & {}^{1}\!\!\diagup\!\!{}_{8}\; & {}^{1}\!\!\diagup\!\!{}_{16}\; \\ {}^{1}\!\!\diagup\!\!{}_{8}\; & {}^{1}\!\!\diagup\!\!{}_{4}\; & {}^{1}\!\!\diagup\!\!{}_{8}\; \\ {}^{1}\!\!\diagup\!\!{}_{16}\; & {}^{1}\!\!\diagup\!\!{}_{8}\; & {}^{1}\!\!\diagup\!\!{}_{16}\; \\ \end{matrix} \right]

 

(1)核大小为 5\times5

                                                                          \frac{1}{273}\times \left[ \begin{matrix} 1 & 4 & 7 & 4 & 1 \\ 4 & 16 & 26 & 16 & 4 \\ 7 & 26 & 41 & 26 & 7 \\ 4 & 16 & 26 & 16 & 4 \\ 1 & 4 & 7 & 4 & 1 \\ \end{matrix} \right]

 

高斯滤波让临近的像素具有更高的重要度,对周围像素计算加权平均值,较近的像素具有较大的权重值。如下图所示,中心位置权重最高为0.4。

 

 

Python中OpenCV主要调用 GaussianBlur() 函数,如下:

dst = cv2.GaussianBlur(src, ksize, sigmaX)

其中,参数:

src 表示原始图像;

ksize 表示核大小;

sigmaX 表示X方向方差。

:核大小(N, N)必须是奇数,X方向方差主要控制权重。

1)核大小为 3\times3

                                                                    K=\left[ \begin{matrix} 0.05 & 0.1 & 0.05 \\ 0.1 & 0.4 & 0.1 \\ 0.05 & 0.1 & 0.05 \\ \end{matrix} \right]

2)核大小为 5\times5

                                                                    K=\left[ \begin{matrix} 1 & 1 & 2 & 1 & 1 \\ 1 & 3 & 4 & 3 & 1 \\ 2 & 4 & 8 & 4 & 2 \\ 1 & 3 & 4 & 3 & 1 \\ 1 & 1 & 2 & 1 & 1 \\ \end{matrix} \right]

 

(1)核大小为 3\times3

代码如下所示:


# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 高斯滤波
result = cv2.GaussianBlur(source, (3, 3), 0) #可以更改核大小

# 显示图形
titles = ['Source Image', 'GaussianBlur Image (3, 3)']
images = [source, result]
for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

 

运行结果如下图所示:

 

(2)核大小为 5\times5

代码如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 高斯滤波
result = cv2.GaussianBlur(source, (5, 5), 0) #可以更改核大小

# 显示图形
titles = ['Source Image', 'GaussianBlur Image (5, 5)']
images = [source, result]
for i in range(2):
    plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

 

运行结果如下图所示:

 

注:

1)随着核大小逐渐变大,会让图像变得更加模糊;

2)核大小(N, N)必须是大于1的奇数,如3、5、7等;


 

参考资料

[1] https://blog.csdn.net/Eastmount/article/details/82216380

[2] Python+OpenCV图像处理

2018-03-07 23:21:25 u012421852 阅读数 514
  • 机器学习之概率与统计推断

    本课程讲解机器学习算法所需概率和统计推断知识。概率部分包括概率公理及推论、条件概率、贝叶斯公式、随机变量及其概率函数(CDF/pdf)、常用概率分布及其均值、方差;统计推断部分包括大数定律和中心极限定理、极大似然估计、贝叶斯估计,估计的评价、偏差-方差平衡。课程还会讲解假设检验的基本概念。

    20328 人正在学习 去看看 AI100讲师
20180307站位
2019-09-18 16:16:40 caimouse 阅读数 79
  • 机器学习之概率与统计推断

    本课程讲解机器学习算法所需概率和统计推断知识。概率部分包括概率公理及推论、条件概率、贝叶斯公式、随机变量及其概率函数(CDF/pdf)、常用概率分布及其均值、方差;统计推断部分包括大数定律和中心极限定理、极大似然估计、贝叶斯估计,估计的评价、偏差-方差平衡。课程还会讲解假设检验的基本概念。

    20328 人正在学习 去看看 AI100讲师

从前面来看已经可以把积分图像的功能集成到OpenCV里,那么在它里面也有相应的均值平滑的函数cv2.blur,这个函数实现的功能与前面实现快速计算平滑的方法是一样的,只不过它可以处理彩色图像,因为它可以把彩色图片进行分离成三个颜色的图像进行平滑,再合并回来。它的定义如下:

src 输入图像

dst 输出图像

ksize 平滑窗口的大小

anchor 锚点,如果宽、高均为奇数,则Point(-1,-1)代表中心点

borderType 边界扩充类型

 

因此前面均值平滑的例子,就可以简写成这样:

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

#图片的路径
imgname = "gauss1.jpg"

#读取图片
image = cv2.imread(imgname, cv2.IMREAD_GRAYSCALE)

#图片的高度和宽度
h,w = image.shape[:2]
print('imagesize={}-{}'.format(w,h))

#显示原图
cv2.imshow("Image",image)

#平滑
out = cv2.blur(image,(5,5))
out = out.astype(np.uint8)
cv2.imshow("out",out)


cv2.waitKey(0)
cv2.destroyAllWindows()

结果输出如下:

输入图片

输出图片

https://blog.csdn.net/caimouse/article/details/51749579

 

2013-04-10 14:51:37 mlkiller 阅读数 4237
  • 机器学习之概率与统计推断

    本课程讲解机器学习算法所需概率和统计推断知识。概率部分包括概率公理及推论、条件概率、贝叶斯公式、随机变量及其概率函数(CDF/pdf)、常用概率分布及其均值、方差;统计推断部分包括大数定律和中心极限定理、极大似然估计、贝叶斯估计,估计的评价、偏差-方差平衡。课程还会讲解假设检验的基本概念。

    20328 人正在学习 去看看 AI100讲师

本章主要讲图像处理中的模糊处理部分

英文叫做blur, 也叫做smootiing,  中文中叫做模糊或者平滑。

用过photoshop的人都应该知道,滤镜里面就有模糊这个选项,我们现在看看它是怎么实现的。

一含义

   模糊(平滑)是一种常用的图片处理方式,它的作用可以用来降低噪声,还有其他用途

   看一下opencv 里面的公式

               g(i,j) = \sum_{k,l} f(i+k, j+l) h(k,l)

     g(i,j)是目标坐标的像素值, f(i+k,j+l)是k,l这些地方的像素值, h(k,l)是 kernel,  我不知道怎么去准确翻译它的意义,它是过滤器的系数。 

    简单的按照我的思路去理解,就是一个权值,模糊的含义是将所有的像素按照一定的权值进行运算,得到一个比较均衡的结果。

二 类型

类型有很多种:
均值模糊(box blur) 高斯模糊(gaussian blur)  中值模糊(media blur) 二值模糊(bilateral blur)
本文只讲均值模糊和高斯模糊

三 算法

1 均值模糊
   均值模糊很简单就是周边所有的影响都是1,求平均值即可
K = \dfrac{1}{K_{width} \cdot K_{height}} \begin{bmatrix}    1 & 1 & 1 & ... & 1 \\    1 & 1 & 1 & ... & 1 \\    . & . & . & ... & 1 \\    . & . & . & ... & 1 \\    1 & 1 & 1 & ... & 1   \end{bmatrix}
2 高斯模糊
关于高斯模糊的算法,推荐这个文章
根据这个公式计算出系数即可。
上篇文章写得很详细,我就不班门弄斧了。

四均值模糊的代码和效果

     先放上均值模糊的代码
void boxblur(Mat input ,Mat &out, int x, int y)
{
	// accept only char type matrices
	CV_Assert(input.depth() != sizeof(uchar));

	out.create(input.size(),input.type());

	int nChannels = input.channels();
	int nRows = input.rows;
	int nCols = input.cols;

	int size = x * y;
	float kernel = 1.0/size;

	int i,j;
	uchar* p;
	uchar* q;
	uchar R,G,B;

	for( i = x; i < nRows - x; ++i)
	{
		q = out.ptr<uchar>(i);
		for ( j = y; j < nCols - y; ++j)
		{
			float sumR = 0;
			float sumG = 0;
			float sumB = 0;
			for (int k =0; k<x;k++)
			{
				p = input.ptr<uchar>(i-x+k);
				for(int l = 0; l < y;l++)
				{
					sumB += input.at<uchar>(i - x + k,(j + l - y)*nChannels) * kernel;//p[(l + j -y)*nChannels ] * kernel;
					sumG += input.at<uchar>(i - x + k,(j + l - y)*nChannels + 1) * kernel;//p[(l + j -y)*nChannels + 1] * kernel;
					sumR += input.at<uchar>(i - x + k,(j + l - y)*nChannels + 2) * kernel;//p[(l + j -y)*nChannels + 2] * kernel;
				}
			}
			q[j*nChannels] = sumB;
			q[j*nChannels+1] = sumG;
			q[j*nChannels+2] = sumR;
		}
	}


}

红色部分是我想直接用at,而不用指针,但是效率低的厉害。


下图是用指针的相差了20倍。。。可见指针虽然万恶,但是确实是个好东西。



由于size(4,4)图太小看不清, 实际用的是8
原始 opencv 本文


五高斯模糊的代码和效果

代码如下:

void gaussblur(Mat input ,Mat &out, int x, int y)
{
	float sigma = 1.5;
	Mat kernel;
	float pi = 3.1415926;

	kernel.create(x ,y ,CV_32F);

	float mx = x/2.0;
	float my = y/2.0;

       //这里有问题,后面做修正。
	for (int i =0; i< x;i++)
	{
		for (int j =0; j<y;j++)
		{
			kernel.at<float>(i,j) = exp(-1 * ((i - mx) * (i - mx) +(j - my) * (j-my) )/( 2 * sigma * sigma))/(2 * pi * sigma *sigma) ;
		}
	}


    int nChannels = input.channels();
	int nRows = input.rows;
	int nCols = input.cols;

	out.create(input.size(),input.type());
    uchar* p;
	uchar* q;
	float* s;

	for(int  i = x; i < nRows - x; ++i)
	{
		q = out.ptr<uchar>(i);
		for (int j = y; j < nCols - y; ++j)
		{
			float sumR = 0;
			float sumG = 0;
			float sumB = 0;
			for (int k =0; k<x;k++)
			{
				p = input.ptr<uchar>(i-x+k);
				s = kernel.ptr<float>(k); 
				for(int l = 0; l < y;l++)
				{
					sumB += p[(l + j -y)*nChannels ] * s[l];//input.at<uchar>(i - x + k,(j + l - y)*nChannels) * kernel;//
					sumG += p[(l + j -y)*nChannels + 1] *s[l];//input.at<uchar>(i - x + k,(j + l - y)*nChannels + 1) * kernel;//
					sumR += p[(l + j -y)*nChannels + 2] * s[l];//input.at<uchar>(i - x + k,(j + l - y)*nChannels + 2) * kernel;
				}
			}
			q[j*nChannels] = sumB;
			q[j*nChannels+1] = sumG;
			q[j*nChannels+2] = sumR;
		}
	}

	
}

效率如下:

效果图如下:
本文没有考虑边界的情况,所以都是灰色的,可以考虑一下如何处理边界。
原始 opencv 本文

上面代码有两处问题:
第一是在size比较小的时候,这些点的概率之和不等于1,会导致图片出问题。修正如下:

	float sum = 0;
	for (int i =0; i< x;i++)
	{
		for (int j =0; j<y;j++)
		{
			sum+= kernel.at<float>(i,j) = exp(-1 * ((i - mx) * (i - mx) +(j - my) * (j-my) )/( 2 * sigma * sigma))/(2 * pi * sigma *sigma) ;
		}
	}
	for (int i =0; i< x;i++)
	{
		for (int j =0; j<y;j++)
		{
			kernel.at<float>(i,j) = kernel.at<float>(i,j)/ sum ;
		}
	}


第二个问题是本文中sigma 是个固定值,实际上它是个可变值,具体怎么计算,我没有搞清楚,可以查看opencv的源代码,下面文章有参考价值

更新一下参考opencv里面的可以这样计算
sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8 .
修改程序之后发现和原始的高斯函数基本一致,希望广大朋友们多多评论,本人水平有限,很多地方有纰漏,希望能够共同提高。
没有更多推荐了,返回首页