# Finding the mean value of subsets of an array

**URL:** <https://discourse.julialang.org/t/finding-the-mean-value-of-subsets-of-an-array/56848>\
**Category:** General Usage\
**Tags:** images, array\
**Created:** [March 10, 2021, 3:16am UTC](https://discourse.julialang.org/t/finding-the-mean-value-of-subsets-of-an-array/56848 "2021-03-10T03:16:22Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![EmadMasroor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/emadmasroor/32/7527_2.png) [@EmadMasroor](https://discourse.julialang.org/u/EmadMasroor)\
**Post date:** [March 10, 2021, 3:16am UTC](https://discourse.julialang.org/t/finding-the-mean-value-of-subsets-of-an-array/56848/1 "2021-03-10T03:16:22Z")

</div>

Hello,

I am trying to take the mean value of a grid of subregions of an image. The images are from a video, hence the `using VideoIO`. My question does not actually depend on video-reading functionality

```julia
using VideoIO
function analyzeSubregions(filename,rows,cols)
    vid = openvideo(filename) # this function is provided by VideoIO package
    frames = 2000 # this is the number of frames in the video

    data = zeros(length(rows),length(cols),frames) # initialize an empty vector
    k = 0
    while !eof(vid)
        k += 1
        frame = floor.(256 .* Float64.(Gray.(read(vid))))
        data[:,:,k] = frame[rows,cols]
    end
    # some processing of "data" ...
end

```

In the `rows` and `cols` arguments to this function, I pass ranges, e.g.

```julia
analyzeSubregions("example.avi",200:25:300,1000:100:1500)

```

this creates a matrix of size `length(200:25:300) x length(1000:100:1500) x frames`, giving me a “grid” of pixels sampled over the length of the video. So far, so good!

**Now, is there a good way to extend this to a grid of sub-arrays?**

For example, I would like to use the same grid spacing as above, but with `mxn` pixels at each location. so instead of producing an array of `5 x 6 ` values at the `k`’th slice:

```julia
5×6 Array{Float64,2}:
 0.75848 0.689624 0.759477 0.13272 0.071992 0.922893
 0.499832 0.739883 0.676422 0.224262 0.13593 0.941888
 0.641937 0.842677 0.624592 0.834348 0.0732766 0.17342
 0.177902 0.128434 0.176731 0.85235 0.533129 0.886172
 0.67728 0.450755 0.92391 0.317936 0.286406 0.330416

```

I would like to get something like this at the `k`’th slice

```julia
5×6 Array{??,2}:
 [m x n] [m x n] [m x n] [m x n] [m x n] [m x n]
 [m x n] [m x n] [m x n] [m x n] [m x n] [m x n]
 [m x n] [m x n] [m x n] [m x n] [m x n] [m x n]
 [m x n] [m x n] [m x n] [m x n] [m x n] [m x n]
 [m x n] [m x n] [m x n] [m x n] [m x n] [m x n]

```

Of course, `m` and `n` would both have to be sufficiently small integers, say, between 2 and 5.

One more thing – I am not actually interested in the entire sub-arrays of size `m x n` – I’m actually only interested in the **mean** value of each sub-array.

1. Is there a good, Julia-idiomatic way of extracting a grid of sub-arrays of pixels at the `k`’th slice, similar to how I extract a grid of pixel values? How would I initialize the `data` array in this case?
2. Further, I need to take the mean of each of those arrays of pixels – so is there a way to extract the mean of the above without needing to allocate an array of arrays?

Thanks for any advice you can offer!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 10, 2021, 5:08am UTC](https://discourse.julialang.org/t/finding-the-mean-value-of-subsets-of-an-array/56848/2 "2021-03-10T05:08:36Z")

</div>

Could you do something like (pseudocode):

```julia
... 
while !eof(vid)
   ...
  for (i, row) in enumerate(rows)
    row_range = row .+ (-div(m, 2):div(m, 2)) # assuming m is even; will need to be tweaked if it's odd
    for (j, col) in enumerate(cols)
      col_range = col .+ (-div(n, 2):div(n, 2))
      sub_region = @view frame[row_range, col_range]
      data[i, j, k] = mean(sub_region)
    end
  end
end

```

That probably isn’t quite right, but hopefully it helps make a couple of useful points:

1. Use `@view` or `view` to efficiently refer to a sub-part of an array without allocating a brand new copy of that part of the array
2. Rather than constructing the array of sub-arrays, just compute the mean of each sub-array as you go. There’s no need to store them all at once, so you can make your code simpler and faster by operating on one sub-array at a time.

---

<div class="post-metadata">

**Author:** ![EmadMasroor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/emadmasroor/32/7527_2.png) [@EmadMasroor](https://discourse.julialang.org/u/EmadMasroor)\
**Post date:** [March 10, 2021, 5:28am UTC](https://discourse.julialang.org/t/finding-the-mean-value-of-subsets-of-an-array/56848/3 "2021-03-10T05:28:53Z")

</div>

This is really helpful, actually! It does the job essentially verbatim. I particularly like your `row .+ (-div(m,2):div(m,2))` idea – worth restricting my m’s and n’s to even numbers.

One question – how exactly does `sub_region = @view frame[row_range, col_range]` differ from plain old `sub_region = frame[row_range, col_range]` ?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [March 10, 2021, 5:33am UTC](https://discourse.julialang.org/t/finding-the-mean-value-of-subsets-of-an-array/56848/4 "2021-03-10T05:33:53Z")

</div>

Doing `frame[row_range, col_range]` will create a brand new array and copy the contents of that range, which is fairly expensive. `@view frame[row_range, col_range]` on the other hand just creates a lightweight reference to that section of the original array without copying any of its data.

```julia
julia> A = zeros(3, 3)
3×3 Array{Float64,2}:
 0.0 0.0 0.0
 0.0 0.0 0.0
 0.0 0.0 0.0

# B is a *copy* of the data in this region of A
julia> B = A[1:2, 1:2]
2×2 Array{Float64,2}:
 0.0 0.0
 0.0 0.0

# Since B is a copy, changing B does not affect A
julia> B .= 1
2×2 Array{Float64,2}:
 1.0 1.0
 1.0 1.0

julia> A
3×3 Array{Float64,2}:
 0.0 0.0 0.0
 0.0 0.0 0.0
 0.0 0.0 0.0

# C is a view into the *same* data as A
julia> C = @view A[1:2, 1:2]
2×2 view(::Array{Float64,2}, 1:2, 1:2) with eltype Float64:
 0.0 0.0
 0.0 0.0

# Changing C affects A:
julia> C .= 2
2×2 view(::Array{Float64,2}, 1:2, 1:2) with eltype Float64:
 2.0 2.0
 2.0 2.0

julia> A
3×3 Array{Float64,2}:
 2.0 2.0 0.0
 2.0 2.0 0.0
 0.0 0.0 0.0

```

In your case, the fact that modifying the view affects the original doesn’t matter (since you aren’t modifying either). But the fact that creating a view avoids needing to make a copy of all the data means that your code will avoid wasting time on unnecessary data copies.

---

<div class="post-metadata">

**Author:** ![EmadMasroor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/emadmasroor/32/7527_2.png) [@EmadMasroor](https://discourse.julialang.org/u/EmadMasroor)\
**Post date:** [March 10, 2021, 5:37am UTC](https://discourse.julialang.org/t/finding-the-mean-value-of-subsets-of-an-array/56848/5 "2021-03-10T05:37:16Z")

</div>

Got it, thanks! I’ll be implementing this batch-wise on a bunch of files, so any performance improvements / decreases in allocation are pretty useful for me.
