[IDL] 아이디엘 이미지 처리 (Image Processing) 교육 연수

 정보

  • 업무명     : 아이디엘 이미지 처리 (Image Processing) 교육 연수

  • 작성자     : 이상호

  • 작성일     : 2020-04-03

  • 설   명      :

  • 수정이력 :

 

 내용

[개요]

  • 안녕하세요? 기상 연구 및 웹 개발을 담당하고 있는 해솔입니다.

  • 오늘은 에스이랩 이미지 처리 (Image Processing) 교육 연수 내용을 다루고자 합니다.

  • 이 교육은 2일에 걸쳐 진행하였고 각 시간마다 이론 및 실습을 병행하여 진행했습니다.

  • 특히 배운 지식을 활용하여 학술 논문 또는 보고서 작성 시 많은 도움이 되었습니다.

  • 그에 따라 "교육 일정, 실습 자료, 관련 자료"순으로 소개해 드리겠습니다.

 

vol_anim.gif

 

[특징]

  • 이미지 처리 (Image Processing) 교육에 대한 이해를 돕기위해 작성

 

[기능]

  • 교육 일정

 

[사용 OS]

  • Window 10

 

[사용 언어]

  • IDL v8.5

 

 세부 내용

[교육 일정]

  • 1일

    • 10:00-10:50 이미지 소개

    • 11:00-11:50 이미지 파일 다루기

    • 13:00-13:50 이미지의 표출

    • 14:00-14:50 기본적인 이미지 처리법 1

    • 15:00-15:50 기본적인 이미지 처리법 2

    • 16:00-17:00 컬러를 다루는 법

 

  • 2일

    • 10:00-10:50 이미지의 저장

    • 11:00-11:50 실전 이미지 처리 기법 1

    • 13:00-13:50 실전 이미지 처리 기법 2

    • 14:00-14:50 관심영역(ROI)의 활용

    • 15:00-15:50 형태의 추출 및 분석

    • 16:00-17:00 기타 이슈들

 

 실습 자료

  • 소스 코드에 대한 설명은 주석을 참조하시기 바랍니다.

 

pro test_01

    file = 'data/AHI_b03.png'

    help, file

    ;  read_png, file, img
    read_png, file, png_img
    ;help, png_img
    ;print, size(png_img, /dim)

    result = size(png_img, /dim)
    ;help, result
    ;print, result[0], result[1]

    window, 0, xsize=result[0]/2, ysize=result[1]/2 ; window, xsize=1024, ysize=768
    tv, png_img

    window, 1, xsize=result[0]/2, ysize=result[1]/3
    tvscl, png_img

    ;********************** 재활용 *************************8
    ;window, 1, xsize=result[0], ysize=result[1]
    ;tv, img_png > 90 < 200

    ;window, 2, xsize=result[0], ysize=result[1]
    ;tvscl, img_png > 90 < 200

end

 

pro test_02

    img1 = hanning(300, 300)*60 
    img2 = hanning(300, 300)*120
    img3 = hanning(300, 300)*200
    ; 2차원을 가상으로 만듬. ; hanning은 신호처리 함수 중의 하나 ; 01의 데이터로 만들어짐. 
    ; 
    ; print, min(img), max(img) 

    device, decomposed=0  
    ; 8비트 기반으로 색깔을 해석해라.
    ; IDL을 처음 띄운상태는 컴퓨터 체계 그래도 쓰임. 24인 비트인 RGB로 해석하므로 내가 255인 값을 색깔로 해석할려면 / 단일 값에 해당하는
    ; 값으로 해석함. 

    ; window
    ; erase, 255 이므로 R G B을 255 0 0 으로 컴퓨터가 알아서 해석함. / 컴퓨터가 자체가 8비트로 안되어 있으므로  일단, 빨강색으로 나옴.
    ; device, decomposed=0 으로 하면 8비트로 해석하므로 
    ; erase, 255로 하면 흰색이 나옴. 단일값이므로

    window, xsize = 300*3, ysize = 300

    loadct, 13 
    ; ct는 컬러테이블로써 5번의 약속으로 맵핑을 해라. 0~74까지의 값으로 나옴. 컬러테이블이 어떤 색인지 짐작할 수 없음.
    ;  미리 확인할려면 콘솔창에 xloadct로 치면 창이 나옴.  13으로 하면 레인보우로 나옴. 75개로 선택은 다양해짐. 
    ; xloadct
    ; done 버튼을 누르면서 다음에 나올 번호를 이용해서 사용할 수 있음.
    ; 
    ; xpalette
    ; 특정 색깔에 대해서 나옴. RGB도 확인할 수 있음. 256의 색상은 고유 RGB색깔을 가지고 있음. 그러므로 컬러테이블을 내가 만들 수도
    ; 있음. 컬러테이블은 조금 있다가 함.

    ;  tvscl, img1, 0 
    ;  tvscl, img2, 1
    ;  tvscl, img3, 2
    ; 순서가 순차적으로 매겨짐. 0~255의 스케일로 보여줌으로써 다 똑같이 보이므로 가시적으로 볼려면 tv로 봐야함

    tv, img1, 0
    tv, img2, 1
    tv, img3, 2

    loadct, 0
    ; 뒤의 프로그램의 프로그램의 잔재를 남게 하지 않게할려고

