坚持写博客是最近的目标。加油。
业余学习fsharp以来一直觉得这才是Dotnet开发,或者说所有开发者应该拥有的语言。配合Visual Studio的代码提示,即时执行窗口。开发程序有着极大的乐趣。
最近想学习一些图像处理的相关知识。试着把Fsharp又捡了起来。边学边玩,希望两个方面都有所进益。
图像的处理首先要解决显示的问题。在FSI中内嵌了Winform的消息处理,可以很方便的几句话画出一个带PictureBox的窗体。在FSI中由于可以保持对窗体和控件的控制权,当更新算法后,我们可以很快的看到结果。拥有即时反馈的编程工具真是开发人员的幸运。
open System.Windows.Forms let form = new Form() let image = new PictureBox(Dock = DockStyle.Fill) form.Controls.Add(image) image.SizeMode <- PictureBoxSizeMode.StretchImage form.Show()
显示窗体的代码如上所示,非常的简单。当然此时什么都没有。下面来加载一张图片
open System.Drawing let image_path = __SOURCE_DIRECTORY__ + @"Chrysanthemum.jpg" let bitmap = new Bitmap(image_path) image.Image <- bitmap
好了最基本的框架完成了。此时我们仍可以通过bitmap,image等变量控制窗口的显示。
最后是反色程序,首先我们取出所有像素点
let Pixels =seq {for h in 0..bitmap.Height-1 do for w in 0..bitmap.Width-1 do yield bitmap.GetPixel(w, h)}
进行反色操作
Pixels |> Seq.iteri(fun i c -> bitmap.SetPixel(i%bitmap.Width, i/bitmap.Width, Color.FromArgb((255 - (int c.R)), (255 - (int c.G)), (255 - (int c.B))))) //win10 seem to need to update manually image.Invalidate()
很简单吧。就是速度哦有些慢。主要是SetPixel和GetPixel操作拖累了速度。
使用BitmapData可以大大加快速度。使用#time 操作打开操作时间显示看看快了多少
let imagerect = new Rectangle(0,0,bitmap.Width, bitmap.Height) let bitmapdata = bitmap.LockBits(imagerect, ImageLockMode.ReadWrite, bitmap.PixelFormat) let buffer:byte[] = Array.zeroCreate (bitmap.Width * bitmap.Height * Bitmap.GetPixelFormatSize(bitmap.PixelFormat)/8) Marshal.Copy(bitmapdata.Scan0, buffer, 0, buffer.Length) let newbuff = buffer |> Seq.map(fun x -> 255uy - x) |> Array.ofSeq Marshal.Copy(newbuff, 0, bitmapdata.Scan0, buffer.Length) bitmap.UnlockBits(bitmapdata) image.Invalidate()
Real: 00:00:01.227,CPU: 00:00:01.218,GC gen0: 0, gen1: 0, gen2: 0 Real: 00:00:00.050,CPU: 00:00:00.046,GC gen0: 0, gen1: 0, gen2: 0
下次再找个知识点,不过似乎要先补补微积分和线代了。