Skip to content

Instantly share code, notes, and snippets.

@andland
Last active January 1, 2017 13:43
Show Gist options
  • Save andland/efe66240184328f07429 to your computer and use it in GitHub Desktop.
Save andland/efe66240184328f07429 to your computer and use it in GitHub Desktop.
Time Stack and Time Slicing

See this link for an introduction on time stacking and time slicing.

time_slice.R requires the number of pixels wide or tall the image is to be a multiple of the number of images in your timelapse.

time_slice_v2.R attempts to get around this. Some images will contribute more pixels per slice than others. This is done by making the first x% of the images cover the first x% of the pixels (with appropriate rounding). It does not deal with number of images being greater than the height or width of the images in pixels. Version 2 will probably work better for you.

For example, if the images are 150 pixels wide and your timelapse has 100 images, time_slice.R will make the first image have a slice which is 51 pixels wide. The remaining 99 images will get slices which are 1 pixel wide. time_slice_v2.R will alternate between 1 pixel per image and 2 pixels per image. All of the odd numbered images will get 1 pixel and all of the even numbered images will get 2 pixels. I haven't tested it out enough to tell if this causes any weird undesired (or desired) effects.

Time Slice Lapse

time_slice_lapse.R creates a time lapse out of time slices. (It actually creates the images necessary to create a time lapse. You still have to combine them into a movie.)

There are five options. As before, you can choose the direction. Then I split the path into source_path and save_path. The source_path is where the original images are saved. The save_path is where you want to save the time_slices, which will be used to create a time lapse.

The two new options are images_per_slice and num_of_slices. images_per_slice controls how many images make up each slice and num_of_slices controls how many slices will be in the time lapse. You probably want to use the default for the num_of_slices (i.e. use all of the available images). For images_per_slice, you can probably get different results based on this. The larger this is, the more time passes with a slice, but the fewer available slices for a time lapse. images_per_slice must be less than the number of pixels wide or tall.

I tried it out on a small example and it seems to work. I used only 10 images_per_slice which resulted in 36 total slices. It is posted here.

License

The code I have written is licensed MIT. Copyright Andrew Landgraf.

