Skip to content

Instantly share code, notes, and snippets.

@slopp
Last active June 1, 2017 20:32
Show Gist options
  • Save slopp/96ef090cd97bb304f12da8e714de55ea to your computer and use it in GitHub Desktop.
Save slopp/96ef090cd97bb304f12da8e714de55ea to your computer and use it in GitHub Desktop.
Pachyderm Shiny App
# App requires a pachyderm pipeline with
# input repo "images"
# output repo "edges"
# The app assumes that pachyderm is being run locally with minikube.
# See: http://pachyderm.readthedocs.io/en/latest/getting_started/beginner_tutorial.html
# Setup -------------------------------------------------------------------
library(shiny)
source("flickr_api.R") # file for querying flickr
# set the ADDRESS environment variable
# TODO: Change this to the true IP address of pachyderm service if you're not using minikube
IP <- system2("minikube", "ip", stdout = TRUE)
ADDRESS <- paste0(IP, ":30650")
Sys.setenv(ADDRESS = ADDRESS)
# User-Interface -------------------------------------------------------------------
ui <- fluidPage(
titlePanel("Image Edge Detector"),
sidebarLayout(
sidebarPanel(
textInput("img", "Enter a search term for an interesting image:"),
actionButton("search","Search"),
br(),
uiOutput("edges")
),
mainPanel(
p("This application searches flicker for the user's search term and returns the top result."),
p("Then the application submits the image to a pachyderm pipeline that does edge detection."),
p("Once the pipeline finishes, the application displays the result."),
htmlOutput("img_raw"),
plotOutput("img_edges")
)
)
)
server <- function(input, output, session) {
# Search flickr and return the url for the top result
img_url <- eventReactive(input$search, {
flickr_photo_url(flickr_photos_search_one(input$img))
})
# Add an img tag with the original image
output$img_raw <- renderText({
req(input$img)
capture.output(img(src = img_url()))
})
# Once a user searches for an image, present the option to run edge detection
output$edges <- renderUI({
req(input$img)
actionButton("run_edges", "Detect Edges")
})
# Create a name for the image based on the search string
tmp_img_name <- reactive({
paste0(input$img, ".png")
})
# When a user clicks "Detect Edges", add the image to the pachyderm pipeline
# This action kicks off a job to do edge detection
observeEvent(input$run_edges, {
system2("rm", "www/tmp.png")
system2("pachctl", paste0("put-file images master ", tmp_img_name(), " -c -f ", img_url()))
})
# Helper function to check if pachyderm is done processing the image
check_pachyd_for_output <- function(){
output <- system2("pachctl", paste0("list-file edges master"), stdout = TRUE)
sum(grepl(pattern = tmp_img_name(), x = output, fixed = TRUE))
}
# Run the helper function ever 500 ms
# This is a crude re-implementation of reactivePoll when the result is an image file
ready <- reactive({
invalidateLater(500)
check_pachyd_for_output()
})
# If the edge detection image is ready, render it
output$img_edges <- renderImage({
req(input$run_edges)
# ensure pachyd output is ready
req(ready() > 0)
# get file from pachyd
outfile <- tempfile(fileext = ".png")
width <- session$clientData$output_img_edges_width
height <- session$clientData$output_img_edges_height
system2("pachctl", paste0("get-file edges master ", tmp_img_name(), " >> ", outfile))
list(src = outfile,
width = width,
height = height)
}, deleteFile = TRUE)
}
shinyApp(ui = ui, server = server)
library(httr)
# Please don't copy my API key. Get your own here, it's fast and free:
# https://www.flickr.com/services/api/keys/apply/
api_key <- "d500440eceeb202efc5414d5b23d050c"
# Get a data frame for the search term; one photo will be selected at random
# from the top 10 most relevant
flickr_photos_search_one <- function(query) {
resp <- GET(
sprintf(
"https://api.flickr.com/services/rest/?method=flickr.photos.search&format=json&api_key=%s&text=%s&safe_search=1&content_type=1&per_page=10&sort=relevance",
api_key,
utils::URLencode(query)
),
accept_json()
)
resp <- jsonlite::fromJSON(sub("^jsonFlickrApi\\((.*)\\)$", "\\1", rawToChar(resp$content)))
if (length(resp$photos$photo) == 0 || nrow(resp$photos$photo) == 0)
return(NULL)
resp$photos$photo[sample.int(nrow(resp$photos$photo), 1),]
}
# Form image URLs from flickr photos data frame
flickr_photo_url <- function(photo) {
if (is.null(photo) || nrow(photo) == 0)
return(character(0))
sprintf(
"https://farm%s.staticflickr.com/%s/%s_%s.jpg",
photo$farm,
photo$server,
photo$id,
photo$secret
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment