图像处理tv方法

2018-09-06 14:09:07 weixin_42717711 阅读数 13016
  • 色彩空间转换

    通过本课程的学习,可以对数字成像系统知识整体上得到理解,在相机等成像产品的开发中,获得理论与实际的帮助。

    743人学习 姜卓
    免费试看

首先,搞图像处理,熟悉图像算法是必经之路,如果上过图像处理这门课的话,再好不过。如果没有,我推荐中科院研究生院刘定生老师的数字图像处理与分析(视频),这位老师上课引人入胜,值得推荐。其次,在这个阶段,配套的书籍自然是《冈萨雷斯版数字图像处理》这本书,最好同时用matlab软件,仿真每一个图像算法案例,推荐《matlab宝典》。大概花一个月时间,基本的图像算法,相信你已经学完了。第二阶段,希望你再次认真学习C++,推荐《C++ Primer》,因为以后我们开发程序,都是基于类的开发,什么虚函数,类的继承、多态、命名空间、文件的输入输出、模板STL都应非常熟悉。在这之后,VC++你也应该掌握,圣经级的书籍自然是孙鑫的《VC++深入详解》,大概花一个时间,将书上每一个代码都敲一边,消息的映射机制,尤其要非常熟悉,MFC的框架结构也应明白。在此阶段,有时间的话,看看中科院研究生院杨力祥老师的高级windows程序设计(视频),这些代码开发都是基于VC6.0的。

以上如果你都搞明白了,就进入重头戏了。将图像处理算法和代码结合起来,进行开发。首推北航老师谢凤英,赵主培主编的《Visual C++数字图像处理》这本书,将上面的代码都敲一边,你会有不一样的感觉。

最后一个阶段,因为在实际的开发过程中,不可能每一基本算法都要自己写,前人已经写好了。所以推荐大家使用opencv这个开源库,他实现了大多数图像算法,实际开发中,用他的函数就够了,推荐书籍《学习opencv》,《opencv教程》,视频自然是庞峰老师的视频,大家可以在opencv中文论坛上免费观看。至此,该掌握的工具你已经掌握了,但是将MFC和opencv结合起来开发,最好是要有一个项目,你会理解许多。下面是一些大牛:

第一波是一些资源丰富的博客,有算法介绍,也有代码实现:


1、毕业于荷兰特温特大学的Dirk-Jan Kroon博士,在Mathworks的FileExchange上的链接,曾经到访过他原来读书时的主页,当时有句话对他的评价是,他非常喜欢计算机编程,这个真不假,下面这个链接里有他用Matlab写成的近百个程序源码,质量非常高,而且涉猎广泛。

http://www.mathworks.com/matlabcentral/fileexchange/authors/29180


2、这是研究 image matting(中文叫抠图——这名字真难听,不知道是谁始作俑者)必去的一个网站,里面有大量关于这个主题内容的介绍,包括最新的成果,评测和对比。
http://www.alphamatting.com/


3、laviewpbt的专栏,他有两个基本同步的博客,一个在CSDN,一个在博客园,自称是“一心无二用,本人只专注于基础图像算法的实现与优化,如图像增强、滤镜、分割、解码编码等,无心恋及图像识别。 ”。博客中很少有提供完整的源代码,但是对理论算法的介绍非常到位,我也同意博主的看法,如果真的对算法理解到位了,写代码处理并不是难事。
http://www.cnblogs.com/Imageshop/


4、Rachel Zhang的专栏(浙大计算机女硕士),CSDN博客排名百名以内的名博,里面有大量图像处理和计算机视觉的资料,有算法讲解,也有很多代码实现(OpenCV居多,少量Matlab)
http://blog.csdn.net/abcjennifer/article/category/1173803/2


5、小魏的修行路(又一个女学霸,博主应该是北大女硕士),博客都是图文并茂的,很详细很用心,代码实现上也是用OpenCV的居多。
http://blog.csdn.net/xiaowei_cqu/


6、非常棒的网站,超多资源。IPOL is a research journal of image processing and image analysis. Each article contains a text on an algorithm and its source code。讨论了超过20个大的Topics,具体每个Topics里面还有许多具体的实现分支,配有可供研究的源代码。研究图像处理不可不看的网站。

http://www.ipol.im/

 

7、LIBROW,口号是The Helpful Mathematics,算法文章 && C++代码(算法偏基础),适合初学者参考。

http://www.librow.com/articles

 

8、采石工的博客

数学功底深厚、原理推导明晰的博客。非常值得推荐!

http://www.cnblogs.com/quarryman/

 

第二波是我所关注的一些研究方向上比较前沿的学者主页:

 

1、KAZE特征检测作者的主页,里面有文章,也有代码实现。Pablo F. Alcantarilla博士人非常Nice,我给他写Email讨论问题,基本上8个小时之内就能收到回复,也非常感谢他提供的一些参考资料。

http://www.robesafe.com/personal/pablo.alcantarilla/kaze.html

 

