2013-04-10 14:51:37 mlkiller 阅读数 4225

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

英文叫做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 .
修改程序之后发现和原始的高斯函数基本一致,希望广大朋友们多多评论,本人水平有限,很多地方有纰漏,希望能够共同提高。
2017-03-01 21:02:49 u013355826 阅读数 3312


————————————————————————————————————————————————————————


时间宝贵!珍惜一分一秒


————————————————————————————————————————————————————————

一.空间滤波机理

滤波是指接受或者拒绝一定的频率分量。空间滤波是由一个邻域(典型是一个小矩形),对该邻域包围的图像像素执行预定义操作的结果。如果在图像处理像素上执行的是线性操作,则该滤波器是线性空间滤波器,否则是非线性空间滤波器。

空间滤波的机理就是:在待处理的图像中,逐点移动掩模,在每一点(x , y) 处,滤波器在该点的响应通过事先定义的关系来计算。对于线性空间滤波器,其响应是由滤波器系数和滤波掩模扫过的区域响应的像素索值乘积给出。

g(x,y) = w(-1,-1)f(x-1, y-1)+w(-1,0)f(x-1, y)+.......+w(1,1)f(x+1,y+1)

对于m x n的模板,假设m=2a+1; n=2b+1,则线性空间滤波的公式:


当逐点移动掩模时候,会想到一个问题,就是当掩模移动到图像的边缘时候,掩模内的行或者列可能在图像的外边。这就引出了当滤波中心在图像轮廓的边缘的的情况。

二.滤波中心靠近图像轮廓的情况

当滤波中心 靠近轮廓边缘的时,一种办法就是不让掩模靠近最边上的像素。对于3x3的掩模,掩模中心点不能到最边上的那一行(列),对于5x5的掩模,掩模中心点不能到最边上的那两行(列)。对于 n\times n的掩模,掩模中心的移动范围限制在距离图像边缘不小于(n-1)/2 的像素点。这种办法,导致边缘的像素点不会被处理,可以将未被处理的像素点直接复制到结果处。第二种方法就是,我们在边缘以外的像素点上补上(n-1)/2行(列)个像素点,灰度值可以是其他值,也可以把边缘复制到图像之外。


三.平滑滤波器

平滑处理用户模糊处理和降低噪声。

平滑线性空间滤波器的输出是包含在滤波器模板邻域内的像素的简平均值。这些滤波器有时也称为均值滤波器。平滑滤波器使用模板确定的邻域内像素的平均灰度值代替图像中的每一个像素值,这种处理降低了图像灰度的“尖锐”变化。常见的平滑处理就是为了降低噪声。

(1)标准像素平均值

 对于3x3的平滑滤波器的标准像素平均值。


(2)加权平均

在一个模板内,不同的像素点的重要性不同,这样就给不同的像素引入权值。





三.实例


对输入图像坐标(1,1)的3x3邻域内求标准像素平均值。R=(1*8+10)/ 9=2。同理可得滤波后其他像素点的值。明显看出,消除了输入图像中心点坐标(3,3)的尖锐现象。

对于3x3加权平均滤波,对输入图像坐标(1,1)R=(4+2*4+10+3)/16=25/16.同理可得滤波后其他像素点的值。

平均滤波处理噪声更好些,边缘模糊效果明显。

加权平均滤波边界模糊的负效应不明显。

空间均值处理的一个重要应用就是:为了对感兴趣的物体得到一个粗略的描述而模糊一副图像。这样较小的物体的强度与北京混合一起了,较大物体变得像斑点更易于检测。掩模大小由那些将融入背景中去的物体尺寸来决定。


四.统计排序(非线性)滤波器

中值滤波也会有边缘模糊效应,只是比较小。中值滤波是非线性,处理后的图像不能恢复为原图像。




2013-09-22 11:40:22 a200800170331 阅读数 1886

在数字图像处理中,Lena(Lenna)是一张被广泛使用的标准图片,特别在图像压缩的算法研究中。

[转载]Lena与图像处理


(为什么用这幅图,是因为这图的各个频段的能量都很丰富:即有低频(光滑的皮肤),也有高频(帽子上的羽毛),很适合来验证各种算法)
       然而,这张图片背后的故事是颇有意思的,很多人都抱有学究都是呆子的看法,然而Lena对此就是一个有力的驳斥。lena(lenna)是一张于1972年11月出版的Playboy的中间插页,在这期杂志中使用了“Lenna”的拼写,而实际莉娜在瑞典语中的拼写是“lena”。如今的Lena生活在自己的祖国瑞典,从事于酿造业,婚后并生下3个孩子。

