All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
Asp.net,MVC2.0初级教程-显示列表和内容页_[Asp.Net教程]
SQL,Server存储图像数据的策略与方法_[SQL,Server教程]
ASP.NET,2.0中层次数据的处理_.net资料_编程技术
XML入门教程:XML是如何被利用的?_[XML教程]
delphi结构化异常处理
Visual,C#2005快速入门之基础语法_[Asp.Net教程]
简单介绍.Net3.0,中跨线程访问控件_.net资料_编程技术
ASP.NET底层架构探索之ASP.NET管道_.net资料_编程技术
SQL语句中的布尔表达式_[SQL,Server教程]
整站如何防止SQL注入攻击_[Asp.Net教程]
Reading number is top 10 pictures
Breasts woman big set 1
全球十大灵异酒店
牛奶和人奶哪个好?
何炅哥为中国人的平均工资鸣不平了
Ashlynn Brooke photograph of a group2
大年初五接财神
乳娘帕梅拉安德森3
影评-疯子,我爱你
谁认识这位校花
妹子最好别玩单反
Download software ranking
jBuilder2006
Proficient in Eclipse
Kung fu panda - the secret of the teacher
matrix3
Boxer vs Yellow3
Tram sex maniac 2 (H) rar bag3
Unix video tutorial12
The king of fighters 97(Mobile phone games-apk)
Eclipse 4.2.2 For Win32
Twenty piece of palm leaf
aaa published in(发表于) 2013/12/6 10:39:37 Edit(编辑)
基于.NET数字处理程序的框架设计_.net资料_编程技术

基于.NET数字处理程序的框架设计_.net资料_编程技术

基于.NET数字处理程序的框架设计_.net资料_编程技术-数科优化网

接触数字图像处理最早是在高中,那时候PHOTOSHOP还是4.0,可能是因为先入为主的关系,到现在都没有学3DMAX之类的兴趣,2D到3D的飞跃估计是没我什么事了,舍不得那平方到立方的高薪....呵呵。
在上大学的时候,就和同学一起写过一些图像处理的程序,那个时候编程还很随意,考虑的只是如何实现,现在看来真正的技术是把握全局的能力,而不是灵光一现的神奇。前些日子接触了一些国外的图像处理程序,在这里算是作个总结,估计以后不会再针对性的研究图像处理方面的东西了。
以前的一个同学曾经跟我说过.net没有指针,现在很多培训课好像也是这么讲的,其实这是一个谬误。只是framework不推荐使用指针,尤其是在webservise,remoting等跨进程操作中,指针都是不安全的。但用过TC的各位都应该对指针的执行效率又深刻的印象,在批量运算大规模数据的需求下,指针是不二的选择。因而.net聪明的保留的保留了指针,并将其列入不安全方法集中。合理的使用指针将大幅度提高执行效率,我曾做过试验,对640*480的图像进行逐点运算,非指针运算要执行数分钟,而指针运算几乎是瞬间完成的。所以不要害怕使用指针。
其次就是数学,奉劝大家一定要弄明白了再写程序,数学课不是闹着玩的......想不明白就要躺在床上反复的想,我总觉得数学能预防老年痴呆。
言归正传,说说程序结构吧 :
Imaging项目(滤镜,纹理,图像模式)
Math项目(算法,边界,定制。及常用计算方法)
主程序项目
各举个例子来说明,我也来一回面向接口编程 ,


public interface IFilter
{
Bitmap Apply( Bitmap img );
}


举例来说明,我也来一回面向接口编程 ,各滤镜都要实现这个接口,接口定义还包括一个不生成实际图像,只生成二进制对象的借口定义,在这里暂不作考虑。以取反色滤镜为例
public Bitmap Apply( Bitmap srcImg )
{
// get source image size
int width = srcImg.Width;
int height = srcImg.Height;

PixelFormat fmt = ( srcImg.PixelFormat == PixelFormat.Format8bppIndexed ) ?
PixelFormat.Format8bppIndexed : PixelFormat.Format24bppRgb;


// lock source bitmap data
BitmapData srcData = srcImg.LockBits(
new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadOnly, fmt );


// create new image
Bitmap dstImg = ( fmt == PixelFormat.Format8bppIndexed ) ?
AForge.Imaging.Image.CreateGrayscaleImage( width, height ) :
new Bitmap( width, height, fmt );


// lock destination bitmap data
BitmapData dstData = dstImg.LockBits(
new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadWrite, fmt );


// copy image
Win32.memcpy( dstData.Scan0, srcData.Scan0, srcData.Stride * height );


// process the filter
ProcessFilter( dstData, fmt );


// unlock both images
dstImg.UnlockBits( dstData );
srcImg.UnlockBits( srcData );


return dstImg;
}



