0

I have the following function that creates a shiny app which allows the user to draw a polygon in any image, the path can be changed to any folder in your computer. The default is set to use the example images in a package called ClickMetrics, i recommend using another path since this package is not available on CRAN. It is possible to calculate the area of the polygon? Maybe the proportion in pixels, so it is possible to convert the units but i have no idea how to obtain the pixels of the image.

A new polygon is created when you give a new name in the textInput.

My intention is to print the polygon area and selected proportions in the tableOutput using standard size photos

library(shiny)
library(shinydashboard)
library(tibble)
library(imager)
library(purrr)
library(spatstat)
library(tidyr)


click_poly <- function(image_path = system.file("example_images", package = "ClickMetrics")){
  app <- shinyApp(
    ui <- dashboardPage(
      
      skin = 'purple',
      
      dashboardHeader(title = "ClickMetrics"),
      
      dashboardSidebar(disable = TRUE),
      
      dashboardBody(
        fluidRow(
          box(plotOutput("IMG",
                         height = 400,
                         click = "click_plot")),
          box(selectInput("IMAGE",
                          "Images:",
                          list.files(path = image_path,
                                     pattern = ".jpg",
                                     full.names = TRUE,
                                     include.dirs = FALSE)))
        ),
        
        actionButton("clear", "Clear Points"),
        tableOutput("TABLE"),
        textInput("polygon_name", label = "Polygon name:", value = "polygon 1")
      )
    ),
    
    server <- function(input, output, session){
      img <- reactive({ ## Creates the reactive input to select an image
        f <- input$IMAGE
        imager::load.image(f)
      })
      
      CLICKS <- reactiveVal( # Store clicks
        value = tibble(
        x = numeric(),
        y = numeric(),
        name = character()
        )
      )
      
      ns <- session$ns # For Clear actionButton, to restart the session of the shiny app
      
      observeEvent(eventExpr = input$click_plot$x, handlerExpr = { ##Tibble user inputs
        add_row(CLICKS(),
                x = isolate(input$click_plot$x),
                y = isolate(input$click_plot$y),
                name = isolate(input$polygon_name)
                ) %>% CLICKS()
      })

      observe({ ## Restarting app
        if(input$clear>0){
          session$reload()
        }
      })
      
      output$IMG <- renderPlot({
        expr = {
          img <- img()
          par(mar = c(0.5, 0.5, 1.75, 0.5))
          plot(img, axes = FALSE)
          box(col = 'gray')
          mtext(text = input$IMAGE,
                side = 3,
                line = 0.5,
                adj = 0.5,
                cex = 1.23)
        }
        CLICKS() %>%
          nest(cols = -name) %>%
          deframe() %>%
          map(~polygon(.x$x, .x$y))
      })
      
      output$TABLE <- renderTable(CLICKS())
    }
  )
  runApp(app)
}

Tried to compute the area using pracma::polyarea() but the results are weird, even returning some negative areas. My intention is to print the polygon area and selected proportions in the tableOutput using standard size photos.

  • 1
    It would be a lot easier if you let the user draw the image in some kind of vector format (so you can actually collect the vertices of the polygon and directly calculate the actual area instead of the area of a pixelated polygon). – Remko Duursma Jan 26 '23 at 09:31
  • Yes, the area calculated with `polyarea` can be negative, it all depends on the direction of circulation you or the interactive user chooses. So what is so weird about the results? – Hans W. Jan 27 '23 at 23:50

0 Answers0