2019-11-24 19:09:37 qq_43309286 阅读数 116
  • OpenCV图像分割实战视频教程

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

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

数字图像处理——高斯滤波器【像素级别处理】(python)

简介

高斯滤波通常用它来减少图像噪声以及降低细节层次。这种模糊技术生成的图像,其视觉效果就像是经过一个半透明屏幕在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同。高斯平滑也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果.从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积。由于正态分布又叫作“高斯分布”,所以这项技术就叫作高斯模糊。图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果。由于高斯函数的傅立叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波器。

代码实现

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('Fig0340.tif')  # 测试图片
H = img.shape[0]
W = img.shape[1]

#   产生5*5的Gaussian smoothing filter
# Σ=3,h(x,y)=e^((x^2+y^2)/(2*Σ*Σ))
h = np.zeros((5, 5))  # 高斯模板

for i in range(5):
    for j in range(5):
        x = i - 2
        y = j - 2
        h[i, j] = np.power(np.e, -(x * x + y * y) / 18)

h /= np.sum(h)  # 归一化处理
spanImg = np.zeros((H + 4, W + 4, 3), np.uint8)  # 5*5扩充后的图像

for i in range(H):
    for j in range(W):
        spanImg[i + 2, j + 2] = img[i, j]

blurImg = np.zeros((H, W, 3), np.uint8)  # 高斯模糊化之后的图像
for i in range(H):
    for j in range(W):
        pix = 0
        for x in range(5):
            for y in range(5):
                pix += h[x, y] * spanImg[i + x, j + y, 0]
        blurImg[i, j, 0] = round(pix)
        blurImg[i, j, 1] = blurImg[i, j, 0]
        blurImg[i, j, 2] = blurImg[i, j, 0]

plt.subplot(1, 2, 1)
plt.title('original image')
plt.imshow(img)
plt.axis('off')

plt.subplot(1, 2, 2)
plt.title('blur image')
plt.imshow(blurImg)
plt.axis('off')
plt.show()

在这里插入图片描述

2015-05-19 22:11:31 zyzhangyue 阅读数 424
  • OpenCV图像分割实战视频教程

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

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

高斯滤波是一种线性平滑滤波,适用于滤除高斯白噪声,已广泛应用于图像处理的预处理阶段。按照本人的理解,对图像进行高斯滤波就是对图像中的每个点的像素值计算,计算的准则是,由该点本身灰度值以及其邻域内的其他像素灰度值加权平均所得,而加权平均的权系数由二维离散高斯函数采样并归一化后所得。

void GuassFilter(CvMat *pGrayMat, CvMat* pFilterMat, int nWidth, int nHeight, double dSigma)  

{  

    ////////////////////////参数说明///////////////////////////////////   

    //pGrayMat:待处理图像数组  

    //pFilterMat:保存高斯滤波结果  

    //nWidth:图像宽度  

    //nHeight:图像高度  

    //dSigma:高斯滤波参数,方差  

    int nWidowSize = (int)(1+2*ceil(3*dSigma));  //定义滤波窗口的大小  

    int nCenter = (nWidowSize)/2;                //定义滤波窗口中心的索引  

    //生成二维的高斯滤波系数  

    double* pdKernal = new double[nWidowSize*nWidowSize]; //定义一维高斯核数组  

    double  dSum = 0.0;                                   //求和,进行归一化           

    /////////////二维高斯函数公式//////////////////////        

    //                           x*x+y*y        ///////  

    //                     -1*--------------    ///////  

    //          1               2*Sigma*Sigma   ///////  

    //   ---------------- e                     ///////  

    //   2*pi*Sigma*Sigma                       ///////  

    ///////////////////////////////////////////////////   

    for(int i=0; i<nWidowSize; i++)  

    {  

        for(int j=0; j<nWidowSize; j++)  

        {  

            int nDis_x = i-nCenter;  

            int nDis_y = j-nCenter;  

            pdKernal[i+j*nWidowSize]=exp(-(1/2)*(nDis_x*nDis_x+nDis_y*nDis_y)  

                /(dSigma*dSigma))/(2*3.1415926*dSigma*dSigma);  

            dSum += pdKernal[i+j*nWidowSize];  

        }  

    }  

    //进行归一化  

    for(i=0; i<nWidowSize; i++)  

    {  

        for(int j=0; j<nWidowSize; j++)  

        {  

            pdKernal[i+j*nWidowSize] /= dSum;  

        }  

    }  

    for(i=0; i<nHeight; i++)  

    {  

        for(int j=0; j<nWidth; j++)  

        {  

            double dFilter=0.0;  

            double dSum = 0.0;  

            for(int x=(-nCenter); x<=nCenter; x++)           //  

            {  

                for(int y=(-nCenter); y<=nCenter; y++)       //  

                {  

                    if( (j+x)>=0 && (j+x)<nWidth && (i+y)>=0 && (i+y)<nHeight)  //判断边缘  

                    {  

                        double ImageData = cvmGet(pGrayMat ,i+y, j+x);  

                        dFilter += ImageData * pdKernal[(y+nCenter)*nWidowSize+(x+nCenter)];  

                        dSum += pdKernal[(y+nCenter)*nWidowSize+(x+nCenter)];  

                    }  

                }  

            }  

            cvmSet(pFilterMat, i, j, dFilter/dSum);  

        }  

    }  

    delete[]pdKernal;  

}  