是该滤镜方法的入口,完成了处理前的准备工作,ProcessFilter同时调用每个滤镜类中共有的ProcessFilter方法,而这个ProcessFilter就是实现功能的关键所在了逐点运算或模版运算。
// Process the filter
private unsafe void ProcessFilter( BitmapData data, PixelFormat fmt )
{
int width = data.Width;
int height = data.Height;


int lineSize = width * ( ( fmt == PixelFormat.Format8bppIndexed ) ? 1 : 3 );
int offset = data.Stride - lineSize;


// do the job
byte * ptr = (byte *) data.Scan0.ToPointer( );


// invert
for ( int y = 0; y < height; y++ )
{
for ( int x = 0; x < lineSize; x++, ptr ++ )
{
// ivert each pixel
*ptr = (byte)( 255 - *ptr );
}
ptr += offset;
}
}


其中Format8bppIndexed是不必太关心的,个人认为设计初期可以不用考虑兼容它的问题。
下面来说说纹理,这个以前考虑得还不太多,但发现老外很喜欢玩这个,因为纹理在数学方面发挥的空间更大,我也不知道他们是怎么想出来的,凭空想可能还真是有难度,可能是他们谁在玩数学建模软件的时候发现这个玩法的,于是高数老师谁也不服谁,把算法玩的火火的。反正我觉得是这么回事。。。
public interface ITextureGenerator
{
/**////


/// Generate texture
///

float[,] Generate( int width, int height );


/**////


/// Reset - regenerate internal random numbers
///

void Reset( );
}
这是纹理生成器的实现接口,为了保证每次的纹理不同,还要更新随机数以作为计算参数
private Math.PerlinNoise noise = new Math.PerlinNoise( 1.0 / 32, 0.05, 0.5, 8 );
实现纹理细节还需要靠noise实现,因而需要实现许多种noise。
// Constructors
public WoodTexture( ) : this( 12.0 ) { }
public WoodTexture( double rings )
{
this.rings = rings;
Reset( );
}


构造函数提供了默认值的设置,也就是对单位纹理大小的限定。
// Generate texture
public float[,] Generate( int width, int height )
{
float[,] texture = new float[height, width];
int w2 = width / 2;
int h2 = height / 2;


for ( int y = 0; y < height; y++ )
{
for ( int x = 0; x < width; x++ )
{
double xv = (double) ( x - w2 ) / width;
double yv = (double) ( y - h2 ) / height;


texture[y, x] =
Math.Max( 0.0f, Math.Min( 1.0f, (float)
Math.Abs( Math.Sin(
( Math.Sqrt( xv * xv + yv * yv ) + noise.Function2D( x + r, y + r ) )
* Math.PI * 2 * rings
))
));
}
}
return texture;
}
这就是。。。我数学不好的下场。都不知道她在说什么呢,最小值中选出最大值。算法不难找,关键是要看结构如何将他们整合起来。
public void Reset( )
{
r = rand.Next( 5000 );
}别忘了这个随机数,数字的图像也需要自然的美。


Math工程中面向对象的观念不它容易得到贯彻,看一看那个PerlinNoise吧,抛砖引玉。
public PerlinNoise( double initFrequency, double initAmplitude, double persistance, int octaves )
{
this.initFrequency = initFrequency;
this.initAmplitude = initAmplitude;
this.persistance = persistance;
this.octaves = octaves;
}
首先要收集数据,因为图像处理要涉及到一维和二维两种情况,因而像noise这种底层方法要分别对应着两种情况给出对应的方法。
/**////


/// 1-D Perlin noise function
///

public double Function( double x )
{
double frequency = initFrequency;
double amplitude = initAmplitude;
double sum = 0;

// octaves
for ( int i = 0; i < octaves; i++ )
{
sum += SmoothedNoise( x * frequency ) * amplitude;


frequency *= 2;
amplitude *= persistance;
}
return sum;
}


/**////


/// 2-D Perlin noise function
///

