상세 컨텐츠

본문 제목

수학과 함께하는 AI기초_01(이미지데이터처리)

파이썬·장고·루비·알고리즘

by 김일국 2024. 12. 9. 11:59

본문

이번에 EBS 강의 교재기반의 AI기초(파이선기반)을 공부하고 있습니다.

(교재명)  EBS 수학과 함께하는 AI 기초 : PDF 교재는 아래 에서 무료로 다운로드 가능합니다.^^

https://www.ebssw.kr/info/intrcn/infoTchmtrHeaderView.do?bookCode=6&tabType=AI

(온라인강좌) EBS 이솦: https://www.ebssw.kr/lrnng/alctcr/alctcrDetailView.do?alctcrSn=56134

- 강좌명 : 수학과 함께하는 AI기초 #1 - 데이터의 표현과 가공

- 14개 챕터(장), 31개 강의로 이루어 져 있고, 지금 7-1 ~ 8-1장(챕터) 사이를 하고 있습니다.

 

#  위 교재의 학습내용을 간단히 소개해 보고자 합니다.(소스 실습은 Python 3.8.10 IDLE 에디터를 사용하였습니다.)

- https://www.ebssw.kr/upload/pgm/ebs_math_ai.pdf 교재 제일 마지막의 Python 기본 IDLE(통합 개발 환경)로 실습 환경 준비하기 참조

##1. 넘파이 행렬과 필로우+매트플로트라이브러리를 이용하여 외부에서 불러온 이미지의 RGB 색상을 분해하기(아래)

import numpy as np
import matplotlib.pyplot as plt
import PIL.Image as pilimg

im = pilimg.open("rgb_circle.bmp")
#im = pilimg.open("jeju_summer.jpg")

pix = np.array(im)
pixSize = np.array(pix.shape)
print(pixSize) # [행, 열, 차원-Dimension] 정보 배열 출력
pix_R = pix.copy()
# [:, :, ]으로 행렬 크기는 그대로 유지 하면서,
# 3차원의 RGB(0,1,2) 에서 G,B(1,2) 값을 0으로 만든다.(아래)
pix_R[:,:,(1,2)] = 0
pix_G = pix.copy()
pix_G[:,:,(0,2)] = 0
pix_B = pix.copy()
pix_B[:,:,(0,1)] = 0
# matplot 모듈로 위에서 분리한 이미지를 표시한다.(아래)
plt.subplot(141) # 도표에 1행 4열의 1번째 이미지를 만들겠다.(1/4장)
plt.imshow(pix)
plt.axis("off")
plt.title("RGB")
plt.subplot(142) # 도표에 1행 4열의 2번째 이미지를 만들겠다.(2/4장)
plt.imshow(pix_R)
plt.axis("off")
plt.title("R(red)")
plt.subplot(143) # 도표에 1행 4열의 3번째 이미지를 만들겠다.(3/4장)
plt.imshow(pix_G)
plt.axis("off")
plt.title("G(green)")
plt.subplot(144) # 도표에 1행 4열의 4번째 이미지를 만들겠다.(4/4장)
plt.imshow(pix_B)
plt.axis("off")
plt.title("B(blue)")

plt.show() # 도표에 결과 보이기

- 위 소스에서 RGB 타이틀의 이미지에서 R, G, B 부분만 별도로 추출하여 plot에 출력한 결과이다.(아래)

- 위 소스에서 사용한 RGB이미지 :

rgb_circle.bmp
0.14MB

 

##2. 넘파이 행렬을 기반으로 사칙연산을 하고 터틀로 도형을 그리기(아래)

import turtle
import numpy as np
pixelSize = 10
turtle.speed(0)
def putPixel(x,y,pSize, pCol):
    turtle.penup()
    turtle.goto(x*pSize,(-1)*y*pSize)
    turtle.pendown()
    turtle.begin_fill()
    turtle.fillcolor(pCol)
    turtle.setheading(45)
    turtle.circle(pSize/2, steps=4)
    turtle.end_fill()
