7. Batch Processing

7. Batch Processing: 이미지 일괄 처리

Reference

A Fiji Scripting Tutorial #3. Inspecting properties and pixels of an image

  • 대량의 이미지를 한번에 처리해야 하는 경우, 이미지를 하나 하나 불러오는 것보다 일괄처리가 효과적입니다.

  • 이미지가 모여 있는 폴더를 지정할 수도 있고,
    분석 대상 이미지들을 화면에 띄운 후 떠 있는 이미지들을 일괄적으로 처리할 수도 있습니다.

7.1. 이미지 파일 일괄 처리

  • 그림파일 다섯 개가 있는 예제파일을 받아 한 폴더에 풉니다.

  • 아래 코드를 실행하여 다섯 이미지의 데이터를 일괄적으로 구해봅시다.

    • ImageJ > Tutorial > 6. Image Data 분석 글에 있는 6.2.2.1. 코드를 이용해 보겠습니다.

    • 면적, 평균, 중간값 등을 일괄적으로 추출하기 위해 python의 def 문을 사용하여 함수를 만들어줍니다.

    • 그리고 os.listdir() 을 이용해 지정된 디렉토리 내의 함수를 훑으면서 이미지를 분석하고 그 결과를 출력합니다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      from ij import IJ
      import os

      # 1. Load Image 위치:
      folder = r"C:\Arbeitplatz\19_hexoblog_backup\source\_posts\ImageJ-tutorial-7_Multi\7_batch_1"

      # 2. Image 통계 정보 일괄 분석
      # 2-1. 함수 정의
      def getStatistics(imp):
      stats = imp.getStatistics()
      # 면적, 평균, 중간값, 최소값, 최대값을 가져옴
      return stats.area, stats.mean, stats.median, stats.min, stats.max

      # 확장자가 ".tif"인 파일들로부터 데이터 읽어오기.
      for filename in os.listdir(folder): # 폴더 안에 있는 파일에 하나씩 접근
      if filename.endswith(".tif"): # 파일 이름이 ".tif"로 끝난다면,
      print "\nProcessing", filename
      fullpath = os.path.join(folder, filename) # 폴더명과 파일명을 결합
      print "fullpath", fullpath
      imp = IJ.openImage(fullpath) # 파일을 불러온다.
      if imp is None: # 파일이 제대로 불러지지 않으면,
      print "Could not open image from file:", filename # 에러메시지 출력
      continue # 다른 파일을 읽어본다.
      # 파일이 불러지면, 앞서 정의한 getStatistics() 함수를 실행해서 데이터를 분석한다.
      area, mean, median, vmin, vmax = getStatistics(imp)
      print "Image statistics for", imp.title
      print "Area:", area
      print "Mean:", mean
      print "Median:", median
      print "Min and max:", vmin, "-", vmax
      else: # 파일 이름이 ".tif"로 끝나지 않으면
      print "Ignoring", filename # 파일 이름만 출력하고 넘어간다.
    • 실행 결과가 전체를 보이기엔 너무 길어서 아래 창에 마지막 파일에 대한 실행 결과만을 도시하였습니다.

    • 파일명(7_batch_1_5.tif), 면적(Area: 2160.97), 평균(Mean: 11800.02), 중간값(Median: 0.0) 등이 출력되어 있습니다.

    • 최대값(max: 65535.0)이 이제까지 다룬 이미지(255)와 달리 65536입니다. 16-bit 이기 때문입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    ....
    Processing 7_batch_1_5.tif
    fullpath C:\Arbeitplatz\19_hexoblog_backup\source\_posts\ImageJ-tutorial-7-Batch\7_batch_1\7_batch_1_5.tif
    Image statistics for 7_batch_1_5.tif
    Area: 2160.97959184
    Mean: 11800.0291717
    Median: 0.0
    Min and max: 0.0 - 65535.0