2019-08-30 20:58:33 HopesunIce 阅读数 204
  • OpenCV图像分割实战视频教程

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

    2779 人正在学习 去看看 贾志刚
/*入门学习   图像滤波
  Filtering 是图像处理中的一个基本操作,其目的是为了提取图像中被认为重要的那些部分。
  滤波可以去除图像中的噪声,提取感兴趣的视觉特征,允许图像重采样等。

  这里我们了解一些基本的内容。
  观察一幅图像时,我们看到不同的灰度(或彩色值)在图像中的分布。图像之间存在不同是因为他们有不同的灰度分布。
  因此存在另一种进行图像处理的方式:观察图像中存在的灰度的变化。        

  一些图像中包含大面积恒定的灰度强度,另一些图片中灰度变化迅速。
  因此观察图像中灰度或者像素点变化的频率构成了一种描述图像的方式,这种观点被称为频域。通过观察灰度的分布
  来描述一幅图像 被称为空间区域。 
  
  空间域又称图像空间(image space)。由图像像元组成的空间。
  在图像空间中以长度(距离)为自变量直接对像元值进行处理称为空间域处理。
  以空间坐标作为变量进行的研究就是空间域。

  频域分析按照高频到低频的次序 ,分解图像到频率内容。低频对应区域的图像强度变化缓慢,高频区域是由快速变化的图像
  强度生成的。图像时二维的,他包含垂直频率(垂直方向的变化)和水平频率(水平方向的变化)

  频域分析的框架下,滤波操作的作用是增强部分频段,同时限制或者衰减其他频段。
  低频滤波器去除了图像中的高频成分,高通滤波器去除了低频成分。


  这篇博客个人觉得讲的非常好:https://blog.csdn.net/qq_36359022/article/details/80154900

*/
/*下面开始学习    低通滤波器 */ 
#include<opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
double **getGuassionArray(int size, double sigma)
{
	/*这句话暂时我还讲述不太明白 反正是定义了一个二维数组    
	double *Arr = new double[size]  创建一个动态数组  Arr指向这个数组的地址
	double ** Arr = new double*[size]; 中 double *[]应该是定义了一个指针数组  
	这样这句话 应该就是定义了一个指向指针数组的指针  大概这样理解吧

	比如说 double *[size]里面的指针指向了四个一维数组 每一个一维数组里面有四个元素 
	这时候(void*)(*Arr)+1 得到地址 应该是第二个一维数组的地址  
	这里加1  指针哪里应该是加的四个元素的类型的字节 我没试过  应该是这样吧 
	*/
	double sum = 0;
	int i, j;
	int center = (size-1) / 2;
	double ** Arr = new double*[size];
	for (i = 0; i < size; i++)
	{
		Arr[i] = new double[size]; //Arr[i]其实就是指针 Arr+i就是指向Arr[i]的指针 Arr[i]指向一个一维数组 
	}
	for (i = 0; i < size; i++)
	{
		for (j = 0; j < size; j++)
		{
			Arr[i][j] = exp(-((i - center)*(i - center) + (j - center)*(j - center)) / (2 * sigma*sigma));
			sum += Arr[i][j];
		}
	}
	for (i = 0; i < size; i++)
	{
		for (j = 0; j < size; j++)
		{
			Arr[i][j] /= sum;
		}
	}
	
	return Arr;
}
/*此 函数是用来 输出得到的矩阵 或者说叫核或者掩码
 可以看到sigma取不同的值时 得到掩码的值是不同的  sigma的取值越小
 核中间的像素权值就越大  这也和概率中高斯函数的性质是一样的  sigma的取值越小 图像越高窄  
*/
void printfKernel()
{
	double **Arr;
	Arr = getGuassionArray(3, 10);
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			cout << Arr[i][j] << '\t';
		}
		cout << endl;
	}
}
/*  高斯处理  */
/*const Mat image  前面加一个const  有什么用呢  image前面没有&符号啊  是不让对这个图像操作吗
  为啥  image.at<Vec3b>(i, j)[0] = 0;操作不合法呢??
*/
void myGaussian(const Mat image, Mat & result)
{
	double **Arr;
	Arr = getGuassionArray(3, 1.5);
	int nl = image.rows;
	int nc = image.cols;
	Mat temp(image.size(), image.type());
	for (int i = 0; i < nl; i++)
	{
		for (int j = 0; j < nc; j++)
		{
			if ((i > 0) && (i < nl - 1) && (j > 0) && (j < nc - 1))
			{
				temp.at<Vec3b>(i, j)[0] = 0;
				temp.at<Vec3b>(i, j)[1] = 0;
				temp.at<Vec3b>(i, j)[2] = 0;
				for (int x = 0; x < 3; x++)
				{
					for (int y = 0; y < 3; y++)
					{
						temp.at<Vec3b>(i, j)[0] += Arr[x][y] * image.at<Vec3b>(i + 1 - x, j + 1 - y)[0] ;
						temp.at<Vec3b>(i, j)[1] += Arr[x][y] * image.at<Vec3b>(i + 1 - x, j + 1 - y)[1] ;
						temp.at<Vec3b>(i, j)[2] += Arr[x][y] * image.at<Vec3b>(i + 1 - x, j + 1 - y)[2] ;
					}

				}
			}
		}
	}
	temp.copyTo(result);
}
void namesSet()
{
	namedWindow("原始图像", 0);
	cvResizeWindow("原始图像", 433, 600);

	namedWindow("椒盐图像", 0);
	cvResizeWindow("椒盐图像", 433, 600);

	namedWindow("自定义高斯", 0);
	cvResizeWindow("自定义高斯", 433, 600);

	namedWindow("OpenCv高斯", 0);
	cvResizeWindow("OpenCv高斯", 433, 600);

}
void salt(Mat image, Mat &result,int k)
{
	image.copyTo(result);
	for (; k > 0; k--)
	{
		int i = rand() % result.rows;
		int j = rand() % result.cols;
		if (result.channels() == 1)
		{
			result.at<uchar>(i, j) = 255;
		}
		if (result.channels() == 3)
		{
			result.at<Vec3b>(i, j) = 255;
			result.at<Vec3b>(i, j) = 255;
			result.at<Vec3b>(i, j) = 255;
		}
	}
}
int main()
{
	Mat image, result1,result2,result3;
	image = imread("Test1.jpg", IMREAD_UNCHANGED);
	namesSet();
	salt(image, result1,3000);
	GaussianBlur(result1, result2, Size(3,3), 1.5);
	myGaussian(result1, result3);
	imshow("原始图像",image);
	imshow("椒盐图像", result1);
	imshow("OpenCv高斯", result2);
	imshow("自定义高斯", result3);
	printfKernel();
	waitKey(0);
	return 0;
}

 

2019-03-30 17:31:43 TJMtaotao 阅读数 880
  • OpenCV图像分割实战视频教程

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

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

%读取图像并转成灰度图像
I =imread('tiantan.jpg');
I =rgb2gray(I);
%生成高斯滤波器核
w =fspecial('gaussian',3,0.5);
size_a = size(I);
%进行高斯滤波
g =imfilter(I,w,'conv','symmetric','same');
%降采样
t = g(1:3:size_a(1),1:3:size_a(2));
%显示处理结果
imshow(I);
figure
imshow(t)

 

 

法二:通过video.Pyramid调用

hgausspymd =video.Pyramid;
hgausspymd.PyramidLevel=2;
x =imread('1.jpg');
y =step(video.Pyramid,x);

%显示结果
figure,imshow(x);title('原始图像');
x1 =mat2gray(double(y));
figure,imshow(x1);
title('Decomposed Image')
 

2018-09-27 20:41:41 wsp_1138886114 阅读数 11289
  • OpenCV图像分割实战视频教程

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

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

一、图像处理——滤波

过滤 :是信号和图像处理中基本的任务。其目的是根据应用环境的不同,选择性的提取图像中某些认为是重要的信息。过滤可以移除图像中的噪音、提取感兴趣的可视特征、允许图像重采样等等。
频域分析 :将图像分成从低频到高频的不同部分。低频对应图像强度变化小的区域,而高频是图像强度变化非常大的区域。
在频率分析领域的框架中,滤波器是一个用来增强图像中某个波段或频率并阻塞(或降低)其他频率波段的操作。低通滤波器是消除图像中高频部分,但保留低频部分。高通滤波器消除低频部分。

  • 滤波(高通、低通、带通、带阻) 、模糊、去噪、平滑等。
    在这里插入图片描述

