我刚刚发现了this post,并想知道如何在Haskell中做类似的事情。在下文中,我简化了我遇到困难的部分:
我有一个包含大量2D坐标的列表。为简单起见,我们假设列表包含Int
0 - 1023
个坐标
points :: [(Int,Int)] -- long list of points
目标是现在有一张图片(让我们说img :: [[Int]]
其中img
,其中每个条目的长度为1024
),其中(img!!i)!!j
是(i,j)
的出现次数{ points
中的{1}}(会映射到某些灰色值)。
到目前为止我尝试了什么:
points
的命令式方法并尝试查明某些2d数组的条目i,j
,那么关于选择一些条目i,j
并递增它的部分非常一方面很麻烦,也可能效率不高,另一方面使用!!
容易出现index too large
错误。(i,j)
,使用partition
过滤掉(i,j)
条目并对其进行计数,并将列表的其余部分传递给下一对coordnates。这样我们就会得到(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
答案 0 :(得分:2)
作为变体之一,您可以使用Data.Array
:
import Data.Array
main = do
putStrLn "before:" >> print myArr
putStrLn "after:" >> print myArr2
putStrLn "output of our \"image\":" >> print outArr
n :: Int
n = 4
-- example for "increment"
myArr = listArray ((0,0), (n-1,n-1)) [1..]
myArr2 = accum (+) myArr [((2, 3), 1000)]
-- example for our application
outArr = accumArray (+) 0 ((0,0), (n-1,n-1)) [ (p, 1) | p <- 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]]
将repa
与vector
一起使用:
import Control.Monad
import Data.Array.Repa
import qualified Data.Vector.Generic as V
import qualified Data.Vector.Generic.Mutable as MV
main = putStrLn "output of our \"image\":" >> print outArr
n :: Int
n = 1024
-- example for our application
outArr :: Array U DIM2 Int
outArr = fromUnboxed (Z :. n :. n) $ V.create $ do
v <- MV.new (n * n)
MV.set v 0
forM_ points $ \(i, j) -> do
let idx = i * n + j
MV.modify v (+1) idx
pure v
-- our "data" (here im just filling this with arbitrary numbers)
points = [(i `mod` n,j `mod` n)|i <-[1..14],j<-[i..77+i]]
答案 1 :(得分:1)
在Haskell中进行图像处理的一种可能性是使用 Comonads 。它允许以优雅功能指定图像处理算法。一个好的和可访问的介绍是https://jaspervdj.be/posts/2014-11-27-comonads-image-processing.html。