cella110n commited on
Commit
b50a28a
1 Parent(s): 0954e70

Upload 2 files

Browse files
Files changed (2) hide show
  1. app_0813.R +604 -0
  2. script.R +196 -0
app_0813.R ADDED
@@ -0,0 +1,604 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ rm(list=ls())
2
+
3
+ # 必要なライブラリを読み込む
4
+ library(shiny)
5
+
6
+ # 事前に定義された関数を含むRスクリプトを読み込む
7
+ source("./script.R")
8
+
9
+ # パネル用関数
10
+ orderInputPanel <- function() {
11
+ conditionalPanel(
12
+ condition = "output.showOrderInput",
13
+ numericInput("target_order", "Target Order:", value = 1, min = 1),
14
+ actionButton("confirm_order", "Confirm Order"),
15
+ actionButton("cancel_order", "Cancel")
16
+ )
17
+ }
18
+
19
+ textInputPanel <- function() {
20
+ conditionalPanel(
21
+ condition = "output.showTextInput",
22
+ textInput("related_captions_input", "Enter related captions (comma separated):"),
23
+ actionButton("confirm_text", "Confirm Order"),
24
+ actionButton("cancel_text", "Cancel")
25
+ )
26
+ }
27
+
28
+ # UIを定義
29
+ ui <- fluidPage(
30
+ # アプリケーションのタイトル
31
+ titlePanel("SDtagEditoR"),
32
+
33
+ # CSSを追加
34
+ tags$style(type = "text/css",
35
+ "#image_captions { white-space: pre-wrap; }",
36
+ ".shiny-action-button { margin-bottom: 50px; }"
37
+ ),
38
+
39
+ # JavaScript関数を追加
40
+ tags$head(tags$script(HTML("
41
+ function copyToClipboard(text) {
42
+ var dummy = document.createElement('textarea');
43
+ document.body.appendChild(dummy);
44
+ dummy.value = text;
45
+ dummy.select();
46
+ document.execCommand('copy');
47
+ document.body.removeChild(dummy);
48
+ }
49
+ "))),
50
+
51
+ # ユーザー入力を受け付ける部分
52
+ sidebarLayout(
53
+ sidebarPanel(
54
+ # ディレクトリパスを入力するテキストボックス
55
+ textInput("directory_path", "Enter the directory path:", value = ""),
56
+
57
+ # キャプションデータを読み込むボタン
58
+ actionButton("load_data", "Load Captions Data"),
59
+ tags$br(),
60
+ tags$br(),
61
+
62
+ conditionalPanel(
63
+ condition = "output.dataLoaded",
64
+
65
+ # 画像の選択
66
+ selectInput("selected_image", "Choose an image:", choices = NULL),
67
+
68
+ # 前後の画像に移動するボタン
69
+ actionButton("prev_image", "Prev"),
70
+ actionButton("next_image", "Next"),
71
+ tags$br(),
72
+ tags$br(),
73
+
74
+ # タブセット
75
+ actionButton("shuffle_single", "Shuffle Order for Current Image"),
76
+ actionButton("shuffle_all", "Shuffle Order for All Images"),
77
+ tags$br(),
78
+ tags$br(),
79
+ numericInput("frequency_threshold", "Frequency Threshold:", value = 5, min = 1),
80
+ actionButton("remove_low_freq", "Remove Low Frequency Captions"),
81
+ tags$br(),
82
+ tags$br(),
83
+ textInput("edit_caption", "Caption to Edit:", ""),
84
+ actionButton("remove_single", "Remove from Single"),
85
+ actionButton("remove_from_all", "Remove from All"),
86
+ # actionButton("edit_interactively", "Edit Interactively"),
87
+ tags$br(),
88
+ actionButton("add_single", "Add to Single"),
89
+ actionButton("add_to_all", "Add to All"),
90
+ tags$br(),
91
+ actionButton("move_caption", "Move Caption"),
92
+ actionButton("move_caption_all", "Move Caption of All"),
93
+ tags$br(),
94
+ actionButton("remove_related_single", "Remove Related from Single"),
95
+ actionButton("remove_related_all", "Remove Related from all"),
96
+ orderInputPanel(),
97
+ textInputPanel(), # ここで関数を呼び出しています
98
+ # conditionalPanel(
99
+ # condition = "output.showCaptionConfirmation",
100
+ # tags$div("Do you want to remove the caption '", tags$span(id="confirm_caption", ""), "' from the selected image?"),
101
+ # actionButton("yes_button", "Yes"),
102
+ # actionButton("no_button", "No"),
103
+ # actionButton("end_button", "End")
104
+ # )
105
+ )
106
+ ),
107
+
108
+ mainPanel(
109
+ fluidRow(
110
+ column(6,
111
+ imageOutput("image_display", width = "100%", height = "50%"),
112
+ tags$br(),
113
+ uiOutput("image_captions")
114
+ ),
115
+ column(6,
116
+ verbatimTextOutput("log_output"), # ログの表示領域を追加
117
+ fluidRow( # この行を追加
118
+ column(6, tableOutput("selected_image_captions")),
119
+ column(6, tableOutput("caption_frequency_table_with_links"))
120
+ )
121
+ )
122
+ )
123
+ )
124
+
125
+ )
126
+ )
127
+
128
+
129
+ # サーバーロジックを定義
130
+ server <- function(input, output, session) {
131
+ # リアクティブな変数を定義
132
+ directory_path <- reactiveVal()
133
+ captions_data <- reactiveVal()
134
+ caption_frequency <- reactiveVal()
135
+ operation_mode <- reactiveVal(NULL)
136
+ log_text <- reactiveVal("Log:\n")
137
+
138
+ # ログを追加する関数
139
+ add_log <- function(message) {
140
+ current_log <- log_text()
141
+ new_log <- paste(current_log, message, "\n")
142
+ log_text(new_log)
143
+ }
144
+
145
+ # ログを更新する関数
146
+ update_log <- function(message) {
147
+ log_text(message)
148
+ }
149
+
150
+ # 読み込み確認
151
+ output$dataLoaded <- reactive({
152
+ !is.null(captions_data())
153
+ })
154
+ outputOptions(output, "dataLoaded", suspendWhenHidden=FALSE)
155
+
156
+ ## Load Data
157
+ observeEvent(input$load_data, {
158
+ update_log("Loading captions data...")
159
+
160
+ # ボタンが押されたときに実行されるコード
161
+ temp_directory_path <- isolate(input$directory_path)
162
+ temp_captions_data <- read_captions_from_directory(temp_directory_path)
163
+ temp_caption_frequency <- get_caption_frequency(temp_captions_data)
164
+
165
+ # リアクティブな変数を更新
166
+ directory_path(temp_directory_path)
167
+ captions_data(temp_captions_data)
168
+ caption_frequency(temp_caption_frequency)
169
+
170
+ # 画像の選択のための選択肢を更新
171
+ unique_images <- unique(captions_data()$image_path)
172
+ updateSelectInput(session, "selected_image", choices = unique_images, selected = unique_images[1])
173
+
174
+ update_log("Captions data loaded.")
175
+ })
176
+
177
+ # 画像の移動
178
+ observeEvent(input$prev_image, {
179
+ current_index <- which(unique(captions_data()$image_path) == input$selected_image)
180
+ if (current_index > 1) {
181
+ updateSelectInput(session, "selected_image", selected = unique(captions_data()$image_path)[current_index - 1])
182
+ }
183
+ })
184
+
185
+ observeEvent(input$next_image, {
186
+ current_index <- which(unique(captions_data()$image_path) == input$selected_image)
187
+ if (current_index < length(unique(captions_data()$image_path))) {
188
+ updateSelectInput(session, "selected_image", selected = unique(captions_data()$image_path)[current_index + 1])
189
+ }
190
+ })
191
+
192
+ # Shuffle Order for Current Image
193
+ observeEvent(input$shuffle_single, {
194
+ if (!is.null(operation_mode())) {
195
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
196
+ return()
197
+ }
198
+
199
+ current_image <- input$selected_image
200
+ updated_data <- captions_data()
201
+ captions_for_current_image <- filter(updated_data, image_path == current_image)
202
+
203
+ # Orderをランダムにする
204
+ new_order <- sample(1:nrow(captions_for_current_image), nrow(captions_for_current_image))
205
+ captions_for_current_image$caption_order <- new_order
206
+
207
+ # データを更新
208
+ updated_data[updated_data$image_path == current_image, ] <- captions_for_current_image
209
+ captions_data(updated_data)
210
+
211
+ update_log("captions of this image was shauffled.")
212
+ })
213
+
214
+ # Shuffle Order for All Images
215
+ observeEvent(input$shuffle_all, {
216
+ if (!is.null(operation_mode())) {
217
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
218
+ return()
219
+ }
220
+
221
+ updated_data <- captions_data()
222
+ unique_images <- unique(updated_data$image_path)
223
+
224
+ for (image in unique_images) {
225
+ captions_for_image <- filter(updated_data, image_path == image)
226
+ new_order <- sample(1:nrow(captions_for_image), nrow(captions_for_image))
227
+ captions_for_image$caption_order <- new_order
228
+ updated_data[updated_data$image_path == image, ] <- captions_for_image
229
+ }
230
+
231
+ captions_data(updated_data)
232
+ update_log("captions of all images was shauffled.")
233
+ })
234
+
235
+ # remove_low_freqボタンが押されたときの処理
236
+ observeEvent(input$remove_low_freq, {
237
+ if (!is.null(operation_mode())) {
238
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
239
+ return()
240
+ }
241
+
242
+ if (!is.null(captions_data())) {
243
+ threshold <- input$frequency_threshold
244
+ updated_data <- remove_low_frequency_captions(captions_data(), threshold)
245
+ captions_data(updated_data)
246
+
247
+ # キャプションの頻度を更新
248
+ updated_caption_frequency <- get_caption_frequency(updated_data)
249
+ caption_frequency(updated_caption_frequency)
250
+ }
251
+
252
+ update_log("Low frequency captions removed.")
253
+ })
254
+
255
+ # Remove Captions from All Images
256
+ observeEvent(input$remove_from_all, {
257
+ if (!is.null(operation_mode())) {
258
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
259
+ return()
260
+ }
261
+
262
+ # 指定されたキャプションをすべての画像から削除
263
+ target_caption <- input$edit_caption
264
+ updated_data <- captions_data()
265
+ unique_images <- unique(updated_data$image_path[updated_data$caption == target_caption])
266
+ for (image in unique_images) {
267
+ updated_data <- remove_caption_and_adjust_order(updated_data, image, target_caption)
268
+ }
269
+ captions_data(updated_data)
270
+
271
+ # キャプションの頻度を更新
272
+ updated_caption_frequency <- get_caption_frequency(updated_data)
273
+ caption_frequency(updated_caption_frequency)
274
+
275
+ update_log("Caption removed from all images.")
276
+ })
277
+
278
+ # Edit Captions Interactivelyの処理
279
+ # グローバル変数として画像のインデックスと画像リストを保持
280
+ # image_index <- reactiveVal(1)
281
+ # image_list <- reactiveVal()
282
+ # show_confirmation <- reactiveVal(FALSE)
283
+
284
+ # observeEvent(input$edit_interactively, {
285
+ # update_log("Starting interactive caption editing...")
286
+ #
287
+ # # 該当するキャプションを持つ画像のリストを取得
288
+ # target_caption <- input$edit_caption
289
+ # images <- search_by_caption(captions_data(), target_caption)$image_path
290
+ # image_list(images)
291
+ # image_index(1)
292
+ # show_confirmation(TRUE)
293
+ # updateSelectInput(session, "selected_image", selected = images[1])
294
+ # })
295
+ #
296
+ # observeEvent(input$yes_button, {
297
+ # update_log(paste("Caption removed from image:", input$selected_image))
298
+ #
299
+ # # キャプションを削除
300
+ # captions_data(remove_caption_and_adjust_order(captions_data(), input$selected_image, input$edit_caption))
301
+ #
302
+ # # 次の画像を表示
303
+ # image_index(image_index() + 1)
304
+ # if (image_index() <= length(image_list())) {
305
+ # updateSelectInput(session, "selected_image", selected = image_list()[image_index()])
306
+ # } else {
307
+ # show_confirmation(FALSE)
308
+ # update_log("Interactive caption editing ended.")
309
+ # }
310
+ # })
311
+ #
312
+ # observeEvent(input$no_button, {
313
+ # update_log(paste("Caption retained for image:", input$selected_image))
314
+ #
315
+ # # 次の画像を表示
316
+ # image_index(image_index() + 1)
317
+ # if (image_index() <= length(image_list())) {
318
+ # updateSelectInput(session, "selected_image", selected = image_list()[image_index()])
319
+ # } else {
320
+ # show_confirmation(FALSE)
321
+ # update_log("Interactive caption editing ended.")
322
+ # }
323
+ # })
324
+ #
325
+ # observeEvent(input$end_button, {
326
+ # # プロセスを終了
327
+ # image_index(1)
328
+ # show_confirmation(FALSE)
329
+ # update_log("Interactive caption editing ended.")
330
+ # })
331
+ #
332
+ # output$showCaptionConfirmation <- reactive({
333
+ # show_confirmation()
334
+ # })
335
+ #
336
+ # outputOptions(output, "showCaptionConfirmation", suspendWhenHidden=FALSE)
337
+
338
+ # output$confirm_caption <- renderText({
339
+ # input$edit_caption
340
+ # })
341
+
342
+ # Remode/Add Single/Add all/move captionの処理
343
+ showOrderInput <- reactiveVal(FALSE)
344
+ showTextInput <- reactiveVal(FALSE)
345
+
346
+ observeEvent(input$remove_single, {
347
+ if (!is.null(operation_mode())) {
348
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
349
+ return()
350
+ }
351
+ target_caption <- input$edit_caption
352
+ if (target_caption %in% captions_data()$caption[captions_data()$image_path == input$selected_image]) {
353
+ updated_data <- remove_caption_and_adjust_order(captions_data(), input$selected_image, target_caption)
354
+ captions_data(updated_data)
355
+ update_log("Caption removed from this image.")
356
+ } else {
357
+ showNotification("Error: Caption not found in the selected image.", type = "error")
358
+ }
359
+ })
360
+
361
+ observeEvent(input$add_single, {
362
+ if (!is.null(operation_mode())) {
363
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
364
+ return()
365
+ }
366
+ operation_mode("add_single")
367
+ showOrderInput(TRUE)
368
+ update_log("ADD SINGLE MODE.")
369
+ })
370
+
371
+ observeEvent(input$add_to_all, {
372
+ if (!is.null(operation_mode())) {
373
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
374
+ return()
375
+ }
376
+ operation_mode("add_all")
377
+ showOrderInput(TRUE)
378
+ update_log("ADD ALL MODE.")
379
+ })
380
+
381
+ observeEvent(input$move_caption, {
382
+ if (!is.null(operation_mode())) {
383
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
384
+ return()
385
+ }
386
+ target_caption <- input$edit_caption
387
+ if (target_caption %in% captions_data()$caption[captions_data()$image_path == input$selected_image]) {
388
+ operation_mode("move_caption")
389
+ showOrderInput(TRUE)
390
+ update_log("MOVE CAPTION SINGLE MODE.")
391
+ } else {
392
+ showNotification("Error: Caption not found in the selected image.", type = "error")
393
+ }
394
+ })
395
+
396
+ observeEvent(input$move_caption_all, {
397
+ if (!is.null(operation_mode())) {
398
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
399
+ return()
400
+ }
401
+ operation_mode("move_caption_all")
402
+ showOrderInput(TRUE)
403
+ update_log("MOVE CAPTION ALL MODE.")
404
+ })
405
+
406
+ observeEvent(input$remove_related_single, {
407
+ if (!is.null(operation_mode())) {
408
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
409
+ return()
410
+ }
411
+ if (!is.null(captions_data())) {
412
+ selected_image_path <- input$selected_image
413
+ target_caption <- input$edit_caption
414
+
415
+ # target_captionが選択された画像に紐づいているか確認
416
+ if (any(captions_data()$image_path == selected_image_path & captions_data()$caption == target_caption)) {
417
+ operation_mode("remove_related_single")
418
+ showTextInput(TRUE)
419
+ update_log("RELATIVE REMOVE SINGLE MODE.")
420
+ } else {
421
+ showNotification("Error: Caption not found in the selected image.", type = "error")
422
+ }
423
+ }
424
+ })
425
+
426
+ observeEvent(input$remove_related_all, {
427
+ if (!is.null(operation_mode())) {
428
+ showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
429
+ return()
430
+ }
431
+ operation_mode("remove_related_all")
432
+ showTextInput(TRUE)
433
+ update_log("RELATIVE REMOVE ALL MODE.")
434
+ })
435
+
436
+ observeEvent(input$confirm_order, {
437
+ switch(operation_mode(),
438
+ "add_single" = {
439
+ # Add to Singleの処理
440
+ target_caption <- input$edit_caption
441
+ target_order <- max(1, floor(input$target_order))
442
+ updated_data <- add_caption_at_order(captions_data(), input$selected_image, target_caption, target_order)
443
+ captions_data(updated_data)
444
+ update_log("Caption added to target order.")
445
+ },
446
+ "add_all" = {
447
+ target_caption <- input$edit_caption
448
+ target_order <- target_order <- max(1, floor(input$target_order))
449
+ updated_data <- captions_data()
450
+ unique_images <- unique(updated_data$image_path)
451
+ for (image in unique_images) {
452
+ updated_data <- add_caption_at_order(updated_data, image, target_caption, target_order)
453
+ }
454
+ captions_data(updated_data)
455
+ update_log("Caption added to all images.")
456
+ },
457
+ "move_caption" = {
458
+ # Move Captionの処理
459
+ target_caption <- input$edit_caption
460
+ target_order <- target_order <- max(1, floor(input$target_order))
461
+ updated_data <- move_caption_order(captions_data(), input$selected_image, target_caption, target_order)
462
+ captions_data(updated_data)
463
+ update_log("Caption moved to target order.")
464
+ },
465
+ "move_caption_all" = {
466
+ # Move Caption Allの処理
467
+ target_caption <- input$edit_caption
468
+ target_order <- target_order <- max(1, floor(input$target_order))
469
+ updated_data <- captions_data()
470
+ unique_images <- unique(updated_data$image_path[updated_data$caption == target_caption])
471
+ for (image in unique_images) {
472
+ updated_data <- move_caption_order(updated_data, image, target_caption, target_order)
473
+ }
474
+ captions_data(updated_data)
475
+ update_log("Caption moved to target order from all images.")
476
+ }
477
+ )
478
+
479
+ # キャプションの頻度を更新
480
+ updated_caption_frequency <- get_caption_frequency(updated_data)
481
+ caption_frequency(updated_caption_frequency)
482
+ operation_mode(NULL)
483
+ showOrderInput(FALSE)
484
+ })
485
+
486
+
487
+ observeEvent(input$confirm_text, {
488
+ switch(operation_mode(),
489
+ "remove_related_single" = {
490
+ # Remove Related captions of Singleの処理
491
+ related_captions <- unlist(strsplit(input$related_captions_input, ","))
492
+ related_captions <- trimws(related_captions) # スペースを削除
493
+ representative_caption <- input$edit_caption
494
+
495
+ updated_data <- remove_related_captions_except_representative(captions_data(), related_captions, representative_caption, input$selected_image)
496
+ captions_data(updated_data)
497
+ update_log("Relative captions were removed from this image.")
498
+ },
499
+ "remove_related_all" = {
500
+ # Remove Related captions from All Imagesの処理
501
+ related_captions <- unlist(strsplit(input$related_captions_input, ","))
502
+ related_captions <- trimws(related_captions) # スペースを削除
503
+ representative_caption <- input$edit_caption
504
+
505
+ updated_data <- captions_data()
506
+ # representative_captionを持つすべての画像を検索
507
+ images_with_rep_caption <- unique(updated_data$image_path[updated_data$caption == representative_caption])
508
+
509
+ for (image_path in images_with_rep_caption) {
510
+ updated_data <- remove_related_captions_except_representative(updated_data, related_captions, representative_caption, image_path)
511
+ }
512
+
513
+ captions_data(updated_data)
514
+ update_log("Relative captions were removed from all images.")
515
+ }
516
+ )
517
+
518
+ # キャプションの頻度を更新
519
+ updated_caption_frequency <- get_caption_frequency(updated_data)
520
+ caption_frequency(updated_caption_frequency)
521
+ operation_mode(NULL)
522
+ showTextInput(FALSE)
523
+ })
524
+
525
+
526
+ observeEvent(input$cancel_order, {
527
+ operation_mode(NULL)
528
+ showOrderInput(FALSE)
529
+ update_log("Operation was canceled.")
530
+ })
531
+
532
+ observeEvent(input$cancel_text, {
533
+ operation_mode(NULL)
534
+ showTextInput(FALSE)
535
+ update_log("Operation was canceled.")
536
+ })
537
+
538
+ output$showOrderInput <- reactive({
539
+ showOrderInput()
540
+ })
541
+
542
+ outputOptions(output, "showOrderInput", suspendWhenHidden=FALSE)
543
+
544
+ output$showTextInput <- reactive({
545
+ showTextInput()
546
+ })
547
+
548
+ outputOptions(output, "showTextInput", suspendWhenHidden=FALSE)
549
+
550
+ # Remove Related
551
+
552
+ # レンダリング
553
+ output$image_display <- renderImage({
554
+ list(src = file.path(input$selected_image), alt = "Selected Image", width = "80%")
555
+ }, deleteFile = FALSE)
556
+
557
+ output$image_captions <- renderUI({
558
+ if (!is.null(captions_data())) {
559
+ selected_image_path <- input$selected_image
560
+ captions <- filter(captions_data(), image_path == selected_image_path) %>%
561
+ arrange(caption_order) %>%
562
+ pull(caption)
563
+ # キャプションをリンク付きのHTMLに変換
564
+ linked_captions <- lapply(captions, function(caption) {
565
+ sprintf("<a href='javascript:void(0);' onclick='copyToClipboard(\"%s\");'>%s</a>", caption, caption)
566
+ })
567
+
568
+ HTML(paste(linked_captions, collapse = ", "))
569
+ } else {
570
+ return(NULL)
571
+ }
572
+ })
573
+
574
+ output$log_output <- renderText({
575
+ log_text()
576
+ })
577
+
578
+ output$selected_image_captions <- renderTable({
579
+ if (!is.null(captions_data())) {
580
+ selected_image_path <- input$selected_image
581
+ selected_captions <- filter(captions_data(), image_path == selected_image_path) %>%
582
+ select(caption, caption_order) %>%
583
+ arrange(caption_order)
584
+
585
+ # caption列の各エントリにリンクを追加
586
+ selected_captions$caption <- sprintf("<a href='javascript:void(0);' onclick='copyToClipboard(\"%s\");'>%s</a>", selected_captions$caption, selected_captions$caption)
587
+
588
+ return(selected_captions)
589
+ }
590
+ }, sanitize.text.function = function(x) x) # HTMLをエスケープしないようにする
591
+
592
+ output$caption_frequency_table_with_links <- renderTable({
593
+ if (!is.null(caption_frequency())) {
594
+ freq_data <- caption_frequency()
595
+ freq_data$caption <- sprintf("<a href='javascript:void(0);' onclick='copyToClipboard(\"%s\");'>%s</a>", freq_data$caption, freq_data$caption)
596
+ freq_data
597
+ }
598
+ }, sanitize.text.function = function(x) x, rownames = TRUE)
599
+
600
+ }
601
+
602
+ # アプリを実行
603
+ shinyApp(ui = ui, server = server)
604
+
script.R ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ library(tidyverse)
2
+
3
+ # ----- #
4
+ read_captions_from_directory <- function(directory_path) {
5
+ # ディレクトリ内の.txtファイルのリストを取得
6
+ txt_files <- list.files(directory_path, pattern = "\\.txt$", full.names = TRUE)
7
+
8
+ # 各.txtファイルからキャプションを読み込み
9
+ data <- lapply(txt_files, function(file) {
10
+ captions <- readLines(file, warn = FALSE)
11
+ captions_list <- strsplit(captions, ",")[[1]]
12
+ captions_list <- trimws(captions_list) # 余分な空白を取り除く
13
+ tibble(
14
+ image_path = gsub(".txt$", ".png", file),
15
+ caption_order = 1:length(captions_list),
16
+ caption = captions_list
17
+ )
18
+ })
19
+
20
+ # データフレームに変換
21
+ bind_rows(data)
22
+ }
23
+
24
+ get_caption_frequency <- function(data) {
25
+ data %>%
26
+ group_by(caption) %>%
27
+ summarise(frequency = n()) %>%
28
+ arrange(-frequency)
29
+ }
30
+
31
+ search_by_caption <- function(data, target_caption) {
32
+ data %>%
33
+ filter(caption == target_caption) %>%
34
+ group_by(image_path) %>%
35
+ distinct()
36
+ }
37
+
38
+ remove_caption_and_adjust_order <- function(data, target_image_path, target_caption) {
39
+ # キャプションが存在するか確認
40
+ if (!any(data$image_path == target_image_path & data$caption == target_caption)) {
41
+ cat(sprintf("The caption '%s' does not exist for image '%s'.\n", target_caption, target_image_path))
42
+ return(data)
43
+ }
44
+
45
+ # 削除するキャプションのcaption_orderを取得
46
+ removed_order <- data$caption_order[data$image_path == target_image_path & data$caption == target_caption]
47
+ # キャプションを削除
48
+ data <- data %>% filter(!(image_path == target_image_path & caption == target_caption))
49
+ # caption_orderを調整
50
+ data$caption_order[data$image_path == target_image_path & data$caption_order > removed_order] <- data$caption_order[data$image_path == target_image_path & data$caption_order > removed_order] - 1
51
+
52
+ return(data)
53
+ }
54
+
55
+ remove_low_frequency_captions <- function(data, threshold) {
56
+ # キャプションの頻度を取得
57
+ caption_freq <- get_caption_frequency(data)
58
+
59
+ # 指定された頻度以下のキャプションのリストを作成
60
+ low_freq_captions <- caption_freq %>%
61
+ filter(frequency <= threshold) %>%
62
+ pull(caption)
63
+
64
+ # 低頻度のキャプションを削除し、caption_orderを調整
65
+ for (caption in low_freq_captions) {
66
+ unique_images <- unique(data$image_path[data$caption == caption])
67
+ for (image in unique_images) {
68
+ data <- remove_caption_and_adjust_order(data, image, caption)
69
+ }
70
+ }
71
+
72
+ return(data)
73
+ }
74
+
75
+ edit_captions_interactively <- function(data, target_caption) {
76
+ # キャプションで画像を検索
77
+ image_paths <- search_by_caption(data, target_caption)$image_path
78
+
79
+ for (path in image_paths) {
80
+ # OSに応じて画像を開く
81
+ if (Sys.info()["sysname"] == "Windows") {
82
+ cmd <- sprintf('start "" "%s"', path)
83
+ shell(cmd, intern = TRUE)
84
+ } else if (Sys.info()["sysname"] == "Darwin") { # macOS
85
+ cmd <- sprintf('open "%s"', path)
86
+ system(cmd)
87
+ } else { # Linux
88
+ cmd <- sprintf('xdg-open "%s"', path)
89
+ system(cmd)
90
+ }
91
+
92
+ # ユーザーにキャプションの削除を選択させる
93
+ cat(sprintf("Do you want to remove the caption '%s' from image '%s'? (yes/no/end): ", target_caption, path))
94
+ response <- readline()
95
+
96
+ if (tolower(response) == "end") {
97
+ break
98
+ } else if (tolower(response) == "yes") {
99
+ data <- remove_caption_and_adjust_order(data, path, target_caption)
100
+ }
101
+ }
102
+
103
+ return(data)
104
+ }
105
+
106
+ add_caption_at_order <- function(data, target_image_path, target_caption, target_order = NULL) {
107
+ # 指定された画像の最大のcaption_orderを取得
108
+ max_order <- max(data$caption_order[data$image_path == target_image_path], na.rm = TRUE)
109
+
110
+ # キャプションの重複チェック
111
+ if (target_caption %in% data$caption[data$image_path == target_image_path]) {
112
+ return(data) # 重複がある場合、データをそのまま返す
113
+ }
114
+
115
+ # target_orderが指定されていない場合、キャプションを表示してユーザーに選ばせる
116
+ if (is.null(target_order)) {
117
+ print_image_captions_as_csv(data, target_image_path)
118
+ cat("Enter the position (order) to insert the new caption (1 to", max_order + 1, "): ")
119
+ target_order <- as.numeric(readline())
120
+
121
+ # 不適切な値が入力された場合、最大のorder + 1で追加
122
+ if (target_order <= 0 || target_order > max_order + 1) {
123
+ target_order <- max_order + 1
124
+ }
125
+ }
126
+
127
+ # 指定されたorder以降のcaption_orderを増加
128
+ data <- data %>%
129
+ mutate(caption_order = ifelse(image_path == target_image_path & caption_order >= target_order, caption_order + 1, caption_order))
130
+
131
+ # 新しいキャプションを追加
132
+ new_caption <- tibble(
133
+ image_path = target_image_path,
134
+ caption_order = target_order,
135
+ caption = target_caption
136
+ )
137
+ data <- bind_rows(data, new_caption)
138
+
139
+ return(data)
140
+ }
141
+
142
+ move_caption_order <- function(data, target_image_path, target_caption, new_order) {
143
+
144
+ # キャプションが存在するか確認
145
+ if (!any(data$image_path == target_image_path & data$caption == target_caption)) {
146
+ cat(sprintf("The caption '%s' does not exist for image '%s'.\n", target_caption, target_image_path))
147
+ return(data)
148
+ }
149
+
150
+ # キャプションを削除
151
+ data_after_removal <- remove_caption_and_adjust_order(data, target_image_path, target_caption)
152
+
153
+ # 新しい位置にキャプションを追加
154
+ data_after_addition <- add_caption_at_order(data_after_removal, target_image_path, target_caption, new_order)
155
+ return(data_after_addition)
156
+ }
157
+
158
+ # キャプションが存在するか確認 (使わないかも)
159
+ is_caption_present <- function(data, target_image_path, target_caption) {
160
+ return(any(data$image_path == target_image_path & data$caption == target_caption))
161
+ }
162
+
163
+ # すべてのキャプションを表示
164
+ print_all_unique_captions_as_csv <- function(data) {
165
+ # 重複なく全てのキャプションを取得
166
+ unique_captions <- unique(data$caption)
167
+ # CSV形式で表示
168
+ cat(paste(unique_captions, collapse = ", "), "\n")
169
+ }
170
+
171
+ print_image_captions_as_csv <- function(data, target_image_path) {
172
+ captions <- filter(data, image_path == target_image_path) %>%
173
+ arrange(caption_order) %>%
174
+ pull(caption)
175
+
176
+ cat(paste(captions, collapse = ", "), "\n")
177
+ }
178
+
179
+ # 代表するキャプションに集約
180
+ remove_related_captions_except_representative <- function(data, related_captions, representative_caption, target_image_path) {
181
+
182
+ # representative_captionがtarget_image_pathに紐づいているか確認
183
+ if (!any(data$image_path == target_image_path & data$caption == representative_caption)) {
184
+ cat(sprintf("The representative caption '%s' is not associated with image '%s'.\n", representative_caption, target_image_path))
185
+ return(data)
186
+ }
187
+
188
+ # target_image_pathに関連するキャプションを削除
189
+ for (caption in related_captions) {
190
+ if (caption != representative_caption) {
191
+ data <- remove_caption_and_adjust_order(data, target_image_path, caption)
192
+ }
193
+ }
194
+
195
+ return(data)
196
+ }