public double Function2D( double x, double y )
{
double frequency = initFrequency;
double amplitude = initAmplitude;
double sum = 0;

// octaves
for ( int i = 0; i < octaves; i++ )
{
sum += SmoothedNoise( x * frequency, y * frequency ) * amplitude;


frequency *= 2;
amplitude *= persistance;
}
return sum;
}
一维跟二维的区别是什么,上中学的时候知道了线的运动生成了面,上大学又知道了循环着变化着的线能代表面,但如果做过了边缘识别和锐化以后话,又发现以前小看线了,其实它只是比面少一个参数而已。



/**////


/// Ordinary noise function
///

protected double Noise( int x )
{
int n = ( x << 13 ) ^ x;


return ( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 );
}
protected double Noise( int x, int y )
{
int n = x + y * 57;
n = ( n << 13 ) ^ n ;


return ( 1.0 - ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7fffffff ) / 1073741824.0 );
}又一次证明了前面那段话,个人感觉这个x+y*57有点投影的意思。获取相应的噪点值。但噪点不是直接就能拿来用的
/**////


/// Smoothed noise
///

protected double SmoothedNoise( double x )
{
int xInt = (int) x;
double xFrac = x - xInt;


return CosineInterpolate( Noise( xInt ) , Noise( xInt + 1 ), xFrac );
}
protected double SmoothedNoise( double x, double y )
{
int xInt = (int) x;
int yInt = (int) y;
double xFrac = x - xInt;
double yFrac = y - yInt;


// get four noise values
double x0y0 = Noise( xInt , yInt );
double x1y0 = Noise( xInt + 1, yInt );
double x0y1 = Noise( xInt , yInt + 1 );
double x1y1 = Noise( xInt + 1, yInt + 1) ;


// x interpolation
double v1 = CosineInterpolate( x0y0, x1y0, xFrac );
double v2 = CosineInterpolate( x0y1, x1y1, xFrac );
// y interpolation
return CosineInterpolate( v1, v2, yFrac );
}平滑的噪点,这个称呼似乎有点不协调,通过余弦插值,而不是离散余弦来运算。什么是余弦插值呢? /**////


/// Cosine interpolation
///

protected double CosineInterpolate( double x1, double x2, double a )
{
double f = ( 1 - Math.Cos( a * Math.PI ) ) * 0.5;


return x1 * ( 1 - f ) + x2 * f;
}就是这个,有些事情,大师知道就够了,你就照着去做就行了,为什么?因为你可能一辈子也不明白,自然有人会去弄明白的,知识还在传承。就像你不必知道自己的胃酸比例,也可以放心的吃香喝辣一样,也不必担心子孙后代消化不良。有些事情不必强求,有点消极了,呵呵。
画面并不难,只要把握好调用关系就可以了,另外像photoshop那样的悬浮窗体是最佳的选择我认为, // Invert image
private void invertColorFiltersItem_Click(object sender, System.EventArgs e)
{
ApplyFilter(new Invert());
}


// Apply filter on the image
private void ApplyFilter(IFilter filter)
{
try
{
// set wait cursor
this.Cursor = Cursors.WaitCursor;


// apply filter to the image
Bitmap newImage = filter.Apply(image);


if (host.CreateNewDocumentOnChange)
{
// open new image in new document
host.NewDocument(newImage);
}
else
{
if (host.RememberOnChange)
{
// backup current image
if (backup != null)
backup.Dispose();


backup = image;
}
else
{
// release current image
image.Dispose();
}


image = newImage;


// update
UpdateNewImage();
}
}
catch (ArgumentException)
{
MessageBox.Show("Selected filter can not be applied to the image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
// restore cursor
this.Cursor = Cursors.Default;
}
}调用顺畅的话,多少代码都不会觉得乱,对于初学者来说,要善用region。
这里还有个DocumentsHost的概念,用它来承载图像文件,并将图像和窗体连接起来,很方便 /**////


/// IDocumentsHost interface
/// Provides connectione between documents and the main widnow
///

public interface IDocumentsHost
{
bool CreateNewDocumentOnChange{get;}
bool RememberOnChange{get;}


bool NewDocument(Bitmap image);
bool NewDocument(ComplexImage image);


Bitmap GetImage(object sender, String text, Size size, PixelFormat format);
}


欢迎大家跟我讨论






添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.