end

 

pro test_03

    ; 아직도 컬러테이블이 흑백이였으나, 앞의 프로그램의 컬러테이블의 잔재가 남은 경우가 있음. 그래서 test_02.pro에 마지막에
    ; loadct, 0으로 컬러테이블 끝남

    ; 1024,764 데이터
    file = 'data/bw0406.jpg'
    read_jpeg, file, img
    result = size(img, /dim)
    window, 0,  xsize=result[0], ysize=result[1] 
    tv, img

    print, img[512,384]
    ; 화소값을 뽑아낼려면 x방향으로 513번쨰, y방향으로 385번쨰 화소의 값에 대해서 뽑아냄

    print, img[50,50]

    ; print, img[*, 384]
    ; 가로방향으로 수평 스캔으로하면 하나의 스트림을 뽑아낼려고 함. 특정 차원에 대해서 모두 뽑아낼려면 * 방향, 보기 너무 어려우므로

    window, 1
    for i = 0, 400 do begin
    ; 반복문할떄 0으로 안해도 되지만, 배열 자체가 0으로 하므로 / 반복문 구조 (for ~ endfor)

    line = img[*, i]
    ;   help, line

    plot, line, yrange=[0, 255], YST=1
    ; ystyle(YST)=1 


    wait, 0.1
    ; plot을 점점 바꿔짐. 즉, y축이 자꾸 변하여 비교하기 어려움. 0.1초씩 다른거를 해라


    ; 별도의 창을 만들지 않을 경우에 그래픽창이 계속 누적됨. 그래서 window, 1로서 설정해주어야 함. 제목 창에 window 0~1으로 보여줌.
    ; 그래서 인덱스 별로 따로 구분할 경우도 있음.  
    ; y축을 고정하지 않을경우, y축이 이동되므로 비교하기 어려움.

    ; IDL도 반복문, 조건문이 주어짐. 반복적으로 작업을 할떄 사용함.

    endfor
    ; 주석을 여러개 달떄 ctrl + ; 으로 시작 함.

end

 

pro test_04

    ; 아직도 컬러테이블이 흑백이였으나, 앞의 프로그램의 컬러테이블의 잔재가 남은 경우가 있음. 그래서 test_02.pro에 마지막에
    ; loadct, 0으로 컬러테이블 끝남

    ; 1024,764 데이터

    file = 'data/bw0406.jpg'
    read_jpeg, file, img
    result = size(img, /dim)
    window, 0,  xsize=result[0], ysize=result[1]
    tv, img

    print, img[512,384]
    ; 화소값을 뽑아낼려면 x방향으로 513번쨰, y방향으로 385번쨰 화소의 값에 대해서 뽑아냄

    print, img[50,50]

    img_sub = img[300:499, 100:299]
    ; 일부 영역을 뽑아낼려면 x축 300개, y축 300개에 대한 영역을 뽑아냄.

    help, img_sub

    window, 1, xsize=300, ysize=300
    tv, img_sub

    ;  window, 2, xsize=300*3, ysize=300*3

    ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    mf=3
    window, 2, xsize=200*mf, ysize=200*mf
    ; 뽑아낸 좌표를 확대함. 가로/세로 확대함.

    img_sub_zoom = congrid(img_sub, 200*mf, 200*mf)  
    tv, img_sub_zoom
    ; 확대 명령어 congrid임. 원본데이터는 300,300인데 900,900으로 없는 값을 채워야하는 알고리즘이 있음. 

    window, 3, xsize=200*mf, ysize=200*mf
    img_sub_zoom = congrid(img_sub, 200*mf, 200*mf, /interp)
    tv, img_sub_zoom
    ; window, 2보다 조금 더 부드러움. 꺠끗하게 보임. / interpolation을 새롭게 새로운 값을 내삽하여 부드럽게 보임. 밝기에 대한 부드러움의 차이.
    ; 
    ; rebin은 정수에 대해서만 한계를 가짐. 
    ; congrid는 defalult로 neaest sampling으로 되어있으나, 옵션으로 interp 있음.
    ; 
    ; Nearest은 가까이 있는 실제값을 넣는 방법이므로 마치 크게 깍두기 생긴 것과 같다. 계단적으로 굉장히 거칠게 보임. 화소 차이가 큼.
    ; 픽셀만 커진 내용임, 절대 원본값으로 살리고 싶으면 이 방법이 좋으나

    ; interplolation은 원본값은 살리지 않고 원본에 존재하지 않은 값을 중간에 이어 붙임. 눈으로 보이게 부드러워 보임. interplolation은 Bilinear해도
    ; 충분함. 많은 내삽의 방법도 있음.  

    ;  a = [1., 2., 3.]
    ;  print, congrid(a, 6)
    ;  print, congrid(a, 6, /interp)
    ;  둘의 차이가 있음.

    ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    line = img[*,383]

    ; pl = plot(line, yrange=[0,255], color='blue' ) 
    ; function, 프로시저로 구분함.
    ; NG 방식으로 test_03.pro와 큰 차이가 없다. 계속적으로 설명 해줌. 곧곧에 편리한 기능을 가짐. 이미지에 대해서 한 포인트, 한 라인에 대해서
    ; 추출했다. / 이제는 그 데이터의 일부만 뽑아낼려면
  