1.1 均值模糊(低通滤波)、中值模糊(中值滤波)

  • 均值滤波:典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。
  • 中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。
import cv2
import numpy as np


def blur_demo(image):            
	"""
	均值模糊 : 去随机噪声有很好的去噪效果
	(1, 15)是垂直方向模糊,(15, 1)是水平方向模糊
	"""
    dst = cv2.blur(image, (1, 15))    
    cv2.imshow("avg_blur_demo", dst)

def median_blur_demo(image):    # 中值模糊  对椒盐噪声有很好的去燥效果
    dst = cv2.medianBlur(image, 5)
    cv2.imshow("median_blur_demo", dst)

def custom_blur_demo(image):
	"""
	用户自定义模糊
	下面除以25是防止数值溢出
	"""
    kernel = np.ones([5, 5], np.float32)/25   
    dst = cv2.filter2D(image, -1, kernel)
    cv2.imshow("custom_blur_demo", dst)

src = cv2.imread("./fapiao.png")
img = cv2.resize(src,None,fx=0.8,fy=0.8,interpolation=cv2.INTER_CUBIC)
cv2.imshow('input_image', img)

blur_demo(img)
median_blur_demo(img)
custom_blur_demo(img)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

1.2 边缘保留滤波EPF

进行边缘保留滤波通常用到两个方法:高斯双边滤波和均值迁移滤波。

  • 双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。
    双边滤波器顾名思义比高斯滤波多了一个高斯方差 σd\sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波
  • 双边滤波函数原型:
"""
	bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]]) -> dst
	  - src: 输入图像。
	  - d:   在过滤期间使用的每个像素邻域的直径。如果输入d非0,则sigmaSpace由d计算得出,如果sigmaColor没输入,则sigmaColor由sigmaSpace计算得出。
	  - sigmaColor: 色彩空间的标准方差,一般尽可能大。
	                较大的参数值意味着像素邻域内较远的颜色会混合在一起,
	                从而产生更大面积的半相等颜色。
	  - sigmaSpace: 坐标空间的标准方差(像素单位),一般尽可能小。
	                参数值越大意味着只要它们的颜色足够接近,越远的像素都会相互影响。
	                当d > 0时,它指定邻域大小而不考虑sigmaSpace。 
	                否则,d与sigmaSpace成正比。
"""
import cv2

def bi_demo(image):      #双边滤波
    dst = cv2.bilateralFilter(image, 0, 100, 5)
    cv2.imshow("bi_demo", dst)

def shift_demo(image):   #均值迁移
    dst = cv2.pyrMeanShiftFiltering(image, 10, 50)
    cv2.imshow("shift_demo", dst)