7.2. 이미지 목록(list) 만들기

  • 7.1.에서는 특정 위치의 파일들을 하나씩 건드려보는 방식을 취했습니다.

  • 그러나 동일한 파일 집합을 대상으로 여러 오퍼레이션을 하는 경우에, 미리 파일을 묶어놓으면 좋습니다.

  • 화면에 띄워놓은 이미지들은 WindowManager모듈을 이용하여 리스트 형식으로 모을 수 있습니다.

    1
    2
    3
    4
    5
    6
    7
    from ij import WindowManager as WM

    images = [] # 빈 리스트 생성
    for id in WM.getIDList():
    images.append(WM.getImage(id))

    print images
    • 처럼 다섯 그림을 모두 띄워놓고 실행하면, 다음과 같은 메시지가 나옵니다.

    1
    [img["7_batch_1_1.tif" (-67), 8-bit, 1536x1103x1x1x1], img["7_batch_1_2.tif" (-68), 8-bit, 1536x1103x1x1x1], img["7_batch_1_3.tif" (-72), 8-bit, 1536x1103x1x1x1], img["7_batch_1_4.tif" (-73), 16-bit, 1536x1103x1x1x1], img["7_batch_1_5.tif" (-74), 16-bit, 1536x1103x1x1x1]]
    • 각 이미지에 대해 -67 ~ -74 까지의 id가 매겨져 있습니다.
    • 이미지의 이름이나 크기 등에 무관하게 ImageJ가 실행된 후 열어본 이미지들에 붙는 일련번호입니다.
    • 그 외의 정보는 ImageJ > Tutorial > 2. Image File 구조 에 기술되어 있습니다.

  • 이미지 리스트 작성을 더 짧게 할 수도 있습니다.
    ImageJ > Tutorial > 4. Python Basic 에서 설명한 list comprehensionmap을 사용하면 됩니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from ij import WindowManager as WM

    # 1. list comprehension
    images_lc = [WM.getImage(id) for id in WM.getIDList()]

    # 2. map
    images_map = map(WM.getImage, WM.getIDList())

    print "images (list comprehension):\n", images_lc
    print "\nimages (map):\n", images_map
    • 다음과 같이 두 가지 방식에서 동일한 결과가 얻어집니다.
      1
      2
      3
      4
      5
      images (list comprehension):
      [img["7_batch_1_1.tif" (-67), 8-bit, 1536x1103x1x1x1], img["7_batch_1_2.tif" (-68), 8-bit, 1536x1103x1x1x1], img["7_batch_1_3.tif" (-72), 8-bit, 1536x1103x1x1x1], img["7_batch_1_4.tif" (-73), 16-bit, 1536x1103x1x1x1], img["7_batch_1_5.tif" (-74), 16-bit, 1536x1103x1x1x1]]

      images (map):
      [img["7_batch_1_1.tif" (-67), 8-bit, 1536x1103x1x1x1], img["7_batch_1_2.tif" (-68), 8-bit, 1536x1103x1x1x1], img["7_batch_1_3.tif" (-72), 8-bit, 1536x1103x1x1x1], img["7_batch_1_4.tif" (-73), 16-bit, 1536x1103x1x1x1], img["7_batch_1_5.tif" (-74), 16-bit, 1536x1103x1x1x1]]

7.3. 이미지 list 활용하기

7.3.1. 이름으로 파일 찾기

  • 읽어들인 이미지 중에서 내가 찾는 이름(“7_batch_1_4.tif”)의 파일이 있는지 확인해보겠습니다.

  • ImageJ > Tutorial > 4. Python Basic 에서 설명한 filter를 사용하면 효과적입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from ij import WindowManager as WM

    # 1. map을 이용해 image list 작성
    imps = map(WM.getImage, WM.getIDList())

    # 2. 함수 이름 비교 함수
    def match(imp):
    # 이미지(imp)의 title에 찾는 이름이 있으면 true
    return imp.title.find("7_batch_1_4.tif") > -1

    # 3. filter를 이용해서 파일 존재 확인
    matching = filter(match, imps)

    # 4. 결과 출력
    print matching
    • 실행 결과, 성공적으로 파일을 찾았습니다.
    1
    [img["7_batch_1_4.tif" (-73), 16-bit, 1536x1103x1x1x1]]
    • 그리고 당연히, filter 대신 for loop, list comprehension 등을 사용할 수 있습니다.
    1
    2
    3
    4
    5
    6
    7
    8
    # 1: 'for' loop (별도의 리스트를 생성해야 합니다)
    matching = []
    for imp in imps:
    if match(imp):
    matching.append(imp)

    # Method 2: list comprehension
    matching = [imp for imp in imps if match(imp)]

    #### 7.3.2. 가장 밝은 이미지 찾기
  • 이미지의 평균 밝기를 비교해서 가장 큰 것을 찾아보겠습니다.

    • 이미지를 하나씩 열면서 방금 연 이미지의 밝기가 기존 기록보다 더 크면 갱신하는 작업입니다.
    • for loopreduce를 비교해 보겠습니다.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      from ij import IJ
      from ij import WindowManager as WM
      from ij.plugin import Duplicator

      # 1. map을 이용해 image list 작성
      imps = map(WM.getImage, WM.getIDList())

      # 2. 평균 명도를 구하는 함수
      def bright(imp):
      stats = imp.getStatistics()
      return stats.mean

      # 3. 가장 밝은 이미지 찾기
      # 3-1. for loop
      brightest = None
      brightness = 0
      for imp in imps:
      a = bright(imp)
      if brightest is None:
      brightest = imp
      brightness = a
      else:
      if a > brightness:
      brightest = imp
      brightness = a

      print "\n# for loop"
      print "Brightest image=", brightest.title
      print "Brightness=", brightness

      brightest_for = Duplicator().run(brightest)
      brightest_for.title = "by_for"
      brightest_for.show()

      # 3-2. reduce
      def brightestImage(imp1, imp2):
      return imp1 if bright(imp1) > bright(imp2) else imp2

      largest = reduce(brightestImage, imps)

      print "\n# reduce"
      print "Brightest image=", brightest.title
      print "Brightest area=", brightness

      brightest_reduce = Duplicator().run(brightest)
      brightest_reduce.title = "by_reduce"
      brightest_reduce.show("by_reduce")
    • for loop은 가장 큰 이미지와 그 넓이를 사전에 정의하고, image 리스트인 imps에 저장된 이미지를 하나씩 꺼내보면서 새로 꺼낸 이미지의 넓이가 기존 기록을 갱신했는지 비교합니다.
    • reduce는 이미지의 넓이를 비교하는 함수(brightestImage)와 이미지 리스트(imps)를 인자로 받아들여, imps에 brightestImage를 적용합니다.



도움이 되셨나요? 카페인을 투입하시면 다음 포스팅으로 변환됩니다

Share