[转载]Lena与图像处理
从1973年以来,Lena就开始出现在图像处理的科学论文中,直到1988年,她才得知自己原来已经被从事图像处理行业的工作者认识。 1997年,lena 被邀请参加了在波士顿举办的第50届图像科技技术年会。
       1973年6,7月间,南加州大学信号图像处理研究所的副教授Alexander和学生一起,为了一个同事的学会论文正忙于寻找一副好的图片。他们想要一副具有良好动态范围的人的面部图片用于扫描。不知是谁拿着一本Playboy走进研究室。由于当时实验室里使用的扫描仪(Muirhead wirephoto scanner)分辨率是100行/英寸,试验也仅仅需要一副512X512的图片,所以他们只将图片顶端开始的5.12英寸扫描下来,切掉肩膀一下的部分。多年以来,由于图像Lena源于Playboy,将其引用于科技文章中饱受争议。Playboy杂志也将未授权的引用告上法庭。随着时间流失,人们渐渐淡忘Lena的来源,Playboy也放松了对此的关注。值得一提的是,Lena也是playboy发行的最畅销的海报,已经出售7,161,561份。

      这个是原版的Lena照片,图像处理的初学者一定会大跌眼镜吧

PlayBoy杂志封面上的Lena.jpg;

[转载]Lena与图像处理

另外一件有趣的事情是,Lenna的那一期杂志是当时Playboy销量最好的一期,共卖出去了7161561份。

现在Lena.jpg

[转载]Lena与图像处理

标准Lena.jpg
[转载]Lena与图像处理  

该图原本是刊于1972年11月号花花公子杂志上的一张裸体插图照片的一部分,这期花花公子也是历年来最畅销的一期,销量达7,161,561本。1973 年6月,美国南加州大学的信号图像处理研究所的一个助理教授和他的一个研究生打算为了一个学术会议找一张数字照片,而他们对于手头现有成堆"无聊"照片感到厌烦。事实上他们需要的是一个人脸照片,同时又能让人眼前一亮。这时正好有人走进实验室,手上带着一本当时的花花公子杂志,结果故事发生了……而限于当时实验室设备和测试图片的需要,lenna的图片只抠到了原图的肩膀部分。

       图中人为瑞典模特儿 Lena Soderberg (Lena Söderberg)。现在被广泛使用的英文化名字"Lenna"最初是由花花公子杂志发表此照片时命名的,以方便英语读者近似正确地读出瑞典语中"Lena"的发音。Lena Soderberg 女士现在仍住在她的家乡瑞典,拥有一个有三个孩子的家庭,并且在国家酒类专卖局工作。在1988年的时候,她接受了瑞典一些计算机相关出版社的访问,她对于她的照片有这样的奇遇感到非常的惊奇与兴奋。这是她首次得知她的照片被应用在计算机行业。Lena Soderberg于1997年被邀请为嘉宾,参加了数字图像科学技术50周年学术会议。在该会议上,Lenna成了最受欢迎的人之一,她做了关于自己介绍的简要发言,并被无数的fans索取签名。 

       莱娜图在图像压缩算法是最广泛应用的标准测试图——她的脸部与裸露的肩部已经变成了事实上的工业准。然而,这张图像的使用也引起了一些争议。一些人担心它的色情内容;《花花公子》杂志曾经威胁要起诉对莱娜图未经授权的使用。不过这家杂志已经放弃了这种威胁,取而代之的是鼓励因为公众利益使用莱娜图。

        戴维·C·蒙森(David C.Munson),IEEE图像处理汇刊(IEEE Transactions on Image Processing)的主编, 在1996年1月引用了两个原因来说明莱娜图在科研领域流行的原因:1.该图适度的混合了细节、平滑区域、阴影和纹理,从而能很好的测试各种图像处理算法。2.Lenna是个美女,对于图象处理界的研究者来说,美女图可以有效的吸引他们来做研究。

2012-02-28 12:17:16 lj695242104 阅读数 3770

描述:频率滤波器是一种常见的滤波器,它是基于Fourier 变换演变过来的,它主要分为高通滤波器和低通滤波器。所谓高通滤波器就是只通过高频,滤除低频。反之低通滤波器就是滤除高频,保留低频。


现举例一个常见的频率滤波器——FFT Filter


Code:


  /** 
   * Constructor to set up an FFT object and then automatically 
   * apply the FFT algorithm.
   *
   * @param pixels  int array containing the image data.
   * @param w  The width of the image in pixels.
   * @param h  The height of the image in pixels.
   */
  public FFT(int [] pixels, int w, int h){
    input = new TwoDArray(pixels,w,h);
    intermediate = new TwoDArray(pixels,w,h);
    output = new TwoDArray(pixels,w,h);
    transform();
  }
  
  /**
   * Method to recursively apply the 1D FFT to a ComplexNumber array.
   *
   * @param  x  A ComplexNumber array containing a row or a column of
   * image data.
   * @return A ComplexNumber array containing the result of the 1D FFT.
   */
  static ComplexNumber [] recursiveFFT (ComplexNumber [] x){
    ComplexNumber z1,z2,z3,z4,tmp,cTwo;
    int n = x.length;
    int m = n/2;
    ComplexNumber [] result = new ComplexNumber [n];
    ComplexNumber [] even = new ComplexNumber [m];
    ComplexNumber [] odd = new ComplexNumber [m];
    ComplexNumber [] sum = new ComplexNumber [m];
    ComplexNumber [] diff = new ComplexNumber [m];
    cTwo = new ComplexNumber(2,0);
    if(n==1){
      result[0] = x[0];
    }else{
      z1 = new ComplexNumber(0.0, -2*(Math.PI)/n);
      tmp = ComplexNumber.cExp(z1);
      z1 = new ComplexNumber(1.0, 0.0);
      for(int i=0;i<m;++i){
	z3 = ComplexNumber.cSum(x[i],x[i+m]);
	sum[i] = ComplexNumber.cDiv(z3,cTwo);
	
	z3 = ComplexNumber.cDif(x[i],x[i+m]);
	z4 = ComplexNumber.cMult(z3,z1);
	diff[i] = ComplexNumber.cDiv(z4,cTwo);
	
	z2 = ComplexNumber.cMult(z1,tmp);
	z1 = new ComplexNumber(z2);
      }
      even = recursiveFFT(sum);
      odd = recursiveFFT(diff);
      
      for(int i=0;i<m;++i){
	result[i*2] = new ComplexNumber(even[i]);
	result[i*2 + 1] = new ComplexNumber(odd[i]);
      }
    }
    return result;
  }
   
  /**
   * Method to apply the 2D FFT by applying the recursive 1D FFT to the
   * columns and then the rows of image data.
   */ 
  void transform(){
      
      for(int i=0;i<input.size;++i){
	  intermediate.putColumn(i, recursiveFFT(input.getColumn(i)));
      }
      for(int i=0;i<intermediate.size;++i){
	  output.putRow(i, recursiveFFT(intermediate.getRow(i))); 
      }
      for(int j=0;j<output.values.length;++j){
	  for(int i=0;i<output.values[0].length;++i){
	      intermediate.values[i][j] = output.values[i][j];
	      input.values[i][j] = output.values[i][j];
	  }
      }
  }
}


Input Image:



Output Image:


1/3 cut-off frequency



1/2 cut-off frequency


总结:在此只举例一个低通滤波器的情形,如果在图像处理中仅仅使用低通滤波器来处理噪声是远远不够的,低通滤波器不仅处理了噪声中得高频信号也处理了图像有用信息的高频信号。因此,有待于发展后续更加的精细的处理工作。

2016-04-12 22:50:52 k_shmily 阅读数 3102

本文转自:http://www.wtoutiao.com/p/17bqT6G.html

图像处理知识库:http://www.wtoutiao.com/author/imageKB.html


导读

图像处理(image processing),用计算机对图像进行分析,以达到所需结果的技术。又称影像处理。图像处理一般指数字图像处理。

Scriptol列出了几种神奇的图像处理算法,让我们一起来看一下。

http://www.scriptol.com/programming/graphic-algorithms.php

一、像素图生成向量图的算法

数字时代早期的图片,分辨率很低。尤其是一些电子游戏的图片,放大后就是一个个像素方块。Depixelizing算法可以让低分辨率的像素图转化为高质量的向量图。

http://research.microsoft.com/en-us/um/people/kopf/pixelart/

上面的图就是像素图和转换后的向量图,可见,生成的向量图/矢量图的效果更好

像素图,也就是我们通常讲的1280*720什么的,就是每行多少个像素,每列多少个像素图片的像素数越多,颜色就越连贯美,图像就越清晰。这种图片被实际广泛应用于1990年代中期以前所有的电脑和电子游戏。另外,较老的桌面环境里的图标、小显示屏设备例如手机,都应用这类图片。由于那时的硬件条件限制,美工们被强迫用只有很少颜色分类的画板作图,并且要机械地手工设定每个像素的位置,而不是从更高分辨率作品自动缩放。

这些像素图实际上成为了一整代人的文化符号,如今虽然已经很少出现,但是由于每个像素手工布局使得每个像素都承载丰富的意义,是值得怀念的,情怀啊。如果能够将其重现至现在的各个分辨率的电子设备,岂不是也是一种乐趣?

这就引出了另外一种图:矢量图,也称为面向对象的图像或绘图图像。矢量文件中的图形元素称为对象。每个对象都是一个自成一体的实体,具有颜色、形状、轮廓、大小和位置等属性。

也就是说,矢量图是由很多独立的图像拼接起来的。放大后图像不会失真,和分辨率无关。

我们平常拍摄的图像,如果放大就会模糊。而一些条码里面的文字,logo打印出来的图像非常大,仍然非常清晰,就是因为我们拍摄的图像是位图,而一些设计出来的图像是矢量图。需要说明的是,矢量图只能通过软件设计来生成,因为设备拍照获取的图像是一个整体,不可能是相互独立分离的一些元素拼接成一幅图像。

矢量图是通过多个对象的组合生成的,对其中的每一个对象的纪录方式,都是以数学函数来实现的,也就是说,矢量图实际上并不是象位图那样纪录画面上每一点的信息,而是纪录了元素形状及颜色的算法,

当你打开一幅矢量图的时候,软件对图形象对应的函数进行运算,将运算结果[图形的形状和颜色]显示给你看。无论显示画面是大还是小,画面上的对象对应的算法是不变的,所以,即使对画面进行倍数相当大的缩放,其显示效果仍然相同[不失真]。

矢量图的主要格式有EPS,CDR,WMF,emf等,通常用到的jpg,bmp,png通通不是矢量图,而写论文杂志社肯定是要求矢量图的。


换言之:你只要知道矢量图可以任意放大,不变色,不模糊就行了。而位图是由无数的色彩点组成的图案,当被无限放大时会看到一块一块的像素色块,效果会失真。

   那怎么从像素图导出一张光滑、与分辨率无关的矢量图,它可以任意放大而不会失真。先来看看效果吧,就是这样的。有没有觉得很神奇?其实原理就一句话,检测边界并曲线拟合,但是过程是非常具有挑战性的。


此处简要介绍一下算法的原理,结合例子来简要说明,特意将英文子图说明注释保留。


上图从左至右就是基本的流程,中间四幅图展现的是放大的耳朵部位。有几个部分需要注意:

1 保留有意义的像素。当有些像素与周围像素的颜色信息不同时,它是图像的典型特征,需要保留,如找出图中的耳朵部位。

2 区分需要进行连续处理的部分,与不需要进行连续处理的部分。如图嘴巴是不需要进行连续处理的,要保持波动。而脑袋的轮廓需要进行连续光滑处理。

3 区分哪些相似像素应该被联系起来,哪些不需要。如图嘴巴处,考虑2*2四个像素,比如嘴巴部位下面的四个像素,红色应该被连接起来构成特征曲线的部分,而白色不应该。(具体是采用启发的方法,过于复杂不提)

解决了上面的问题后,就得到了一些线条,对这些线条进行样条插值可以得到最终的结果。(中间省略N多技术难题)。

二、黑白图片的着色算法

让老照片自动变成彩色的算法

http://www.cs.huji.ac.il/~yweiss/Colorization/index.html

当年一张黑白照片就珍贵的不行,现在手机拍出来的都是高清彩色图了。

好吧,那就当那当年的黑白图片,重新着个色可好?《Colorization using Optimization》。

该文章基于最简单的原理,那就是灰度值差不多的像素,应该具有差不多的颜色。既然在灰度空间相似,在彩色空间也应该相似。





有没有觉得很神奇,几乎是全自动的,用户只需要一些很简单的交互,就能将各个区域分割开来,然后分别上色。

比如下图,在需要上相同颜色的区域,用相同的笔触简要画出,就能识别各个区域,然后分别上色,毫无失真感有没有?!

当然,如果将各个区域平滑地分割出去,避免出现不连续的颜色边界,是问题的难点。那是图像分割的问题,堪称图像处理领域最难的几个方向之一。

三、图像自动合成

可以把许多图自动拼接成一幅图:《Sketch2Photo: Internet Image Montage》,绝逼的黑科技。

根据一张草图,选择原始照片,然后把它们合成在一起,生成新照片。这是清华大学的科研成果

http://cg.cs.tsinghua.edu.cn/montage/main.htm

四、消除阴影的算法

不留痕迹地去掉照片上某件东西的阴影的算法

Pyramid-Based Shadow Removal

http://www.cs.huji.ac.il/~danix/ShadowRemoval/index.html

五、HDR照片的算法

所谓"HDR照片",就是扩大亮部与暗部的对比效果,亮的地方变得非常亮,暗的地方变得非常暗,亮暗部的细节都很明显。

实现HDR的软件有很多,这里推荐G'MIC。它是GIMP图像编辑软件的一个插件,代码全部开源。

http://gmic.sourceforge.net/

六、消除杂物的算法

所谓"消除杂物",就是在照片上划出一块区域,然后用背景自动填补。Resynthesizer可以做到这一点,它也是GIMP的一个插件。

http://www.logarithmic.net/pfh/resynthesizer

七、美颜的算法

自动对容貌进行"美化"的算法

http://www.leyvand.com/beautification2008/


图片圆角化处理

阅读数 580

Lena与数字图像处理

阅读数 1526

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