end

 

pro test_05

    file = 'data/20140709_000000_Ic_flat_1k.jpg'
    ; 파일 속성에 24비트로 되어 있으므로 RGB로 되어있음.

    read_jpeg, file, img
    ; 원본이 RGB일 경우

    read_jpeg, file, img, /gray
    ; 원본 RGB ==> 그레이 색으로 바꿈으로써 더 편함. 마우스를 띄움으로써 기본적인 정보를 보여줌.  IDL을 생략해도 쓸 수 있음.

    help, img

    window,  0, xsize=1024, ysize=1024
    tv, img
    ;tv, img, /true
    ; 원본이 RGB일 경우, true 컬러 이미지에 대해서 보여줌.

    img_sub = img[500:899, 300:699]
    sz = size(img_sub, /dim)
    window, 1, xsize=sz[0], ysize = sz[1]
    tv, img_sub
    ; 어두운 흑점에 대해서 관심이 있을경우, 히스토그램으로 img_sub의 빈도분포를 보자

    ;pl = plot(histogram(img_sub))
    pl = plot(histogram(img_sub), yrange=[0,100])
    ; 180값보다 낮은 값이 관심이 있음. 화소값 중심으로 히스토그램으로 그려봐서 알 수 있음. 180을 기준으로 낮은 값만 뽑아내면 그것이 
    ; 바로 흑점이라고 생각하여함.

    window, 2, xsize = sz[0], ysize = sz[1]
    img_sub_mask = img_sub ge 130 and img_sub lt 180
    ; 180보다 낮으므로 0,1로 환산되어 나타남. 180보다 작으면 true(1), 180보다 크거나 같으면 false(0). 모든 화소에 대해서 생각해줌.
    print, min(img_sub_mask), max(img_sub_mask)
    ; 0, 1밖에 없으므로 바이너리 이미지로 보임

    ;tv, img_sub_mask
    ; 01로서 색깔이 보임.
    ;tvscl, img_sub_mask
    ; 흑점에 대해서만 보여줌. 01로 극명하게 보여줌으로 / 이것이 마스킹이라고 함. 문법이 허무하게 끝날정도로 간단함. 화소값을 기준으로
    ; 값을 쉽게 뽑아 낼수 있음.
    tvscl, img_sub_mask*img_sub
    ; 히스토그램으로 값에 대해서 극명하게 보여줌.  원본이미지 색깔과 똑같이 만들어주고, 그에 따라 아닌값은 0으로 판단해줌.즉, 그 부분만
    ; 마스킹 되는 기법임. 내가 생각한 흑점에 대해서만 보여줌. 

    ;*********************************************** 클리핑 *******************************************
    ; 150보다 크면 150으로 맞추고, 90보다 낮으면 90으로 맞추니깐 90~150 사이 값에 대해서만 보여줌. 나머지 값인 값들은 사라짐. 
    ; 90보다 작고, 150보다 작은 값은 없어짐.  tvscl은 0~255으로 재 조정됨.

    window, 3, xsize = sz[0], ysize = sz[1]
    tvscl, img_sub > 130 < 180
    ; 130보다 어두운 부분 없어지고, 180보다 높은 부분 없어짐.

end

 