2、在去噪领域中当前最成功的算法莫过于BM3D系列(当然还有BM4D等等),下面这个是项目的主页,非常值得推荐,对于研究降噪问题的同学实在应该仔细看看。

http://www.cs.tut.fi/~foi/GCF-BM3D/

 

3、布朗大学Douglas Lanman博士的主页,很多有意思的成果,部分有代码资源下载
http://mesh.brown.edu/dlanman/courses.html

 

4、两位以色列学者(犹太人)的主页。经验中,大部分Paper的作者会在自己的网站上贴出文章,但很少附有代码,如果你自己去写个代码,很多都无法达到作者paper中给出的效果,吹水的可能性极大。但是在研究Close-form soluting 的图像matting时,看到了以色列女学者Anat Levin的主页,作者就提供有matlab代码,很值得推荐。
http://www.wisdom.weizmann.ac.il/~levina/
另外一个以色列学者(以色列理工的Guy Gilboa教授)的主页(有关于TV去噪的代码)。
http://visl.technion.ac.il/~gilboa/PDE-filt/tv_denoising.html

2014-01-20 14:57:46 xiaowei_cqu 阅读数 13523
  • 色彩空间转换

    通过本课程的学习,可以对数字成像系统知识整体上得到理解,在相机等成像产品的开发中,获得理论与实际的帮助。

    743人学习 姜卓
    免费试看

TV去噪主页:http://visl.technion.ac.il/~gilboa/PDE-filt/tv_denoising.html

可以下载MATLAB代码。

function J=tv(I,iter,dt,ep,lam,I0,C)
%% Private function: tv (by Guy Gilboa).
%% Total Variation denoising.
%% Example: J=tv(I,iter,dt,ep,lam,I0)
%% Input: I    - image (double array gray level 1-256),
%%        iter - num of iterations,
%%        dt   - time step [0.2],
%%        ep   - epsilon (of gradient regularization) [1],
%%        lam  - fidelity term lambda [0],
%%        I0   - input (noisy) image [I0=I]
%%       (default values are in [])
%% Output: evolved image

if ~exist('ep')
   ep=1;
end
if ~exist('dt')
   dt=ep/5;  % dt below the CFL bound
end
if ~exist('lam')
   lam=0;
end
if ~exist('I0')
	I0=I;
end
if ~exist('C')
	C=0;
end
[ny,nx]=size(I); ep2=ep^2;

for i=1:iter,  %% do iterations
   % estimate derivatives
   I_x = (I(:,[2:nx nx])-I(:,[1 1:nx-1]))/2;
	I_y = (I([2:ny ny],:)-I([1 1:ny-1],:))/2;
	I_xx = I(:,[2:nx nx])+I(:,[1 1:nx-1])-2*I;
	I_yy = I([2:ny ny],:)+I([1 1:ny-1],:)-2*I;
	Dp = I([2:ny ny],[2:nx nx])+I([1 1:ny-1],[1 1:nx-1]);
	Dm = I([1 1:ny-1],[2:nx nx])+I([2:ny ny],[1 1:nx-1]);
	I_xy = (Dp-Dm)/4;
   % compute flow
   Num = I_xx.*(ep2+I_y.^2)-2*I_x.*I_y.*I_xy+I_yy.*(ep2+I_x.^2);
   Den = (ep2+I_x.^2+I_y.^2).^(3/2);
   I_t = Num./Den + lam.*(I0-I+C);
   I=I+dt*I_t;  %% evolve image by dt
end % for i
%% return image
%J=I*Imean/mean(mean(I)); % normalize to original mean
J=I;


另外有博主谢了C++的代码:经典的变分法图像去噪的C++实现 ,不过个人感觉写的不太简洁。稍稍修改了一下,新版代码出炉:

  //TV去噪函数