# 16x16
faceImg = np.array([
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
    [0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
    [0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
    [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
    [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
    [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
    [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
    [0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
    [0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    ])
smileImg = np.array([
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,0],
    [0,0,0,0,2,0,2,0,2,0,2,0,0,0,0,0],
    [0,0,0,0,2,2,2,0,2,2,2,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0],
    [0,0,0,0,2,2,0,0,0,0,2,2,0,0,0,0],
    [0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0],
    [0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    ])
for j in range(0, 16):
    for i in range(0,16):
        if(faceImg[j][i] > 0):
            putPixel(i,j,pixelSize,"orange")
        else:
            putPixel(i,j,pixelSize,"white")
for j in range(0, 16):
    for i in range(0,16):
        if(smileImg[j][i] > 0):
            putPixel(i+20,j,pixelSize,"red")
        else:
            putPixel(i+20,j,pixelSize,"white")
#turtle.getscreen()._root.mainloop() # 창을 종료할 때까지 프로그램을 실행한다.
addImg = np.array(faceImg + smileImg)
print(addImg)
for j in range(0, 16):
    for i in range(0,16):
        if(addImg[j][i] > 1):
            putPixel(i-20,j,pixelSize,"red")
        elif(addImg[j][i] > 0):
            putPixel(i-20,j,pixelSize,"orange")
        else:
            putPixel(i-20,j,pixelSize,"white")
turtle.getscreen()._root.mainloop() # 창을 종료할 때까지 프로그램을 실행한다..

- 위 소스를 실행하면, 아래 오른쪽 터틀모듈로 그린 도형을 합쳐서 제일 왼쪽 최종 결과가 보인다.(아래)

 

##3. im1=배경이미지 내부에 im2,im3 이미지크기를 변경하고 투명도를 조정하여 겹친 이미지를 표시한다.(아래)

import numpy as np
import matplotlib.pyplot as plt
import PIL.Image as pilimg

# im1=배경이미지 내부에 im2,im3 이미지크기를 변경하고 투명도를 조정하여 겹친다.
im1 = pilimg.open("jeju_summer.jpg")
im2 = pilimg.open("1.jpg")
im3 = pilimg.open("2.jpg")
'''
print(im1.size)
print(im2.size) # 이미지 행렬의 크기
print(im3.size)
'''
# im1에 들어갈 이미지 x축=가로크기를 resizeX1, resizeX2 변수에 저장한다.(아래)
pix1 = np.array(im1) # im1 *행렬생성. 단, 각 행렬의 최대값은 255를 넘지 않는다.
print(pix1.shape[0]) # 행렬의 행=y축의 크기.
resizeX2 = pix1.shape[1]/2 # 행렬중 shape[1]=열=x축의 크기를 반으로 나눈다.
if(pix1.shape[1]%2>0): # 열의 크기가 홀수라면...
    resizeX1 = pix1.shape[1]/2+1 # 열의 크기를 짝수로 만든다.
else:
    resizeX1 = pix1.shape[1]/2

# im2, im3 의 x축=가로크기, y축=shape[0]=세로크기를 지정 후 *행렬생성(아래)
im2 = im2.resize((int(resizeX1), int(pix1.shape[0])))
pix2 = np.array(im2)
im3 = im3.resize((int(resizeX2), int(pix1.shape[0])))
pix3 = np.array(im3)

# im2, im3 가로로 붙이기(아래) axis값을 0으로 하면 세로로 붙인 *행렬생성.
pix4 = np.concatenate((pix2, pix3), axis = 1)

# 이미지 RGB=256가지색상값을 실수범위(0-1)의 256단계로 정규화한 *행렬생성(아래)
pix1 = (1/255)*pix1 # pix1의 행렬의 각 값의 최대값이 255이기 때문에, 즉,(아래계속)
pix4 = (1/255)*pix4 # , ~즉, 255로 나누면, 0-255 값을 0-1사이의 범위로 변환된다.

# 이미지 행렬의 알파값=투명도 정하기(im1 으니 30%, im2,im3는 70%)
weight = 0.3

# 위 투명도 a를 직용한 *행렬생성(아래) Pn = a*Pa + (1-a)*Pb
pix5 = (pix1*weight)+(pix4*(1-weight))
# 위 투명도를 반대로 적용한 *행렬생성(아래)
pix6 = (pix1*(1-weight))+(pix4*weight)

# pix5, pix6 행렬출력하기
plt.subplot(141) # 전체plot=출력영역의 1행4열중 1번열로 출력할 위치 지정
plt.imshow(pix1)
plt.axis("off")
plt.title("im1", fontsize=10)
plt.subplot(142)
plt.imshow(pix4)
plt.axis("off")
plt.title("im2+im3", fontsize=10)
plt.subplot(143)
plt.imshow(pix5)
plt.axis("off")
plt.title("70% blended", fontsize=10) # im2,im3 가 더 선명하게
plt.subplot(144)
plt.imshow(pix6)
plt.axis("off")
plt.title("30% blended", fontsize=10) # im1=배경이 더 선생하게
plt.show()

# Pillow를 사용하여 pix5, pix6 저장하기
pix5 = pix5*255 # 정규화 한 값을 원상복구하지 않으면, 사진이 검은색으로 나온다.
im5 = pilimg.fromarray(pix5.astype(np.uint8)) # uint8=8bit unsigned intteger
im5.save('result_70.png')
pix6 = pix6*255
im6 = pilimg.fromarray(pix6.astype(np.uint8))
im6.save('result_30.png')

- 위 소스를 실행한 결과 순서: im1-배경이미지, im2+im3(2개 이미지 합치기), 70%알파값, 30%알파값 결과(아래)

- 위 와 아래 소스에서 사용한 이미지는 픽사베이 ( https://pixabay.com/ko/ ) 무료 이미지 3개를 다운받아 사용하였습니다.

 

##4. 컬러이이지를 흑백이미지로 만들기(아래)

# 컬리 이지미를 흑백 이미지톤으로 만들기
import numpy as np
import matplotlib.pyplot as plt
import PIL.Image as pilimg
import time # 작업시간 측정
start = time.time() # 시작시간 지정
im1 = pilimg.open("1.jpg") # 같은 폴더의 이미지 불러오기
im1 = im1.resize((im1.width//2, im1.height//2)) # 속도 향상을 위해 이미지 사이즈 줄이기

'''
# im1 데이터를 numpy 배열array 로 변환
pix1 = np.array(im1)
pix1 = (1/255)*pix1 # RGB 0-255사이의 값을 최대값255로 나누면, 0-1사이 값으로 정규화된다.
print(pix1.shape) # 3차원 RGB 데이터임을 확
pixSize1 = np.array(pix1.shape)
pix2 = np.empty(pixSize1)

for i in range(pixSize1[0]):
    for j in range(pixSize1[1]): # pix1[행][열][R=0,G=1,B=2] 값을 회색톤으로 변환(아래)
        grayPix = 0.2126*pix1[i][j][0] + 0.7152*pix1[i][j][1] + 0.0722*pix1[i][j][2]
        pix2[i,j] = (grayPix, grayPix, grayPix) # 이미지 행렬의 값을 회색톤으로 지정
'''
# 위 코드 대신 아래 im1.convert()함수를 사용하면 아래처럼 간단하다.
# PILLOW 내장 기능으로도 흑백 이미지로 만들수도 있다.(위 11번라인 부터 21번까지 필요없다.)
pix1 = pilimg.open("1.jpg") # 같은 폴더의 이미지 불러오기
pix2 = im1.convert('LA') # convert함수로 흑백이미지로 변환하기

print("Time : ", time.time() - start) # 작업시간 출력

plt.subplot(121) # 플로트화면에 1행2열의 1번째지정
plt.imshow(pix1) # 원래 이미지 출력
plt.axis("off") # 플로트도표의 축은 보이지 않게지정
plt.title("Original", fontsize=9)

plt.subplot(122) # 플로트화면에 1행2열의 2번째지정
plt.imshow(pix2) # 회색통으로 변환된 이미지 출력
plt.axis("off") # 플로트도표의 축은 보이지 않게지정
plt.title("Gray converted", fontsize=9)

plt.show()

- 위 소스에서 정규화란? [개별값들/전체개별값 중 최대값 = 0~1사이로 값이 변환]을 아래식과 같이 예를 들면, 어떤 계산식이 더 간단할 것인가? 판단할 수 있다. 

비교 계산식:   1,000,000/10,000,000 = 1/10  (즉, 1/10 으로 변경해서 계산하는 식이 더 간단하다.)

- 위 처럼 변환 코드를 PILLOW의 convert(LA)함수로 간단히 흑백이미지로 변환가능하다. 참고로, 변환시간도 더 빠르다.(아래)

관련글 더보기

댓글 영역