Home > OS >  How to cut a polygon out of an image and move it to another part of the image?
How to cut a polygon out of an image and move it to another part of the image?

Time:08-19

I want to cut a polygon from a photo and move it to another place in the photo and I want to plot the final image with ggplot2.

I use the terra package (feel free to suggest a better approach/method) to convert the photo into a data.frame which is necessary for ggplot2:

# load libraries
library(terra)
library(ggplot2)

# download the cat photo from internet (its an open source photo)
cat_url = "https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg?auto=compress&cs=tinysrgb&w=600"
download.file(url = cat_url, destfile = "cat.jpeg")

# return the full path to the cat photo
cat_path = list.files(pattern = "cat.jpeg", full.names = TRUE) 

# load the cat photo as rast from terra
cat_rast = rast(cat_path)

# convert the rast file into a dataframe containing the pixels in red, green and blue channels
cat_df = as.data.frame(cat_rast, xy = TRUE) # xy = TRUE returns x and y coordinates as 1st and 2nd columns

I can now plot the red channel of the image using ggplot2:

# plot red channel with ggplot2
ggplot(data = cat_df, aes(x, y, fill = cat_1))   # cat_1 corresponds to the 1st channel in the image, which is red
        geom_raster()  
        coord_fixed(xlim = c(0, 1.5), ylim = c(0, 1.5))

which produces:

enter image description here

What I want to do at this point is to cut a polygon from the left side of the image and move all the pixels contained in the polygon to the right side of the image. I also want to cut a polygon from the bottom and move it up.

Using photoshop:

enter image description here

Here, the drawn "polygon" on the left should then be moved to the right side of the image and the drawn "polygon" on the bottom should be moved to the upper side of the image.

CodePudding user response:

cat_url = "https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg?auto=compress&cs=tinysrgb&w=600"

library(terra)    
x <- rast(cat_url)
ext(x) <- c(0,1,0,1) # for forward compatibility and generality

You can draw polygons like this

#plot(x)
#p <- draw("polygon")

predefined polygon

p <- vect("POLYGON ((0.419787 0.740037, 0.528909 0.996227, 0.623798 0.996227, 0.666498 0.673618, 0.609565 0.645152, 0.419787 0.740037))")

Crop/mask the area you want to use, and shift it a number of entire pixels

a <- crop(x, p, mask=TRUE)
r <- res(x)

b <- shift(a, 150*r[1], 125*r[2])

If this had been cut from the left side and you want to move it to the right side, you would do b <- shift(a, 1, 0)

Remove the area from the original and merge

y <- mask(x, p, inverse=TRUE)
z <- merge(b, y)

Set RGB channels again and plot (here using base-plot)

RGB(z) <- 1:3
plot(z)

enter image description here

CodePudding user response:

If you want to do this all within ggplot, perhaps it is just as easy to select which pixels you want to move and move them. For the curves you have drawn, the pixels are bounded by simple quadratic curves, so you could do:

cat_rast <- rast(cat_url)

cat_df = as.data.frame(cat_rast, xy = TRUE)
names(cat_df) <- c('x', 'y', 'R', 'G', 'B')

shift1 <- cat_df$y <  0.5 * (abs(cat_df$x-0.1))^1.8   0.45 & 
          cat_df$y > cat_df$x^2   0.25

shift2 <- cat_df$y < (cat_df$x   0.2)^4 - 0.2 &
          cat_df$y < (cat_df$x - 1.5)^4 - 0.2

cat_df$x[shift1] <- cat_df$x[shift1]   1
cat_df$y[shift2] <- cat_df$y[shift2]   1

ggplot(data = cat_df, aes(x, y, fill = R))  
  geom_raster()  
  coord_fixed(xlim = c(0, 1.5), ylim = c(0, 1.5))

enter image description here

  • Related