使用FSharp 探索Dotnet图像处理功能1--反色变化

时间:2023-03-09 18:16:15
使用FSharp 探索Dotnet图像处理功能1--反色变化

坚持写博客是最近的目标。加油。

业余学习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 ..bitmap.Height- do
for w in ..bitmap.Width- do
yield bitmap.GetPixel(w, h)}

进行反色操作

Pixels |> Seq.iteri(fun i c ->
bitmap.SetPixel(i%bitmap.Width,
i/bitmap.Width,
Color.FromArgb(( - (int c.R)), ( - (int c.G)), ( - (int c.B)))))
//win10 seem to need to update manually
image.Invalidate()

很简单吧。就是速度哦有些慢。主要是SetPixel和GetPixel操作拖累了速度。

使用BitmapData可以大大加快速度。使用#time 操作打开操作时间显示看看快了多少

let imagerect = new Rectangle(,,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)/)
Marshal.Copy(bitmapdata.Scan0, buffer, , buffer.Length)
let newbuff = buffer |> Seq.map(fun x -> 255uy - x) |> Array.ofSeq
Marshal.Copy(newbuff, , bitmapdata.Scan0, buffer.Length)
bitmap.UnlockBits(bitmapdata) image.Invalidate()
Real: ::01.227,CPU: ::01.218,GC gen0: , gen1: , gen2: 

Real: ::00.050,CPU: ::00.046,GC gen0: , gen1: , gen2: 

下次再找个知识点,不过似乎要先补补微积分和线代了。