library(jpeg)
direction = "E" # in c("N", "S", "E", "W")
# make sure the path ends with a '/'
path = "enter/path/here/"
# this gets all the files in the folder that end in JPG or JPEG
files = list.files(path)
files = files[(toupper(substring(files, nchar(files) - 3)) == ".JPG" |
toupper(substring(files, nchar(files) - 4)) == ".JPEG")]
baseimg = readJPEG(paste0(path, files[1]))
# extra_pixels gives the first frame the extra pixels due to rounding
if (direction %in% c("E", "W")) {
num_pixels = floor(dim(baseimg)[2] / length(files))
extra_pixels = dim(baseimg)[2] - num_pixels * length(files)
} else if (direction %in% c("N", "S")) {
num_pixels = floor(dim(baseimg)[1] / length(files))
extra_pixels = dim(baseimg)[1] - num_pixels * length(files)
}
horiz = 1:dim(baseimg)[2]
vert = 1:dim(baseimg)[1]
for (i in 2:length(files)) {
cat(i, "of", length(files), "\n")
newimg = readJPEG(paste0(path, files[i]))
if (direction == "E") {
horiz = (num_pixels * (i - 1) + 1):(num_pixels * i) + extra_pixels
} else if (direction == "W") {
horiz = dim(baseimg)[2] - (num_pixels * (i - 1)):(num_pixels * i - 1) - extra_pixels
} else if (direction == "N") {
vert = dim(baseimg)[1] - (num_pixels * (i - 1)):(num_pixels * i - 1) - extra_pixels
} else if (direction == "S") {
vert = (num_pixels * (i - 1) + 1):(num_pixels * i) + extra_pixels
}
baseimg[vert, horiz, ] = newimg[vert, horiz, ]
}
writeJPEG(baseimg, paste0(path, "TimeSlice-", direction, ".JPG"), 1)
library(jpeg)
direction = "E" # in c("N", "S", "E", "W")
# make sure the paths end with a '/'
source_path = "path/to/original/images/"
save_path = "path/to/where/to/save/slices/"
files = list.files(source_path)
# get all of the images that end in .JPG or .JPEG
files = files[(toupper(substring(files, nchar(files) - 3)) == ".JPG" |
toupper(substring(files, nchar(files) - 4)) == ".JPEG")]
images_per_slice = round(length(files) / 2)
num_of_slices = length(files) - images_per_slice + 1
for (slice_num in 1:num_of_slices) {
cat("Slice", slice_num, "of", num_of_slices, "\n")
first_img = slice_num
# last_img = images_per_slice + slice_num - 1
# assumes all images are the same dimensions as the first image
baseimg = readJPEG(paste0(source_path, files[first_img]))
height = dim(baseimg)[1]
width = dim(baseimg)[2]
# num_images = length(files)
# the slicing will use all the pixels in one dimension
if (direction %in% c("E", "W")) {
vert = 1:height
} else if (direction %in% c("N", "S")) {
horiz = 1:width
}
end_pixel = floor(ifelse(direction %in% c("E", "W"), width, height) / images_per_slice * 1)
for (i in 2:images_per_slice) {
cat(" - Image", i, "of", images_per_slice, "\n")
newimg = readJPEG(paste0(source_path, files[first_img + i - 1]))
begin_pixel = end_pixel + 1
end_pixel = floor(ifelse(direction %in% c("E", "W"), width, height) / images_per_slice * i)
if (direction == "E") {
horiz = begin_pixel:end_pixel
} else if (direction == "W") {
horiz = width - (begin_pixel:end_pixel) + 1
} else if (direction == "N") {
vert = height - (begin_pixel:end_pixel) + 1
} else if (direction == "S") {
vert = begin_pixel:end_pixel
}
baseimg[vert, horiz, ] = newimg[vert, horiz, ]
}
writeJPEG(baseimg, paste0(save_path, "TimeSlice-", direction, "-",
sprintf("%03d", slice_num), ".JPG"), 1)
rm(baseimg)
}
library(jpeg)
direction = "E" # in c("N", "S", "E", "W")
# make sure the path ends with a '/'
path = "enter/path/here/"
# this gets all the files in the folder that end in JPG or JPEG
files = list.files(path)
files = files[(toupper(substring(files, nchar(files) - 3)) == ".JPG" |
toupper(substring(files, nchar(files) - 4)) == ".JPEG")]
# assumes all images are the same dimensions as the first image
baseimg = readJPEG(paste0(path, files[1]))
height = dim(baseimg)[1]
width = dim(baseimg)[2]
num_images = length(files)
# the slicing will use all the pixels in one dimension
if (direction %in% c("E", "W")) {
vert = 1:height
} else if (direction %in% c("N", "S")) {
horiz = 1:width
}
end_pixel = floor(ifelse(direction %in% c("E", "W"), width, height) / num_images * 1)
for (i in 2:num_images) {
cat(i, "of", num_images, "\n")
newimg = readJPEG(paste0(path, files[i]))
begin_pixel = end_pixel + 1
end_pixel = floor(ifelse(direction %in% c("E", "W"), width, height) / num_images * i)
if (direction == "E") {
horiz = begin_pixel:end_pixel
} else if (direction == "W") {
horiz = width - (begin_pixel:end_pixel) + 1
} else if (direction == "N") {
vert = height - (begin_pixel:end_pixel) + 1
} else if (direction == "S") {
vert = begin_pixel:end_pixel
}
baseimg[vert, horiz, ] = newimg[vert, horiz, ]
}
writeJPEG(baseimg, paste0(path, "TimeSlice-", direction, ".JPG"), 1)
library(jpeg)
# make sure the path ends with a '/'
path = "enter/path/here/"
files = list.files(path)
files = files[(toupper(substring(files, nchar(files) - 3)) == ".JPG" |
toupper(substring(files, nchar(files) - 4)) == ".JPEG")]
baseimg = readJPEG(paste0(path, files[1]))
for (i in 2: length(files)) {
cat(i, "of", length(files), "\n")
newimg = readJPEG(paste0(path, files[i]))
for (d in 1:3) {
baseimg[, , d] = pmax(baseimg[, , d], newimg[, , d])
}
}
writeJPEG(baseimg, paste0(path, "TimeStack.JPG"), 1)
@errorsurface
Copy link

Works perfect, thanks!

@errorsurface
Copy link

Sometimes while using time_slice_v2.R I get:

Error in newimg[vert, horiz, ] : subscript out of bounds
Execution halted

and some other times:

Error in newimg[vert, horiz, ] : incorrect number of dimensions

Even if I'm using images of equal size, certain folder of images will work and others won't.
What could it be? I noticed that if I remove some images, sometimes it accomplishes to create the time slice, but none of the files seem corrupt or any different from the others.
Thank you.

@andland
Copy link
Author

andland commented Dec 4, 2015

@gomezgomez Sorry for the delayed response. Github does not alert me when there are comments on Gists.

I unfortunately do not know what could be causing that issue besides have images of varying sizes. Make sure there are no unexpected images in the folder you are using. If you have a small example I can reproduce, I can try to debug it.

@pthiedeke
Copy link

Hi Andrew, Thanks so much for your scripts and descriptions, this is amazing stuff. I am new to code so am having a few teething issues. I have downloaded R and the scripts but am not able to get it working. Can you tell me the routine for importing images into time_slice_lapse.R once R is open ? Thanks again, Peter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment