@@ -3,79 +3,95 @@ library(reticulate) # Used to call Tensorflow Python script
33library(shiny )
44library(shinycssloaders )
55
6+ behavior <- config :: get(" image" )
7+ stopifnot(behavior %in% c(" upload" , " fetch-image-url" ))
8+
69# Load source of Python image classifier script
710source_python(' image-classifier.py' )
811
912server <- function (input , output , session ) {
10-
11- output $ contents <- renderTable({
12- # After the user uploads a file, the image will be classified and the predictions will be shown.
13+
14+ # where the image that should be classified is on disk
15+ image_path <- reactiveVal(" ./img/cat.jpg" )
16+
17+ image_prefix <- " pytorch_image"
18+
19+ # the configurable selector for fetch-image-url vs. upload
20+ output $ image_selector <- renderUI({
21+ if (behavior == " fetch-image-url" ) {
22+ list (
23+ textInput(" file1" , label = h5(" Enter Image URL:" ), value = " " ),
24+ actionButton(" fetch-image-url" , " Fetch Image" )
25+ )
26+ } else if (behavior == " upload" ) {
27+ fileInput(" file_upload" , label = h5(" Upload an Image:" ))
28+ } else {
29+ stop(" Invalid configuration. Please chose 'fetch-image-url' or 'upload'" )
30+ }
31+ })
32+
33+ # handle upload
34+ observe({
35+ req(input $ file_upload )
36+ upload_file <- input $ file_upload
37+ image_path(upload_file $ datapath [[1 ]])
38+ })
39+
40+ # handle fetch-image-url
41+ observeEvent(input [[" fetch-image-url" ]], {
1342 req(input $ file1 )
43+ tryCatch({
44+ # Fetch image from URL
45+ temp_fetch_image_url <- fs :: file_temp(image_prefix , ext = " .jpg" )
46+ downloader :: download(input $ file1 , temp_fetch_image_url )
47+
48+ image_path(temp_fetch_image_url )
49+ }, error = function (e ){
50+ # usually, you would not expose this to the user
51+ # without a little sanitization
52+ showNotification(as.character(safeError(e )), type = " warning" )
53+ })
54+ })
55+
56+ output $ contents <- renderTable({
57+ req(image_path())
1458
1559 tryCatch(
1660 {
17- # Download image from URL
18- downloader :: download(input $ file1 , " image" )
19-
2061 # Call function from PyTorch Python script to classify image
21- results <- classify_image_pytorch(image_path = " image " )
62+ results <- classify_image_pytorch(image_path = image_path() )
2263 },
2364 error = function (e ) {
24- stop(safeError(e ))
65+ # usually, you would not expose this to the user
66+ # without a little sanitization
67+ showNotification(as.character(safeError(e )), type = " warning" )
2568 }
2669 )
2770 return (results )
2871 })
2972
73+ # render the image
3074 output $ image1 <- renderImage({
31- req(input $ file1 )
32- tryCatch(
33- {
34- input $ file1
35- },
36- error = function (e ) {
37- stop(safeError(e ))
38- }
39- )
75+ req(image_path())
76+
77+ # Copy the image to temp space
78+ new_path <- fs :: file_copy(image_path(), fs :: file_temp(image_prefix , ext = " .jpg" ))
4079
4180 # Return a list containing the filename
42- if (is.null(input $ file1 )) {
81+ if (is.null(new_path )) {
4382 return (NULL )
4483 }
4584 else {
46- return (list (src = " image " ))
85+ return (list (src = new_path , style = htmltools :: css( width = " 100% " ) ))
4786 }
4887 })
4988
50- observe({
51- x = input $ oil_platform
52- image_url = " https://upload.wikimedia.org/wikipedia/commons/a/a1/Oil_platform.jpeg"
53- updateTextInput(session , " file1" , value = paste(image_url ))
54- })
55-
56- observe({
57- x = input $ truck
58- image_url = " https://upload.wikimedia.org/wikipedia/commons/6/6c/Toyota-1984-truck.jpg"
59- updateTextInput(session , " file1" , value = paste(image_url ))
60- })
61-
62- observe({
63- x = input $ flower
64- image_url = " https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Aster_Tataricus.JPG/612px-Aster_Tataricus.JPG"
65- updateTextInput(session , " file1" , value = paste(image_url ))
66- })
67-
68- observe({
69- x = input $ cat
70- image_url = " https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Egyptian_Mau_Bronze.jpg/611px-Egyptian_Mau_Bronze.jpg"
71- updateTextInput(session , " file1" , value = paste(image_url ))
72- })
73-
74- observe({
75- x = input $ dog
76- image_url = " https://upload.wikimedia.org/wikipedia/commons/e/e4/Border_Collie_600.jpg"
77- updateTextInput(session , " file1" , value = paste(image_url ))
78- })
89+ # default images
90+ observeEvent(input $ oil_platform , image_path(" ./img/oil_platform.jpg" ))
91+ observeEvent(input $ truck , image_path(" ./img/truck.jpg" ))
92+ observeEvent(input $ flower , image_path(" ./img/flower.jpg" ))
93+ observeEvent(input $ cat , image_path(" ./img/cat.jpg" ))
94+ observeEvent(input $ dog , image_path(" ./img/dog.jpg" ))
7995
8096}
8197
@@ -84,8 +100,8 @@ ui <- fluidPage(
84100 titlePanel(" Image Classifier" ),
85101 sidebarLayout(
86102 sidebarPanel(
87- textInput( " file1 " , label = h5( " Enter Image URL: " ), value = " " ),
88- helpText(" Your image will be downloaded and classified using Tensorflow in Python." ),
103+ uiOutput( " image_selector " ),
104+ helpText(" Your image will be classified using Tensorflow in Python." ),
89105 helpText(" The resulting predictions will be shown along with their confidence level." ),
90106 hr(),
91107 helpText(" Or, choose an example image:" ),
@@ -103,7 +119,7 @@ ui <- fluidPage(
103119 mainPanel(
104120 # Output
105121 tableOutput(" contents" ) %> % withSpinner(),
106- imageOutput(" image1" ) %> % withSpinner(color = " #ffffff" )
122+ imageOutput(" image1" , height = NULL ) %> % withSpinner(color = " #ffffff" )
107123 )
108124 )
109125)
0 commit comments