src = cv2.imread('./100.png')
img = cv2.resize(src,None,fx=0.8,fy=0.8,
                 interpolation=cv2.INTER_CUBIC)
cv2.imshow('input_image', img)

bi_demo(img)
shift_demo(img)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

二、图像处理——噪点与滤波

2.1 椒盐噪点(使用中值滤波去除)

import cv2
import numpy as np

def salt(img, n):
    for k in range(n):
        i = int(np.random.random() * img.shape[1])
        j = int(np.random.random() * img.shape[0])
        if img.ndim == 2:
            img[j,i] = 255
        elif img.ndim == 3:
            img[j,i,0]= 255
            img[j,i,1]= 255
            img[j,i,2]= 255
        return img

img = cv2.imread("./original_img.png",cv2.IMREAD_GRAYSCALE)
result = salt(img, 500)
median = cv2.medianBlur(result, 5)
cv2.imshow("original_img", img)
cv2.imshow("Salt", result)
cv2.imshow("Median", median)
cv2.waitKey(0)
cv2.destroyWindow()

在这里插入图片描述

2.1 高斯滤波/模糊(去噪效果好)

高斯模糊实质上就是一种均值模糊,只是高斯模糊是按照加权平均的,距离越近的点权重越大,距离越远的点权重越小。
通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。
我们可以从其函数表达式可知:
在这里插入图片描述

import cv2
import numpy as np

def clamp(pv):
    if pv > 255:
        return 255
    if pv < 0:
        return 0
    else:
        return pv

def gaussian_noise(image):           # 加高斯噪声
    h, w, c = image.shape
    for row in range(h):
        for col in range(w):
            s = np.random.normal(0, 20, 3)
            b = image[row, col, 0]   # blue
            g = image[row, col, 1]   # green
            r = image[row, col, 2]   # red
            image[row, col, 0] = clamp(b + s[0])
            image[row, col, 1] = clamp(g + s[1])
            image[row, col, 2] = clamp(r + s[2])
    cv2.imshow("noise image", image)

src = cv2.imread('888.png')
cv2.imshow('input_image', src)

gaussian_noise(src)
dst = cv2.GaussianBlur(src, (15,15), 0) #高斯模糊
cv2.imshow("Gaussian_Blur2", dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

三、高通过滤/滤波(边缘检测/高反差保留)

使用的函数有:cv2.Sobel() , cv2.Schar() , cv2.Laplacian()
Sobel,scharr其实是求一阶或者二阶导数。scharr是对Sobel的优化。
Laplacian是求二阶导数。

  • cv2.Sobel() 是一种带有方向过滤器
"""
dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
src:    需要处理的图像;
ddepth: 图像的深度,-1表示采用的是与原图像相同的深度。 
        目标图像的深度必须大于等于原图像的深度;
dx和dy: 求导的阶数,0表示这个方向上没有求导,一般为0、1、2。

dst     不用解释了;
ksize: Sobel算子的大小,必须为1、3、5、7。  ksize=-1时,会用3x3的Scharr滤波器,
        它的效果要比3x3的Sobel滤波器要好 
scale: 是缩放导数的比例常数,默认没有伸缩系数;
delta: 是一个可选的增量,将会加到最终的dst中, 默认情况下没有额外的值加到dst中
borderType: 是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。

"""
import cv2

img=cv2.imread('888.png',cv2.IMREAD_COLOR)
x=cv2.Sobel(img,cv2.CV_16S,1,0)
y=cv2.Sobel(img,cv2.CV_16S,0,1)

absx=cv2.convertScaleAbs(x)
absy=cv2.convertScaleAbs(y)
dist=cv2.addWeighted(absx,0.5,absy,0.5,0)

cv2.imshow('original_img',img)
cv2.imshow('y',absy)
cv2.imshow('x',absx)
cv2.imshow('dsit',dist)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
参考博客:
https://blog.csdn.net/sunny2038/article/details/9155893
https://www.cnblogs.com/FHC1994/p/9097231.html
https://www.cnblogs.com/FHC1994/p/9097231.html
https://blog.csdn.net/wangleixian/article/details/78237597

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