【发布时间】:2017-11-11 10:47:16
【问题描述】:
我刚刚发现 this post 并且想知道如何在 Haskell 中做类似的事情。下面我只是简化了我遇到困难的部分:
我有一个包含大量 2D 坐标的列表。为简单起见,让我们假设列表包含 Int 坐标,这些坐标都在 0 - 1023 范围内
points :: [(Int,Int)] -- long list of points
现在的目标是拥有一个图像(假设img :: [[Int]],其中img,其中每个条目的长度为1024),其中(img!!i)!!j 是points 中(i,j) 的出现次数(其中会被映射到一些灰度值)。
到目前为止我尝试了什么:
- 如果我只使用循环遍历
points并尝试增加某个二维数组的条目i,j的命令式方法,那么选择一些条目i,j并增加它的部分非常麻烦并且可能效率不高一方面,另一方面使用!!容易出现index too large错误。 - 一种更有效的方法:对于每对坐标
(i,j),使用partition过滤掉(i,j)条目并计算它们,并将列表的其余部分传递给下一对坐标。这样我们就得到了(i,j, count)的列表,我们只需将count插入每个像素i,j一次,但在我看来这仍然不是很优雅。
那么您能否提出任何解决方案,以更高效、更优雅的功能方式做到这一点?
这只是一个示例问题,因为我经常遇到类似的问题,但只找到了不满意的解决方案。
编辑:这里要求是此类代码的示例:
main = putStrLn "before:" >> print myImg >> putStrLn "after:" >> print myImg2
>> putStrLn "output of our \"image\":" >> print outImg
n :: Int
n = 4
-- example for "increment"
myImg = [[n..n+3]|n<-[1,5..16]] :: [[Int]]
myImg2 = increment myImg 2 3 10000
-- example for our application
zeroImg = [[0,0,0,0]|_<-[0,0,0,0]]
outImg = foldl (\img (i,j) -> increment img i j 1 ) zeroImg points
-- our "data" (here im just filling this with arbitrary numbers)
points = [(i `mod` n,j `mod` n)|i <-[1..14],j<-[i..77+i]]
-- not very elegant code
increment :: [[Int]] -> Int -> Int -> Int -> [[Int]]
increment img i j v = a ++ [x ++ [y + v] ++ z] ++ c -- increments the "pixel" (i,j) by v
where
a = take i img
b = img !! i
c = drop (i+1) img
x = take j b
y = b !! j
z = drop (j+1) b
【问题讨论】:
-
某些语言可以互换使用这些术语,这取决于您所谈论的语言,但这不是重点。我认为我们是否使用列表并不重要,困难在于使用索引访问和更改某些内容。如果你坚持你可以用例如替换这个列表。来自
Codec.Picture的Image,但我的问题基本保持不变。 -
您对更高效、更优雅的功能方式的疑问。所以,我用列表写了它不是有效的方法。关于优雅的功能方式,也许如果您添加您的解决方案,它可以帮助我们在这里了解您的问题?
-
通常在 Haskell 上解决此类问题没有意义,因为您是从便于命令式代码的数据开始的。但是你应该从那些方便函数式的数据开始。例如,您可以通过添加两个图像来改变这个问题。其中一个将是您的原始图像,第二个将是“从您的点创建”的图像。
-
这个怎么样? wiki.haskell.org/… "Vector 是一个用于处理数组的 Haskell 库。它强调非常高性能......"
-
@freestyle 您如何以更实用的方式从链接示例中生成数据?我不确定我是否理解正确,但是在每个步骤中添加两个图像似乎效率不高,因为基本上只需要更新一个像素。我现在添加了我的解决方案,只使用了
4x4而不是1024x1024“图像”。
标签: haskell image-processing fractals