首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 冲浪宝典-> 联络聊天
基于.net数字处理程序的框架设计_asp.net技巧
作者:网友供稿 点击:0
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 

        接触数字图像处理最早是在高中,那时候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
    {
        /**//// <summary>
        /// Generate texture
        /// </summary>
        float[,] Generate( int width, int height );

        /**//// <summary>
        /// Reset - regenerate internal random numbers
        /// </summary>
        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这种底层方法要分别对应着两种情况给出对应的方法。
        /**//// <summary>
        /// 1-D Perlin noise function
        /// </summary>
        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;
        }

        /**//// <summary>
        /// 2-D Perlin noise function
        /// </summary>
        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;
        }
 一维跟二维的区别是什么,上中学的时候知道了线的运动生成了面,上大学又知道了循环着变化着的线能代表面,但如果做过了边缘识别和锐化以后话,又发现以前小看线了,其实它只是比面少一个参数而已。


        /**//// <summary>
        /// Ordinary noise function
        /// </summary>
        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有点投影的意思。获取相应的噪点值。但噪点不是直接就能拿来用的
        /**//// <summary>
        /// Smoothed noise
        /// </summary>
        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 );
        }平滑的噪点,这个称呼似乎有点不协调,通过余弦插值,而不是离散余弦来运算。什么是余弦插值呢?         /**//// <summary>
        /// Cosine interpolation
        /// </summary>
        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的概念,用它来承载图像文件,并将图像和窗体连接起来,很方便     /**//// <summary>
    /// IDocumentsHost interface
    /// Provides connectione between documents and the main widnow
    /// </summary>
    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);
    }欢迎大家跟我讨论

http://www.cnblogs.com/phono/archive/2006/09/07/phono.html


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·Java Unicode转义字符的小小研究-JSP教程,Java技巧及代码
·实现VB与EXCEL的无缝连接-.NET教程,VB.Net语言
·在ASP.NET里通过URL传递参数得到乱码的解决方法-ASP教程,ASP应用
·实例讲解:Java中的SOAP技术-JSP教程,Java技巧及代码
·Session过期问题-ASP教程,ASP应用
·设计模式笔记-抽象工厂模式-.NET教程,评论及其它
·JSP标准标记库促进了网页的开发-JSP教程,Jsp/Servlet
·在Remoting Server上取得Remoting Client的IP地址-ASP教程,ASP应用
·使用JSP标记库校验用户输入-JSP教程,Jsp/Servlet
·c#中DataGrid的数据新增编辑删除操作代码-.NET教程,数据库应用
最新文章
·xp也能享受vista readyboost闪存加速_windows xp
·c# 3.0新特性系列:隐含类型var_c#教程
·如此做google广告,月赚10万美金不成问题_网赚技巧
·王通:个人博客的赚钱之道_网赚技巧
·这一年来风风雨雨-再访中客宋陈磊_站长访谈
·个人网站的定位推广和赚钱-访中国建站站长_站长访谈
·祥瑞网方文春:从800元到6000万元_站长访谈
·行业类、专业性成功网站给个人站长的启示_站长访谈
·网站推广 新招老招齐用上_站长心得
·widnows vista工具栏添加快速启动tabletpc图标_windows vista
相关主题
  • 基于.net的邮件解决方案_邮件服务器
  • 基于.net开发平台项目案例集锦-.NET教程,Asp.Net开发
  • 基于.Net平台应用程序唯一运行实例实现-.NET教程,.NET Framework
  • 基于.net的用户处理机制。-.NET教程,Asp.Net开发
  • 基于.Net Framework的N层分布式应用开发-.NET教程,.NET Framework
  • 西部数码虚拟主机

    友情链接
    CNNIC 西部数码
    万网 自助建站
    虚拟主机 asp空间
    域名注册 域名
    域名申请 主页空间
    论坛空间 网站空间
    国际域名 虚拟空间
    空间租用 DDOS防火墙
    成都主机托管 四川主机托管
    主机租用 服务器租用
    网站目录 自助建站
    虚拟主机 网址大全
    软件下载
    自助链接
    虚拟主机资讯 特价虚拟主机
    版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
    关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
    特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
    发表评论 打印  刷新     关闭