1 사진속 사물인식

먼저 사진속 이미지를 컴퓨터로 인식시키기 위해서 인터넷에서 적당한 .jpg, .png 파일을 가져와서 로컬 컴퓨터 적당한 디렉토리에 저장시킨다. 그리고 나서 EBImage 팩키지를 사용해서 이미지를 R로 작업할 수 있는지 확인하기 위해서 또한, 시각적으로 파악하고자 불러온다.

그리고 나서 keras 팩키지를 사용해서 이미 이미지넷(imagenet) 학습데이터를 사용해서 resnet50 모형으로 이미지를 인식시킨다.

작업흐름

2 이미지 살펴보기

다양한 시각화 팩키지가 존재한다. 시각화 팩키지로 EBImage를 사용해서 R로 기계가 제대로 이미지를 가져오는지만 확인한다.

3 이미지 인식

사진속 사물을 keras API를 사용해서 인식해본다. 즉 이미지를 텐서플로우에 던져 이미 학습된 resnet50 사전학습 모형을 사용해서 이미지 인식을 시도한다.

imagenet_decode_predictions() 함수를 사용해서 이미지 작업 결과를 반환받아 이미지에 flagpole이 들어 있을 가능성이 가장 높다는 결과를 받아낸다.

4 사물 인식 제품 1

R 언어로 기계가 이미지를 잘 인식하고 keras를 사용해서 이미지속 사물도 잘 분류해 내기 때문에 이를 제품화하여 다른 사용자가 사용할 수 있도록 한다. 이를 위해서 xwMOOC 데이터 제품, “이미지 분류 - 케라스(딥러닝)” 코드를 참조하여 shiny 웹을 개발한다.

먼저 ui.R, server.R, global.R로 앱을 나눠 이미지를 받아서 이미지속 사물을 인식한 결과를 출력하도록 ui.R을 준비한다. 그리고 이벤트를 받아 처리하는 로직을 server.R에 넣고, global.R에 이미지를 받아 keras를 활용하여 이미지 인식, 즉 분류하는 로직을 함수로 담아낸다.

# global.R -------------------------------------------------------------------------

library(tidyverse)
library(shiny)
library(keras)
library(DT)

classify_image <- function(src_img){
  
  img <- image_load(src_img, target_size = c(224,224))
  x <- image_to_array(img)
  
  x <- array_reshape(x, c(1, dim(x)))
  x <- imagenet_preprocess_input(x)
  
  model <- application_resnet50(weights = 'imagenet')
  
  preds <- model %>% predict(x)
  
  # Table Output
  main_tbl <- imagenet_decode_predictions(preds, top = 5)[[1]]
  main_tbl$explore_class_on_imagenet <- sprintf('Explore %s on ImageNet', main_tbl$class_name, main_tbl$class_description)
  
  return(main_tbl)
}

# server.R -------------------------------------------------------------------------
server <- function(input, output, session) {
  
  output$uploaded_image <- renderImage({
    
    src <- input$img_file
    src <- src$datapath
    
    if (is.null(src)) {
      list(src = "www/Flag_of_South_Korea.jpg",
           height = "300",
           alt = "Classify Image")
    } else {
      return(list(
        src = src,
        height = "300",
        alt = "Classifed Image"
      ))
    }
    
  }, deleteFile = FALSE)
  
  output$keras_table <- DT::renderDataTable({
    
    uploaded_img_file <- input$img_file
    uploaded_img_path <- uploaded_img_file$datapath
    
    if (is.null(uploaded_img_path)) {
      if(input$flag_check) {
        withProgress(message = '사진 판별중...', value = 1,
                     classify_image("www/Flag_of_South_Korea.jpg")
        )
      } else {
        NULL   
      }
    } else {
      withProgress(message = 'Predicting...', value = 1,
                   img2tbl_df <- classify_image(uploaded_img_path)
      )
      DT::datatable(img2tbl_df)
    }
  })
}

# ui.R -------------------------------------------------------------------------
shinyUI(fluidPage(
  
  # Application title
  titlePanel("데이터 사이언스 언어 R - 기계 이미지 인식"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      # Image Input: Select a file ----
      fileInput("img_file", "Choose Image file: ", accept = c('image/png', 'image/jpeg')),
      
      # Horizontal line ----
      tags$hr(),
      
      # Check Keon-Woong Moon image ----
      checkboxInput("flag_check", "기본 예제 사진(태극기)", FALSE)
    ),
    
    # Show Image & Keras Output
    mainPanel(
      imageOutput("uploaded_image", height = 300),
      DT::dataTableOutput("keras_table")
    )
  )
))

결과