Ok, ich fand ein paar Minuten. Im Folgenden behandle ich vier Lösungen und habe die schlechtesten Lösungen (die mittleren zwei mit O (n) Datenkonvertierung) wirklich einfach für Sie gemacht.
Lets Bestätigen Sie die Dumb Lösung
Es ist vernünftig mit dem Offensichtlichen zu starten. Sie Data.List.foldl
verwenden könnten die Zeilen und Spalten, den Aufbau Ihres Histogramme von Erstnullabgleich Arrays (ungetestet/Teil Code folgt) zu durchqueren:
foldl (\(histR, histG, histB) (row,col) ->
let r = arr ! (Z:.row:.col:.0)
g = arr ! (Z:.row:.col:.1)
b = arr ! (Z:.row:.col:.2)
in (incElem r histR, incElem g histG, incElem b histB)
(zero,zero,zero)
[ (row,col) | row <- [0..nrRow-1], col <- [0..nrCol-1] ]
...
where (Z:.nrRow:.nrCol:._) = extent arr
Ich bin nicht sicher, wie effizient dies sein wird, aber vermuten, dass es wird Überprüfe zu viele Grenzen. Der Wechsel zu unsafeIndex sollte vernünftigerweise tun, unter der Annahme, dass die verzögerten Arrays hist*
gut funktionieren, obwohl Sie sich dafür entscheiden, incElem
zu implementieren.
Sie können den Array Sie
Wollen Sie bauen
traverse
Verwenden Sie tatsächlich konvertieren JP-Repa Stil Arrays in DIM2
Arrays mit Tupeln für Elemente:
main = do
let arr = R.fromFunction (Z:.a:.b:.c) (\(Z:.i:.j:.k) -> i+j-k)
a =4 :: Int
b = 4 :: Int
c= 4 :: Int
new = R.traverse arr
(\(Z:.r:.c:._) -> Z:.r:.c) -- the extent
(\l idx -> (l (idx:.0)
,l (idx:.1)
,l (idx :. 2)))
print (R.computeS new :: R.Array R.U DIM2 (Int,Int,Int))
Können Sie mir auf den Körper zeigen von Code, über den Sie gesprochen haben, der dieses Format verwendet? Es wäre einfach, JP-Repa mit einer Funktion dieses Typs zu versehen.
Sie können die Unboxed Vector bauen Sie Erwähnt
Sie haben erwähnt, eine einfache Lösung zu falten unboxed Vektoren, aber beklagte, dass JP-repa keine unboxed Array liefert. Glücklicherweise Umwandlung ist einfach:
toUnboxed :: Img a -> VU.Vector Word8
toUnboxed = R.toUnboxed . R.computeUnboxedS . R.delay . imgData
Wir können Patch-Repa
Das ist wirklich nur ein Problem, weil Repa hat nicht das, was ich eine normale traverse
Funktion prüfen. Repas Traverse ist eher eine Array-Konstruktion, die zufällig eine Indizierungsfunktion in einem anderen Array bereitstellt. Wir wollen Traverse in der Form:
newTraverse :: Array r sh e -> a -> (a -> sh -> e -> a) -> a
aber von grob ist dies eigentlich nur eine missgebildete Falte. So lässt es umbenennen und neu anordnen, die Argumente:
foldAllIdxS :: (sh -> a - > e -> a) -> a -> Array r sh e -> a
, die gut mit dem (bereits existierenden) foldAllS
Betrieb kontrastiert:
foldAllS :: (a -> a -> a) -> a -> Array r sh a -> a
Beachten Sie, wie unsere neue Falte zwei kritische Eigenschaften aufweist. Der Ergebnistyp muss nicht mit dem Elementtyp übereinstimmen, daher könnten wir mit einem Histogramm-Tupel beginnen. Zweitens übergibt unsere Version von fold den Index, mit dem Sie auswählen können, welches Histogramm im Tupel aktualisiert werden soll (falls vorhanden).
Sie können lazily verwenden die neuesten JuicyPixels-Repa
Um Ihre bevorzugte Repa Array-Format zu erwerben oder eine unboxed Vektor zu erwerben, können Sie die neu hochgeladen JuicyPixels-Repa-0.6 verwenden Sie einfach.
someImg <- readImage path :: IO (Either String (Img RGBA))
let img = either (error "Blah") id someImg
uvec = toUnboxed img
tupleArr = collapseColorChannel img
Jetzt können Sie den Vektor umklappen oder das Tupel-Array direkt verwenden, wie Sie ursprünglich gewünscht haben.
Ich habe auch einen hässlichen Stich in die erste, schrecklich naiv, Lösung konkretisiert:
histograms :: Img a -> (Histogram, Histogram, Histogram, Histogram)
histograms (Img arr) =
let (Z:.nrRow:.nrCol:._) = R.extent arr
zero = R.fromFunction (Z:.256) (\_ -> 0 :: Word8)
incElem idx x = RU.unsafeTraverse x id (\l i -> l i + if i==(Z:.fromIntegral idx) then 1 else 0)
in Prelude.foldl (\(hR, hG, hB, hA) (row,col) ->
let r = R.unsafeIndex arr (Z:.row:.col:.0)
g = R.unsafeIndex arr (Z:.row:.col:.1)
b = R.unsafeIndex arr (Z:.row:.col:.2)
a = R.unsafeIndex arr (Z:.row:.col:.3)
in (incElem r hR, incElem g hG, incElem b hB, incElem a hA))
(zero,zero,zero,zero)
[ (row,col) | row <- [0..nrRow-1], col <- [0..nrCol-1] ]
ich zu vorsichtig bin von der Leistung dieses Code (3 Querungen pro Index ... Ich muß es sein müde), um es in JP-Repa zu werfen, aber wenn Sie finden, dass es gut funktioniert, lassen Sie mich wissen.
Was haben Sie versucht? (Könnten Sie es tun, wenn das Array den Typ 'Array U DIM2 (Word8, Word8, Word8) 'hätte? Wenn ja, können Sie eine Konvertierungsfunktion' Array U DIM3 Word8 -> Array U DIM2 (Word8, Word8, Word8) 'schreiben ?) – huon
Ich werde versuchen, das morgen zu sehen. In der Zwischenzeit, wenn es grundlegende Konvertierungen zwischen Bilddarstellungen gibt, von denen Sie denken, dass sie in JP-repa nützlich wären, dann senden Sie bitte ein Patch. –
@FalcoHirschenberger Hast du jemals Otsu Thresholding gemacht? Ich würde es mögen, aber ich möchte doppelte Arbeit vermeiden. –