使用FSharp 探索Dotnet图像处理功能2--均衡灰度

重新捡起大学里的图像处理,好像之前什么都没学到,但是我为什么还留着这本书呢?嘿嘿。

看到均衡灰度处理,上来就是积分,概率分布的公式,头微微的有点疼。网上看了点介绍,隔天再拿起书本,总算有了点眉目。简而言之,就是将灰度直方图的概率分布进行面积不变的拉伸,使图像有更好的显示效果。

其实进行的操作也很少

1.计算灰度值的出现概率。

2.将灰度值进行排序,并累进递加。

3.将累进递加的值映射到0-255的范围中。这时就有了一个原灰度与新灰度的一个对应关系。公式是 Y = (int)(C * p + 0.5) C为目标灰度最大值 p为累进概率。

4.再将原图的每个灰度替换为目标灰度

代码如下

//the number of pixels
let
length = (bitmap.Width * bitmap.Height * Bitmap.GetPixelFormatSize(bitmap.PixelFormat)/8) let rArray = [|for i in 0 .. 255 -> 0uy|] buffer |> Seq.groupBy id |> Seq.map (fun x -> (fst x), double (Seq.length (snd x))/ double length)// step 1 |> Seq.sortBy fst //step 2 |> Seq.scan (fun (_, op) (k,p)-> (k, p + op)) (0uy, 0.0) //step 2 |> Seq.map (fun (k, p) -> (int k, (byte)(255.0 * p + 0.5))) //step 3 |> Seq.iter (fun (k, p) -> rArray.[k] <- p) //step 3 let newbuff = buffer |> Seq.map(fun x -> rArray.[int x]) |> Array.ofSeq //step 4

其中groupBy得到的是key和分组列表值。所以之后用了fst和snd。

scan用来计算递增值真是简单啊。

是不是清楚很多。

rArray 感觉有点别扭,可以再做一点优化

let rArray = 
       buffer  
       |> Seq.groupBy id |> Seq.map (fun x -> (fst x), double (Seq.length (snd x))/ double length)
       |> Seq.append [255uy, 0.0]
       |> Seq.sortBy id
       |> Seq.pairwise
       |> Seq.map (fun (b,e) -> 
                       [for i in fst b..fst e-1uy do 
                           if i = fst b then
                               yield b
                           else 
                               yield (i, 0.0)]) 
       |> Seq.collect id                                
       |> Seq.scan (fun op (k, p) -> (p + op)) (0.0)
       |> Seq.map (fun p -> (byte)(255.0 * p + 0.5))
       |> Seq.toArray

 

posted @ 2017-04-07 22:58  rigid  阅读(283)  评论(0编辑  收藏  举报