Mat TVDenoising(Mat img, int iter)
{
	int ep = 1;
	int nx=img.cols;
	int ny = img.rows;
	double dt = 0.25f;
	double lam = 0.0;
	int ep2 = ep*ep;

	double** image = newDoubleMatrix(nx, ny);
	double** image0 = newDoubleMatrix(nx, ny);

	for(int i=0;i<ny;i++){
		uchar* p=img.ptr<uchar>(i);
		for(int j=0;j<nx;j++){
			image0[i][j]=image[i][j]=(double)p[j];
		}
	}
	//double** image_x = newDoubleMatrix(nx, ny);   //I_x = ( I(:,[2:nx nx]) - I(:,[1 1:nx-1]))/2;
	//double** image_xx = newDoubleMatrix(nx, ny);   //I_xx = I(:,[2:nx nx])+I(:,[1 1:nx-1])-2*I;
	//double** image_y = newDoubleMatrix(nx, ny);   //I_y = (I([2:ny ny],:)-I([1 1:ny-1],:))/2;
	//double** image_yy = newDoubleMatrix(nx, ny);   //I_yy = I([2:ny ny],:)+I([1 1:ny-1],:)-2*I;
	//double** image_dp = newDoubleMatrix(nx, ny);   //Dp = I([2:ny ny],[2:nx nx])+I([1 1:ny-1],[1 1:nx-1
	//double** image_dm = newDoubleMatrix(nx, ny);   //Dm = I([1 1:ny-1],[2:nx nx])+I([2:ny ny],[1 1:nx-1]);
	//double** image_xy = newDoubleMatrix(nx, ny);   //I_xy = (Dp-Dm)/4;
	//double** image_num = newDoubleMatrix(nx, ny);   //Num = I_xx.*(ep2+I_y.^2)-2*I_x.*I_y.*I_xy+I_yy.*(ep2+I_x.^2);
	//double** image_den = newDoubleMatrix(nx, ny);   //Den = (ep2+I_x.^2+I_y.^2).^(3/2);

	//////////////////////////////////////////////////////////////////////////
	//对image进行迭代iter次
	//iter = 80;
	for (int t = 1; t <= iter; t++){

		//for (int i = 0; i < ny; i++){
		//	for (int j = 0; j < nx; j++){
		//		//I_x  = (I(:,[2:nx nx])-I(:,[1 1:nx-1]))/2;
		//		//I_y  = (I([2:ny ny],:)-I([1 1:ny-1],:))/2;
		//		//I_xx = I(:,[2:nx nx])+I(:,[1 1:nx-1])-2*I;
		//		//I_yy = I([2:ny ny],:)+I([1 1:ny-1],:)-2*I;
		//		//Dp   = I([2:ny ny],[2:nx nx])+I([1 1:ny-1],[1 1:nx-1]);
		//		//Dm   = I([1 1:ny-1],[2:nx nx])+I([2:ny ny],[1 1:nx-1]);
		//		//I_xy = (Dp-Dm)/4;
		//		int tmp_i1=(i+1)<ny ? (i+1) :(ny-1);
		//		int tmp_j1=(j+1)<nx ? (j+1): (nx-1);
		//		int tmp_i2=(i-1) > -1 ? (i-1) : 0;
		//		int tmp_j2=(j-1) > -1 ? (j-1) : 0;
		//		image_x[i][j] = (image[i][tmp_j1] - image[i][tmp_j2])/2;
		//		image_y[i][j]= (image[tmp_i1][j]-image[tmp_i2][j])/2;
		//		image_xx[i][j] = image[i][tmp_j1] + image[i][tmp_j2]- image[i][j]*2;
		//		image_yy[i][j]= image[tmp_i1][j]+image[tmp_i2][j] - image[i][j]*2;
		//		image_dp[i][j]=image[tmp_i1][tmp_j1]+image[tmp_i2][tmp_j2];
		//		image_dm[i][j]=image[tmp_i2][tmp_j1]+image[tmp_i1][tmp_j2];
		//		image_xy[i][j] = (image_dp[i][j] - image_dm[i][j])/4;
		//		image_num[i][j] = image_xx[i][j]*(image_y[i][j]*image_y[i][j] + ep2) 
		//			- 2*image_x[i][j]*image_y[i][j]*image_xy[i][j] + image_yy[i][j]*(image_x[i][j]*image_x[i][j] + ep2);
		//		image_den[i][j] = pow((image_x[i][j]*image_x[i][j] + image_y[i][j]*image_y[i][j] + ep2), 1.5);
		//		image[i][j] += dt*(image_num[i][j]/image_den[i][j] + lam*(image0[i][j] - image[i][j]));
		//	}
		//}
		for (int i = 0; i < ny; i++){
			for (int j = 0; j < nx; j++){
				int tmp_i1=(i+1)<ny ? (i+1) :(ny-1);
				int tmp_j1=(j+1)<nx ? (j+1): (nx-1);
				int tmp_i2=(i-1) > -1 ? (i-1) : 0;
				int tmp_j2=(j-1) > -1 ? (j-1) : 0;
				double tmp_x = (image[i][tmp_j1] - image[i][tmp_j2])/2; //I_x  = (I(:,[2:nx nx])-I(:,[1 1:nx-1]))/2;
				double tmp_y= (image[tmp_i1][j]-image[tmp_i2][j])/2; //I_y  = (I([2:ny ny],:)-I([1 1:ny-1],:))/2;
				double tmp_xx = image[i][tmp_j1] + image[i][tmp_j2]- image[i][j]*2; //I_xx = I(:,[2:nx nx])+I(:,[1 1:nx-1])-2*I;
			    double tmp_yy= image[tmp_i1][j]+image[tmp_i2][j] - image[i][j]*2; //I_yy = I([2:ny ny],:)+I([1 1:ny-1],:)-2*I;
				double tmp_dp=image[tmp_i1][tmp_j1]+image[tmp_i2][tmp_j2]; //Dp   = I([2:ny ny],[2:nx nx])+I([1 1:ny-1],[1 1:nx-1]);
				double tmp_dm=image[tmp_i2][tmp_j1]+image[tmp_i1][tmp_j2]; //Dm   = I([1 1:ny-1],[2:nx nx])+I([2:ny ny],[1 1:nx-1]);
				double tmp_xy = (tmp_dp - tmp_dm)/4; //I_xy = (Dp-Dm)/4;
				double tmp_num = tmp_xx*(tmp_y*tmp_y + ep2) 
					- 2*tmp_x*tmp_y*tmp_xy +tmp_yy*(tmp_x*tmp_x + ep2); //Num = I_xx.*(ep2+I_y.^2)-2*I_x.*I_y.*I_xy+I_yy.*(ep2+I_x.^2);
				double tmp_den= pow((tmp_x*tmp_x + tmp_y*tmp_y + ep2), 1.5); //Den = (ep2+I_x.^2+I_y.^2).^(3/2);
				image[i][j] += dt*(tmp_num/tmp_den+ lam*(image0[i][j] - image[i][j]));
			}
		}


	}

	Mat new_img;
	img.copyTo(new_img);
	for(int i=0;i<img.rows;i++){
		uchar* p=img.ptr<uchar>(i);
		uchar* np=new_img.ptr<uchar>(i);
		for(int j=0;j<img.cols;j++){
			int tmp=(int)image[i][j];
			tmp=max(0,min(tmp,255));
			np[j]=(uchar)(tmp);
		}
	}


	//////////////////////////////////////////////////////////////////////////
	//删除内存
	//deleteDoubleMatrix(image_x, nx, ny);
	//deleteDoubleMatrix(image_y, nx, ny);
	//deleteDoubleMatrix(image_xx, nx, ny);
	//deleteDoubleMatrix(image_yy, nx, ny);
	//deleteDoubleMatrix(image_dp, nx, ny);
	//deleteDoubleMatrix(image_dm, nx, ny);
	//deleteDoubleMatrix(image_xy, nx, ny);
	//deleteDoubleMatrix(image_num, nx, ny);
	//deleteDoubleMatrix(image_den, nx, ny);
	deleteDoubleMatrix(image0, nx, ny);
	deleteDoubleMatrix(image, nx, ny);

	//imshow("Image",img);
	//imshow("Denosing",new_img);

	return new_img;
}


 

