2012-11-08 38 views
8

Tôi đang tải hình ảnh RGB từ đĩa với JuicyPixels-repa. Thật không may đại diện mảng của hình ảnh là Array F DIM3 Word8 nơi kích thước bên trong là điểm ảnh RGB. Đó là một chút không tương thích với các thuật toán xử lý hình ảnh repa hiện tại có hình ảnh RGB là Array U DIM2 (Word8, Word8, Word8).Tính toán biểu đồ hình ảnh với repa

tôi muốn để tính toán biểu đồ RGB của ảnh, tôi đang tìm kiếm một chức năng với Chữ ký:

type Hist = Array U DIM1 Int 
histogram:: Array F DIM3 Word8 -> (Hist, Hist, Hist) 

làm thế nào tôi có thể gấp mảng 3d của tôi để có được một mảng 1d cho mỗi colorchannel?

Edit:

Vấn đề chính không phải là tôi không thể chuyển đổi DIM3-DIM2 cho mỗi kênh (dễ dàng thực hiện với cắt). Vấn đề là tôi phải lặp lại hình ảnh nguồn DIM2 hoặc DIM3 và phải tích lũy thành một mảng DIM1 của một khác nhau Shape(Z:.256). Vì vậy, tôi không thể sử dụng foldS của repa vì nó làm giảm kích thước của một, nhưng với cùng một mức độ.

Tôi cũng thử nghiệm với traverse nhưng nó lặp lại trong phạm vi hình ảnh đích, cung cấp chức năng lấy pixel từ hình ảnh nguồn, điều này sẽ dẫn đến mã không hiệu quả, đếm cùng một pixel cho mỗi giá trị màu.

Cách tốt nhất sẽ là một gấp đơn giản hơn một Vector với các loại biểu đồ như accumulator, nhưng tiếc là tôi không có U (không có hộp bọc) hoặc V (vector) dựa mảng, từ mà tôi có hiệu quả có thể nhận được một Vector. Tôi có một số Array F (con trỏ nước ngoài).

+3

Bạn đã thử những gì? (Bạn có thể làm điều đó nếu mảng có kiểu 'Mảng U DIM2 (Word8, Word8, Word8)'? Nếu vậy, bạn có thể viết một hàm chuyển đổi 'Mảng U DIM3 Word8 -> Mảng U DIM2 (Word8, Word8, Word8)' ?) – huon

+1

Tôi sẽ cố gắng xem xét điều này vào ngày mai. Trong thời gian đó, nếu có các chuyển đổi cơ bản giữa các biểu diễn hình ảnh mà bạn cho rằng sẽ hữu ích trong JP-repa thì hãy gửi bản vá. –

+0

@FalcoHirschenberger Bạn đã bao giờ nhận được Otsu thresholding thực hiện? Tôi thích nó nhưng tôi muốn tránh bất kỳ công việc trùng lặp nào. –

Trả lời

7

Ok, tôi đã tìm thấy một vài phút. Dưới đây, tôi bao gồm bốn giải pháp và đã thực hiện các giải pháp tồi tệ nhất (giữa hai, liên quan đến chuyển đổi dữ liệu O (n)) thực sự dễ dàng cho bạn.

Cho phép Ghi nhận những giải pháp Dumb

Đó là hợp lý để bắt đầu với sự rõ ràng. Bạn có thể sử dụng Data.List.foldl đi qua các hàng và cột, xây dựng biểu đồ của bạn từ zero mảng ban đầu (chưa được kiểm tra mã/phần sau):

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 

Tôi không chắc chắn hiệu quả thế nào điều này sẽ được, nhưng nghi ngờ rằng nó sẽ kiểm tra quá nhiều. Chuyển sang unsafeIndex nên làm một cách hợp lý, giả sử mảng bị trì hoãn, hist*, thực hiện tốt do bạn chọn để triển khai incElem.

Bạn có thể xây dựng Array Bạn Muốn

Sử dụng traverse bạn thực sự có thể chuyển đổi mảng kiểu JP-Repa vào DIM2 mảng với các bộ cho các yếu tố:

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)) 

Ông có thể cho tôi điểm cơ thể mã bạn đã nói về việc sử dụng định dạng này? Nó sẽ đơn giản để vá JP-Repa để bao gồm một hàm của kiểu này.

Bạn có thể xây dựng các Hộp Bọc Vector bạn đề cập

Bạn nói một giải pháp dễ dàng là để gấp trên vectơ không có hộp bọc, nhưng than rằng JP-repa không cung cấp một mảng không có hộp bọc. May mắn thay, chuyển đổi rất đơn giản:

toUnboxed :: Img a -> VU.Vector Word8 
toUnboxed = R.toUnboxed . R.computeUnboxedS . R.delay . imgData 

Chúng ta có thể vá Repa

Đây thực sự chỉ là một vấn đề bởi vì Repa không có những gì tôi xem xét một traverse chức năng bình thường. Sự đi lại của Repa là nhiều hơn một công trình xây dựng mảng xảy ra để cung cấp một hàm lập chỉ mục vào một mảng khác. Chúng tôi muốn đi qua theo hình thức:

newTraverse :: Array r sh e -> a -> (a -> sh -> e -> a) -> a 

nhưng thực tế thô này chỉ là một nếp gấp không đúng định dạng. Vì vậy, cho phép đổi tên nó và sắp xếp lại các đối số:

foldAllIdxS :: (sh -> a - > e -> a) -> a -> Array r sh e -> a 

tương phản độc đáo với (từ trước) foldAllS hoạt động:

foldAllS :: (a -> a -> a) -> a -> Array r sh a -> a 

Thông báo bao lần mới của chúng tôi có hai đặc điểm quan trọng. Loại kết quả không bắt buộc phải khớp với loại phần tử, vì vậy chúng tôi có thể bắt đầu bằng một bộ Biểu đồ. Thứ hai, phiên bản gấp của chúng tôi chuyển chỉ mục, cho phép bạn chọn biểu đồ nào trong bộ dữ liệu để cập nhật (nếu có).

Bạn uể oải có thể sử dụng JuicyPixels-Repa mới nhất

Để có được định dạng mảng Repa ưa thích của bạn, hoặc để có được một vector không có hộp bọc, bạn chỉ có thể sử dụng JuicyPixels-Repa-0.6 mới tải lên.

someImg <- readImage path :: IO (Either String (Img RGBA)) 
let img = either (error "Blah") id someImg 
    uvec = toUnboxed img 
    tupleArr = collapseColorChannel img 

Bây giờ bạn có thể gấp trên vectơ hoặc sử dụng mảng tuple trực tiếp, như bạn mong muốn ban đầu.

tôi cũng mất một đâm xấu xí tại fleshing ra đầu tiên, khủng khiếp ngây thơ, giải pháp:

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] ] 

tôi quá thận trọng với việc thực hiện các mã này (3 traversals mỗi chỉ số ... Tôi phải mệt mỏi) để ném nó vào JP-Repa, nhưng nếu bạn thấy nó hoạt động tốt thì hãy cho tôi biết.

+0

Cảm ơn câu trả lời khó chịu của bạn. Tôi sẽ thử đề xuất của bạn càng sớm càng tốt. Tôi cố gắng thực hiện thuật toán thresholding tự động Otsu. Liên quan đến câu hỏi của bạn, các thuật toán trong 'repa-algorithm' đại diện cho một hình ảnh mutichannel ở dạng' Mảng U DIM2 a' và cung cấp các chức năng chuyển đổi điểm ảnh của dạng 'rgb8OfFloat :: (Float, Float, Float) -> (Word8, Word8 , Word8) '. –

Các vấn đề liên quan