pro test_06

    file = 'data/rduck2.jpg'
    read_jpeg, file, img, /gray
    help, img

    img_new = congrid(img, 3264/4, 2448/4, /interp)
    sz = size(img_new, /dim)

    window, 0, xs=sz[0], ys=sz[1]
    tv, img_new

    window, 1, xs=sz[0], ys=sz[1]

    loadct, 0
    ;loadct, 14
    ; 컬러테이블로 이용해서 나타낼 수도 있음.S

    tvscl, img_new < 50 
    ; 원본에서 어둡게 나타났던것이 밝기 디테일이 강조되어서 나타났다. 나무의 그림자가 더 뚜렷하게 보임. 잔디밭과 약간의 음명이 보임. 
    ; 내가 얻고자 하는 정보를 구함. 근데, 밝기 높은 부분을 포기하고 어두운 부분을 보기 위한 클리핑임.
    ; 어느정도 정량적으로 클리핑값을 구할려면 히스토그램으로 수치적으로 판단함.

    pl = plot(histogram(img_new))

    ; 클리핑과 마스킹을 통해서 내가 볼 수 있는 이미지를 새롭게 볼 수 있음. 내가 원하던 정보를 볼 수 있음. 쓰는 방법이 난이도는 베이직하나? 
    ; 베이직한 결과지만 유용한 역할을 할 수 있음. 
    ; 다음 시간은 컬러테이블을 만드는 역할.

end

 

pro test_07

    img = hanning(600, 600)
    win = window( dimension = [600, 600] )
    ; NG체계의 함수형으로 되어있으므로 ( )로 되어있음. NG = function 기반 그래픽. 400, 400에 대한 창을 띄워라!
    ; 그래픽 창에 꽉 채우지 않으므로 

    im = image( img, rgb_table=14, margin=0, /current )
    ; 이미지 선택 후 이미지 자체의 x, y, 화소값을 볼 수 있음. 간단한 문자삽입하거나 저장 할 수 있음.
    ; 여기에서 컬러테이블 저장할떄, rgb_table=5로서 색깔됨.
    ; 그래픽을 꽉채우게 할려면 margin=0을 하면 꽉차게 그려짐.

    tx = text(0.5, 0.93, 'Test Image', alignment=0.5, /normal, $
      color = 'yellow', font_size=20)
    ; 문자를 삽입.  0~1, 0~1로 계산하는 /normal로 생각함.  alignment=왼쪽/오른쪽 삽입. 이어서 하는줄은 $.
    ; 문자 폰트 떄문에 NG을 주로 이용함. 대외적인 결과물을 이용함. 

    ;win.save, 'test_07.png'
    ; 저장하는데 test_07.png로서 알아서 픽셀값에 저장되므로 명시적으로 x,y을 설정하는게 좋음.

    win.save, 'test_07.png', width=600
    win.save, 'test_07.jpg', width=600
    win.save, 'test.pdf'
    ; 확장자에 따라 알아서 그림을 저장할 수 있음. save Method가 저장할떄 쓰는 종속된 변위임.

end

 

test_07.jpg

 

pro test_08

    img = hanning(600, 600) * 10
    img[400,500] = -9999.

    window, 0, xsize=600, ysize=600
    tvscl, img 
    ; 0~10까지 범위를 알아서 설정함.

    window, 1, xsize=600, ysize=600
    tv, bytscl(img)

    window, 2, xsize=600, ysize=600
    img_new = bytscl(img, max=10, min=0)
    tv, img_new
    ; 최대, 최소에 대한 범위를 정해줄 수 있음. -9999가 있다고 하더라도 상관없음. 
    ; 만약에 특정 픽셀이 이상한 값이 있다고 한다면 -9999.0으로 되어있지만, 10으로 되는 값은 255 근처의 값으로 하면 모두 하얗게 보임.
    ; bytscl로 한번 값을 거친 후 해결하는 게 좋음.

end

 

pro cloud_mask_01

    file = 'data/AHI_b03.png'

    help, file
    read_png, file, img
    help, img
    ;print, size(png_img, /dim)

    result = size(img, /dim)
    ;help, result
    ;print, result[0], result[1]

    ;  window, 0, xsize=result[0], ysize=result[1] 
    ;  tv, img
    ;
    ;  ;pl = plot(histogram(img))
    ;
    ;  window, 1, xsize=result[0], ysize=result[1] 
    ;  img_mask = ( img ge 40 and img lt 250 )
    ;  print, min(img_mask), max(img_mask)
    ;  
    ;  tvscl, img_mask*img
    ;  
    ;  window, 2, xsize=result[0], ysize=result[1]
    ;  tvscl, img > 150 < 250

    img = img > 80
    win = window(dimension=[800, 800])
    im = image(img, rgb_table=0, margin=0, /current)
    tx = text(0.5, 0.95, 'AHI b03', alignment=0.5, /normal, color='blue', font_size=20, $
    font_name='Times', font_style='bold')
    ;win.save, 'OUTPUT/cloud_mask01.pdf'


    stop

end

 

etc-image-2

 

 관련 자료

  • 강의안 및 교육 자료 참조

 

01. [에스이랩] IDL Image processing.7z

 

drive.google.com

 

 참고 문헌

[논문]

  • 없음

[보고서]

  • 없음

[URL]

  • 없음

 

 문의사항

[기상학/프로그래밍 언어]

  • sangho.lee.1990@gmail.com

[해양학/천문학/빅데이터]

  • saimang0804@gmail.com