(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu 未经允许请勿用于商业用途)

 

2015-03-14 10:12:22 hujingshuang 阅读数 13292
  • 色彩空间转换

    通过本课程的学习,可以对数字成像系统知识整体上得到理解,在相机等成像产品的开发中,获得理论与实际的帮助。

    743人学习 姜卓
    免费试看

前言图像修复是一项非常有意义的研究工作,比如我们生活中的照片被污染,再比如名贵字画、国家文物壁画等珍贵物品被破坏,这些都需要图像修复工作来完成。

简介整体变分(Total Variation)的方法最早是用来对受到噪声污染的图像进行降噪的,在这方面的应用最早是由L.Rudin和S.Osher等人在1992年提出的,2002年Chan等人把TV模型推广到图像修补中,并提出了基于TV模型的图像修补方法,同时说明了TV修补模型的缺点,进一步提出了CDD修补模型(curvature driven diffusions),此修补模型改正了TV修补模型的缺陷,对图像的修补具有很好的效果。

一、TV模型介绍

如图所示:D区域是被污染区(待修复),E是D的邻域


下面直接给出TV模型的数学公式:

                      ①

其中:u是图像中的像素点,λ为设定的参数

在该模型基础上,考虑到噪声的影响,边界E区域产生的噪声不能超过一定的范围;根据最佳猜测和贝叶斯理论,要求图像u在满足约束条件下使它的能量泛函最小,因此约束条件记做:公式②。根据拉格朗日乘数法,将①②方程转化成为一个求极值的方程,对其求导数并令其等于0,可得到如下方程:


其中:div代表散度(关于图像中的散度解释,可见此处:在图像处理中,散度 div 具体的作用是什么?


由于图像是离散的数值,故可看做如下构成。其中:O为污染点,邻域B=(N,S,W,E),半像素邻域B' =(n,s,w,e)。


因此,离散化后可得到表达式:


化简得到最终的表达式:


其中:λe(O)为中心O处的λ参数,与上λe一致;uo为O点修复后的像素,另一个为O点修复前的原始像素。将上式迭代,知道达到较好的修复效果。

到此,TV模型的理论推导已完成。接下来就是要编程实现其功能。

matlab源码实现:

img=double(imread('lena.jpg'));
mask=imread('mask.jpg');
a1=find(mask>127);
b1=find(mask<=127);
mask(a1)=0;
mask(b1)=255;
[m n]=size(img);
for i=1:m
    for j=1:n
        if mask(i,j)==0
           img(i,j)=0; 
        end
    end
end
imshow(img,[]);     %合成的需要修复的图像

lambda=0.2;
a=0.5;%避免分母为0
imgn=img;
for l=1:1500         %迭代次数
    for i=2:m-1
        for j=2:n-1
            if mask(i,j)==0     %如果当前像素是被污染的像素,则进行处理
                Un=sqrt((img(i,j)-img(i-1,j))^2+((img(i-1,j-1)-img(i-1,j+1))/2)^2);
                Ue=sqrt((img(i,j)-img(i,j+1))^2+((img(i-1,j+1)-img(i+1,j+1))/2)^2);
                Uw=sqrt((img(i,j)-img(i,j-1))^2+((img(i-1,j-1)-img(i+1,j-1))/2)^2);
                Us=sqrt((img(i,j)-img(i+1,j))^2+((img(i+1,j-1)-img(i+1,j+1))/2)^2);

                Wn=1/sqrt(Un^2+a^2);
                We=1/sqrt(Ue^2+a^2);
                Ww=1/sqrt(Uw^2+a^2);
                Ws=1/sqrt(Us^2+a^2);

                Hon=Wn/((Wn+We+Ww+Ws)+lambda);
                Hoe=We/((Wn+We+Ww+Ws)+lambda);
                How=Ww/((Wn+We+Ww+Ws)+lambda);
                Hos=Ws/((Wn+We+Ww+Ws)+lambda);

                Hoo=lambda/((Wn+We+Ww+Ws)+lambda);
                value = Hon*img(i-1,j)+Hoe*img(i,j+1)+How*img(i,j-1)+Hos*img(i+1,j)+Hoo*img(i,j);
                imgn(i,j)= value;
            end
        end
    end
    img=imgn; 
end
figure;
imshow(img)
opencv源码实现:

#include <iostream>
#include <stdlib.h>
#include <cv.h>
#include <math.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

int main(void)
{
	//读取原始图像及掩模图像
	IplImage *src_uint8 = cvLoadImage("src.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	IplImage *mask = cvLoadImage("mask.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	//合成需要修复的图像
	int M = mask->height;
	int N = mask->width;
	int i, j;
	CvMat *src = cvCreateMat(M, N, CV_32FC1);//存放浮点图像
	cvConvert(src_uint8, src);
	for (i = 0; i < M; i++)
	{
		for (j = 0; j < N; j++)
		{
			if ((mask->imageData + i * mask->widthStep)[j] < 0)//理解此处判别条件,根据情况自行更改
			{
				((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] = 0.0;
			}
			if (((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] < 0)
			{
				((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] += 256.0;
			}
		}
	}
	cvConvert(src, src_uint8);
	cvShowImage("需要修复的图像", src_uint8);
	cvWaitKey(0);

	double t = getTickCount();//当前滴答数
	float lambda = 0.2;
	float delta = 0.5;
	float UO, UN, UW, US, UE, UNE, UNW, USW, USE;
	float Un, Ue, Uw, Us;
	float Wn, We, Ww, Ws;
	float Hon, Hoe, How, Hos;
	float Hoo;
	int iteration = 500;
	while(iteration)
	{
		for (i = 1; i < M - 1; i++)
		{
			for (j = 1; j < N - 1; j++)
			{
				if (((char *)(mask->imageData + i * mask->widthStep))[j] < 0)//坏损区
				{
					UO = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j];
					UN = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j];
					US = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j];
					UE = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j+1];
					UW = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j-1];

					UNE = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j+1];
					UNW = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j-1];
					USE = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j+1];
					USW = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j-1];

					Un = sqrt((UO - UN) * (UO - UN) + ((UNW - UNE) / 2.0) * ((UNW - UNE) / 2.0));
					Ue = sqrt((UO - UE) * (UO - UE) + ((UNE - USE) / 2.0) * ((UNE - USE) / 2.0));
					Uw = sqrt((UO - UW) * (UO - UW) + ((UNW - USW) / 2.0) * ((UNW - USW) / 2.0));
					Us = sqrt((UO - US) * (UO - US) + ((USW - USE) / 2.0) * ((USW - USE) / 2.0));

					Wn = 1.0/sqrt(Un * Un + delta * delta);
					We = 1.0/sqrt(Ue * Ue + delta * delta);
					Ww = 1.0/sqrt(Uw * Uw + delta * delta);
					Ws = 1.0/sqrt(Us * Us + delta * delta);

					Hon = Wn/(Wn+We+Ww+Ws+lambda);
					Hoe = We/(Wn+We+Ww+Ws+lambda);
					How = Ww/(Wn+We+Ww+Ws+lambda);
					Hos = Ws/(Wn+We+Ww+Ws+lambda);

					Hoo = lambda/(Wn+We+Ww+Ws+lambda);
					((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j]=(Hon*UN+Hoe*UE+How*UW+Hos*US+Hoo*UO);
				}
			}
		}
		iteration--;
	}
	cvConvert(src, src_uint8);
	t = ((double)getTickCount() - t)/getTickFrequency();
	printf("算法用时:%f秒\n", t);
	cvShowImage("修复结果", src_uint8);
	cvWaitKey(0);
}
由于迭代次数和浮点数的运算,使得算法时间较长,效果如下,仔细观察可以看出仍有细节处修复效果不是很理想。在TV模型之后,又出现了许多改进的TV模型,在速度和效果上都比理想,此处不深入探讨。


本文所需的实验材料都已打包上传,点击此处下载:http://download.csdn.net/detail/hujingshuang/8500553

如有疑问请加群:数字图像处理群:389011389

