@@ -3,79 +3,95 @@ library(reticulate) # Used to call Tensorflow Python script
3
3
library(shiny )
4
4
library(shinycssloaders )
5
5
6
+ behavior <- config :: get(" image" )
7
+ stopifnot(behavior %in% c(" upload" , " fetch-image-url" ))
8
+
6
9
# Load source of Python image classifier script
7
10
source_python(' image-classifier.py' )
8
11
9
12
server <- 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" ]], {
13
42
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())
14
58
15
59
tryCatch(
16
60
{
17
- # Download image from URL
18
- downloader :: download(input $ file1 , " image" )
19
-
20
61
# 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() )
22
63
},
23
64
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" )
25
68
}
26
69
)
27
70
return (results )
28
71
})
29
72
73
+ # render the image
30
74
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" ))
40
79
41
80
# Return a list containing the filename
42
- if (is.null(input $ file1 )) {
81
+ if (is.null(new_path )) {
43
82
return (NULL )
44
83
}
45
84
else {
46
- return (list (src = " image " ))
85
+ return (list (src = new_path , style = htmltools :: css( width = " 100% " ) ))
47
86
}
48
87
})
49
88
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" ))
79
95
80
96
}
81
97
@@ -84,8 +100,8 @@ ui <- fluidPage(
84
100
titlePanel(" Image Classifier" ),
85
101
sidebarLayout(
86
102
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." ),
89
105
helpText(" The resulting predictions will be shown along with their confidence level." ),
90
106
hr(),
91
107
helpText(" Or, choose an example image:" ),
@@ -103,7 +119,7 @@ ui <- fluidPage(
103
119
mainPanel(
104
120
# Output
105
121
tableOutput(" contents" ) %> % withSpinner(),
106
- imageOutput(" image1" ) %> % withSpinner(color = " #ffffff" )
122
+ imageOutput(" image1" , height = NULL ) %> % withSpinner(color = " #ffffff" )
107
123
)
108
124
)
109
125
)
0 commit comments