特别注意:

1、本博客例程仅做学习交流用,切勿用于商业用途。

2、欢迎交流,转载请注明出处:http://blog.csdn.net/hujingshuang/article/details/44257179

2016-02-26 17:48:13 baimafujinji 阅读数 69723
  • 色彩空间转换

    通过本课程的学习,可以对数字成像系统知识整体上得到理解,在相机等成像产品的开发中,获得理论与实际的帮助。

    743人学习 姜卓
    免费试看

什么是数字图像处理?历史、以及它所研究的内容。

 

说起图像处理,你会想到什么?你是否真的了解这个领域所研究的内容。纵向来说,数字图像处理研究的历史相当悠久;横向来说,数字图像处理研究的话题相当广泛。

数字图像处理的历史可以追溯到近百年以前,大约在1920年的时候,图像首次通过海底电缆从英国伦敦传送到美国纽约。图像处理的首次应用是为了改善伦敦和纽约之间海底电缆发送的图片质量,那时就应用了图像编码,被编码后的图像通过海底电缆传送至目的地,再通过特殊设备进行输出。这是一次历史性的进步,传送一幅图片的时间从原来的一个多星期减少到了3小时。

1950年,美国的麻省理工学院制造出了第一台配有图形显示器的电子计算机——旋风I号(Whirlwind I)。旋风I号的显示器使用一个类似于示波器的阴极射线管(Cathode Ray Tube,CRT)来显示一些简单的图形。1958年美国Calcomp公司研制出了滚筒式绘图仪,GerBer公司把数控机床发展成为平板式绘图仪。在这一时期,电子计算机都主要应用于科学计算,而为这些计算机配置的图形设备也仅仅是作为一种简单的输出设备。

随着计算机技术的进步,数字图像处理技术也得到了很大的发展。1962年,当时还在麻省理工学院攻读博士学位的伊凡·苏泽兰(Ivan Sutherland)成功开发了具有划时代意义的“画板”(Sketchpad)程式。而这正是有史以来第一个交互式绘图系统,同时这也是交互式电脑绘图的开端。从此计算机和图形图像被更加紧密地联系到了一起。鉴于伊凡·苏泽兰为计算机图形学创立所做出的杰出贡献,他于1988年被授予计算机领域最高奖——图灵奖。

1964年,美国加利福尼亚的喷气推进实验室用计算机对“旅行者七号”太空船发回的大批月球照片进行处理,以校正航天器上摄影机中各种类型的图像畸变,收到了明显的效果。在后来的宇航空间技术中,数字图像处理技术都发挥了巨大的作用。

到了20世纪60年代末期,数字图像处理已经形成了比较完善的学科体系,这套理论在20世纪70年代发展得十分迅速,并开始应用于医学影像和天文学等领域。1972年,美国物理学家阿伦·马克利奥德·柯麦科(Allan MacLeodCormack)和英国电机工程师戈弗雷·纽博尔德·豪恩斯弗尔德(Godfrey Newbold Housfield)发明了轴向断层术,并将其用于头颅诊断。世界第一台X射线计算机轴向断层摄影装置由EMI公司研制成功,这也就是人们通常所说的CT(Computer Tomograph)。CT可通过一些算法用感知到的数据去重建通过物体的“切片”图像。这些图像组成了物体内部的再现图像,也就是根据人的头部截面的投影,经计算机处理来进行图像重建。鉴于CT对于医学诊断技术的发展所起到的巨大推动作用,柯麦科和豪恩斯弗尔德于1979年获得了诺贝尔生理或医学奖。

随后在2003年,诺贝尔生理或医学奖的殊荣再次授予了两位在医疗影像设备研究方面做出杰出贡献的科学家——美国化学家保罗·劳特伯尔(Paul Lauterbur)和英国物理学家彼得·曼斯菲尔(Peter Mansfield)。两位获奖者在利用磁共振成像(Magnetic Resonance Imaging,MRI)显示不同结构方面分别取得了开创性成就。瑞典卡罗林斯卡医学院称,这两位科学家在MRI领域的开创性工作,代表了医学诊疗和研究的重大突破。而事实上,核磁共振的成功同样也离不开数字图像处理方面的发展。即使在今天,诸如MRI图像降噪等问题依然是数字图像处理领域的热门研究方向。

说到数字图像的发展历程,还有一项至关重要的成果不得不提,那就是电荷耦合元件(Charge-coupled Device,CCD)。CCD最初是由美国贝尔实验室的科学家维拉德·波义耳(Willard Sterling Boyle)和乔治·史密斯(George Elwood Smith)于1969年发明的。CCD的作用就像胶片一样,它能够把光学影像转化为数字信号。今天人们所广泛使用的数码照相机、数码摄影机和扫描仪都是以CCD为基础发展而来的。换句话说,我们现在所研究的数字图像主要也都是通过CCD设备获取的。由于波义耳和史密斯在CCD研发上所做出的巨大贡献,他们两人共同荣获了2009年度的诺贝尔物理学奖。

数字图像处理在今天是非常热门的技术之一,生活中无处不存在着它的影子,可以说它是一种每时每刻都在改变着人类生活的技术。但长久以来,很多人对数字图像处理存在着较大的曲解,人们总是不自觉地将图像处理和Photoshop联系在一起。大名鼎鼎的Photoshop无疑是当前使用最为广泛的图像处理工具。类似的软件还有Corel公司生产的CorelDRAW等软件。

尽管Photoshop是一款非常优秀的图像处理软件,但它的存在并不代表数字图像处理的全部理论与方法。它所具有的功能仅仅是数字图像处理中的一部分。总的来说,数字图像处理研究的内容主要包括如下几个方面:

  • 1)图像获取和输出
  • 2)图像编码和压缩
  • 3)图像增强与复原
  • 4)图像的频域变换
  • 5)图像的信息安全
  • 6)图像的区域分割
  • 7)图像目标的识别
  • 8)图像的几何变换

但图像处理的研究内容,又不仅限于上述内容!所以说图像处理的研究话题是相当宽泛的。那现在图像处理都应用在哪些领域呢?或许我们可能熟知的例子有(当然,你应该还能举出更多例子):

  • 1)一些专业图像处理软件:Photoshop、CorelDRAW……
  • 2)一些手机APP应用:美图秀秀、玩图……
  • 3)一些医学图像处理应用:MRI、彩超图像处理……
  • 4)一些制造业上的应用:元器件检测、瑕疵检测……
  • 5)一些摄像头、相机上的应用:夜间照片的质量改善……
  • 6)一些电影工业上是应用:换背景、电影特技……

 

什么样的人会去学(或者需要学)图像处理?

 

1)如果你是我上述那些应用领域的从业者,你当然需要掌握图像方面的理论和技术;2)相关专业的研究人员、大专院校的博士生、研究生。

所谓相关专业又是指什么呢?这个答案也可能相当宽泛,例如(但不仅限于此):Computer Science, Software Engineering, Electronic Engineering, Biomedical Engineering, Automation, Control, Applied Mathematics……

 

如何学好图像处理——我的一些箴言

 

1)对于初级入门者

 

一个扎实的基础和对于图像处理理论的完整的、系统的整体认识对于后续的深入研究和实践应用具有非常非常重要的意义。

我经常喜欢拿武侠小说《天龙八部》中的一段情节来向读者说明此中的道理,相信读者对这部曾经被多次搬上银幕的金庸作品已经耳熟能详了。书中讲到有个名叫鸠摩智的番僧一心想练就绝世武学,而且他也算是个相当勤奋的人了。但是,他错就错在太过于急功近利,甚至使用道家的小无相功来催动少林绝技。看上去威力无比,而且可以在短时间内“速成”,但实则后患无穷。最终鸠摩智走火入魔,前功尽废,方才大彻大悟。这个故事其实就告诉我们打牢基础是非常重要的,特别是要取得更长足的发展,就更是要对基本原理刨根问底,力求甚解,从而做到庖丁解牛,游刃有余。

一些看似高深的算法往往是许多基础算法的组合提升。例如,令很多人望而却步的SIFT特征构建过程中,就用到了图像金字塔、直方图、高斯滤波这些非常非常基础的内容。但是,它所涉及的基础技术显然有好几个,如果缺乏对图像处理理论的系统认识,你可能会感觉事倍功半。因为所有的地方好像都是沟沟坎坎。

关于课程——

在这个阶段其实对于数学的要求并不高,你甚至可以从一些感性的角度去形象化的理解图像处理中很多内容(但不包括频域处理方面的内容)。具体到学习的建议,如果有条件(例如你还在高校里读书)你最好能选一门图像处理方面的课程,系统地完整的地去学习一下。这显然是入门的最好办法。如此一来,在建立一个完整的、系统的认知上相当有帮助。如果你没办法在学校里上一门这样的课,网上的一些公开课也可以试试。但现在中文MOOC上还没有这方面的优质课程推荐。英文的课程则有很多,例如美国加州伦斯勒理工学院Rich教授的数字图像处理公开课——https://www.youtube.com/channel/UCaiJlKxXamoODQtlx486qJA?spfreload=10。

关于教材——

显然,只听课其实还不太够,如果能一并读一本书就最好了。其实不用参考很多书,只要一本,你能从头读到尾就很好了。如果你没有条件去上一门课,那读一本来完整的自学一下就更有必要了。这个阶段,去网上到处找博客、看帖子是不行的。因为你特别需要在这个阶段对这门学问建立一个系统的完整的知识体系。东一块、西一块的胡拼乱凑无疑是坑你自己,你的知识体系就像一个气泡,可能看起来很大,但是又脆弱的不堪一击。

现在很多学校采用冈萨雷斯的《数字图像处理》一书作为教材。这是一本非常非常经典的著作。但是我必须要提醒读者:

1)这是一本专门为Electronic Engineering专业学生所写的书。它需要有信号与系统、数字信号处理这两门课作为基础。如果你没有这两门课的基础,你读这本书要么是看热闹,要么就是看不懂。

下面是冈书中的一张插图。对于EE的学生来说,这当然不是问题。但是如果没有我说的那两门课的基础,其实你很难把握其中的精髓。H和h,一个大小一个小写,冈书中有的地方用H,有的地方用h,这都是有很深刻用意的。原作者并没有特别说明它们二者的区别,因为他已经默认你应该知道二者是不同的。事实上,它们一个表示频域信号,一个表示时域信号,这也导致有时候运算是卷积,有时候运算是乘法(当然这跟卷积定理有关)。所以我并不太建议那些没有这方面基础的学生在自学的时候读这本书。

 

2)冈萨雷斯教授的《数字图像处理》第一版是在1977年出版的,到现在已经快40年了;现在国内广泛使用的第二版是2002年出版的(第三版是2007年但是其实二者差异并不大),到现在也有20年左右的时间了。事实上,冈萨雷斯教授退休也有快30年了。所以这本书的内容已经偏于陈旧。数字图像处理这个领域的发展绝对是日新月异,突飞猛进的。特别在最近二三十年里,很多新思路,新方法不断涌现。如果你看了我前面推荐的Rich教授的公开课(这也是当前美国大学正在教学的内容),你一下子就会发现,原来我们的教育还停留在改革开放之前外国的水平上。这其实特别可怕。所以我觉得冈萨雷斯教授的《数字图像处理》作为学习过程中的一个补充还是不错的,但是如果把它作为主参考,那真的就是:国外都洋枪洋炮了,我们还在大刀长矛。

 

那么现在问题来了,对于图像处理学习者而言到底看什么书好呢?我的意见是你可以选择下面两本书中的任何一本《数字图像处理原理与实践(Matlab版)》,以及《数字图像处理:技术详解与Visual C++实践》,当然选择的标准之一就是到底你更擅长使用MATLAB还是C++。

   

 

 

 

2)对于中级水平者

 

纸上得来终觉浅,绝知此事要躬行。对于一个具有一定基础的,想更进一步的中级水平的人来说,这个阶段最重要的就是增强动手实践的能力。

还是说《天龙八部》里面的一个角色——口述武功、叹为观止的王语嫣。王语嫣的脑袋里都是武功秘籍,但问题是她从来都没练过一招一式。结果是,然并卵。所以光说不练肯定不灵啊。特别是,如果你将来想从事这个行业,结果一点代码都不会写,那几乎是不可想象的。学习阶段,最常被用来进行算法开发的工具是Matlab和OpenCV。你可以把这两个东西都理解为一个相当完善的库。当然,在工业中C++用得更多,所以Matlab的应用还是很有限的。前面我们讲到,图像处理研究内容其实包括:图像的获取和编解码,但使用Matlab和OpenCV就会掩盖这部分内容的细节。你当然永远不会知道,JPEG文件到底是如何被解码的。

如果你的应用永远都不会涉及这些话题,那么你一直用Matlab和OpenCV当然无所谓。例如你的研究领域是SIFT、SURF这种特征匹配,可以不必理会编解码方面的内容。但是如果你的研究话题是降噪或者压缩,可能你就绕不开这些内容。最开始学的时候,如果能把这部分内容也自己写写,可能会加深你的理解。以后做高级应用开发时,再调用那些库。所以具体用什么,要不要自己写,是要视你所处的阶段和自己的实际情况而定的。以我个人的经验,在我自学的时候,我就动手写了Magic House,我觉得这个过程为我奠定了一个非常夯实的基础,对于我后续的深入研究很有帮助。

 

下面这个文中,我给出了一些这方面的资源,代码多多,很值得参考学习:图像处理与机器视觉网络资源收罗

http://blog.csdn.net/baimafujinji/article/details/32332079

 

3)对于高级进阶者

 

到了这个程度的读者,编程实现之类的基本功应该不在话下。但是要往深,往高去学习、研究和开发图像处理应用,你最需要的内容就变成了数学。这个是拦在很多处于这个阶段的人面前的一大难题。如果你的专业是应用数学,当然你不会感觉有问题。但如果是其他专业背景的人就会越发感觉痛苦。

如果你的图像处理是不涉及机器学习内容的,例如用Poisson方程来做图像融合,那你就要有PDE数值解方面的知识;如果你要研究KAZE特征,你就必须要知道AOS方面的内容。如果你研究TV降噪,你又要知道泛函分析中的BV空间内容……这些词你可能很多都没听过。总的来说,这块需要的内容包括:复变函数、泛函分析、偏微分方程、变分法、数学物理方法……

如果你要涉足机器视觉方法的内容,一些机器学习和数据挖掘方法的内容就不可或缺。而这部分内容同样需要很强大的数学基础,例如最大似然方法、梯度下降法、欧拉-拉格朗日方程、最小二乘估计、凸函数与詹森不等式……

当然,走到这一步,你也已经脱胎换骨,从小白到大神啦!路漫漫其修远兮,吾将上下而求索。

 

(全文完)

 

 

FPGA数字图像处理

阅读数 651