일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 프로그래머스코테
- 리액트
- 몽고DB
- 리액트댓글기능
- 코딩테스트
- 백준js
- 백준nodejs
- 백준
- HTML
- 백준구현
- 백준알고리즘
- JS
- HTML5
- js코테
- 포이마웹
- 알고리즘
- 코테
- 프로그래머스
- 리액트커뮤니티
- 자바스크립트
- JS프로그래머스
- 백준골드
- CSS
- dp알고리즘
- 프로그래머스JS
- 백준구현문제
- 안드로이드 스튜디오
- 다이나믹프로그래밍
- css기초
- 익스프레스
- Today
- Total
개발새발 로그
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-4 본문
안녕하세요
시험을 끝내고 드디어 돌아왔습니다..
얼렁 이 프로젝트도 끝내기 위해 왔습니다!
저번에는 메인 부분 즉, 실행 부분만 보여드리고 설명드렸었죠?!
왜냐하면 그때는 아직 완벽하지 못한 것 같아서 제가 함수 부분은 못 올렸었는데요..
지금은 알고리즘도 다듬었고, 오류도 최소한으로 해봤습니다!
최소한 완성은 되었다고 말할 수 는 있는데
다른 오류가 나올 수도 있으니까 참고 바라요
그럼 먼저 전체소스 코드를 보여드릴게요!
import numpy as np
import cv2
import matplotlib.image as mpimg
from matplotlib import pyplot as plt
from scipy.sparse import base
from sklearn.cluster import KMeans
import re
import colorsys
#클러스터의 수를 파악하고 히스토그램을 만듬(각 클러스터에 할당된 픽셀 수를 기반으로)
def centroid_histogram(clt):
numLabels = np.arange(0, len(np.unique(clt.labels_)) + 1)
(hist, _) = np.histogram(clt.labels_, bins=numLabels)
# 합이 1이 되도록 히스토그램을 정규화합니다.
hist = hist.astype("float")
hist /= hist.sum()
return hist
#-------------------------------------------현재 색상의 빈도에 따라 bar를 만드는 함수------------------------------
def plot_colors(hist, centroids):
# 각 색상의 상대 빈도를 나타내는 막대 차트 초기화
bar = np.zeros((50, 300, 3), dtype="uint8")
startX = 0
maxvalue=0;
# 각 클러스터의 백분율과 색상을 반복합니다.
#zip은 병렬처리할때 여러 그룹의 데이터를 루프한번만 돌면서 처리 가능하다.(두 그룹의 데이터를 서로 엮어주는 것)
for (percent, color) in zip(hist, centroids):
# 각 군집의 상대 백분율을 표시합니다.
endX = startX + (percent * 300)
#startX는 bar의 처음부분 endx는 bar의 마지막 좌표부분임 그래서 막대의 크기를 통해 가장 많은색상을 비교해 추출함
if(maxvalue<(endX-startX)):
maxvalue=endX
maxcolor=color
maxcolor = maxcolor.astype(int)#여기가 가장 많은색상을 추출하는곳
#사각형으로 만듬
cv2.rectangle(bar, (int(startX), 0), (int(endX), 50),
color.astype("uint8").tolist(), -1)
startX = endX
return bar,maxcolor
#-------------------------------------------k값에 따라 bar를 통해 빈도가 높은 색상을 표현------------------------------
def image_color_cluster(image_path,checking, k = 3):
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = image.reshape((image.shape[0] * image.shape[1], 3))
#클러스터 생성 (n_clusters = k)는 정해진 명령어(fit로 클러스터링함)
clt = KMeans(n_clusters = k)
clt.fit(image)
hist = centroid_histogram(clt)
bar,maxcolor = plot_colors(hist, clt.cluster_centers_)
if(checking==True):
plt.figure()
plt.axis("off")
plt.imshow(bar)
plt.show()
return maxcolor
#-------------------------------------------rgb값을 HSV값으로 바꾸는 함수------------------------------
def convert_rgb_to_hsv(r,g,b):
#rgb기본 범위: (0-255, 0-255, 0.255)
#get rgb percentage: range (0-1, 0-1, 0-1 )
red_percentage= r / float(256)
green_percentage= g/ float(256)
blue_percentage=b / float(256)
#get hsv percentage: range (0-1, 0-1, 0-1)
color_hsv_percentage=colorsys.rgb_to_hsv(red_percentage, green_percentage, blue_percentage)
#get normal hsv: range (0-360, 0-255, 0-255)
color_h=round(360*color_hsv_percentage[0])
color_s=round(100*color_hsv_percentage[1])
color_v=round(100*color_hsv_percentage[2])
color_hsv=(color_h, color_s, color_v)
return color_hsv
#-----------------------------------체크하는곳------------------------------------------
def check_up_down (up_hsv,down,up_img,down_img):
#--------중략--------------------------------
#-----------------------------메인부분---체크하는 의류(상의)--------------------------------------
#여기가 내가 선택한 상의를 넣는 곳 상의를 넣게되면 저장되어 있는 하의들과 비교하는 시나리오임
chkimg = "img/up3.png"
image = mpimg.imread(chkimg)
plt.imshow(image)
up_color=image_color_cluster(chkimg,True) #TRUE는 해당 bar를 보여주게끔한다.밑에서는 생략하려고 함
print("체크하는 의류 BRG Format: ",up_color)
colorsB1 =up_color[2]
colorsG1 = up_color[1]
colorsR1 = up_color[0]
up_hsv_color=convert_rgb_to_hsv(colorsR1,colorsG1,colorsB1)
print("저장되는 의류 HSV Format" ,up_hsv_color)
#-----------------------------저장하는 의류(하의)--------------------------------------
img_paths = {
'검정슬랙스': 'img/down1.jpg',
'라이트그레이슬랙스': 'img/down2.jpg',
'카키슬랙스': 'img/down3.jpg',
'연청바지': 'img/down4.jpg',
'진청바지': 'img/down5.jpg',
'생지데님바지': 'img/down6.jpg',
'데미지청바지': 'img/down7.jpg',
'회색트레이닝바지':'img/down8.png'
}
##npy파일 만들기
descs = {
'검정슬랙스': None,
'라이트그레이슬랙스': None,
'카키슬랙스': None,
'연청바지': None,
'진청바지': None,
'생지데님바지': None,
'데미지청바지': None,
'회색트레이닝바지':None
}
print(type(img_paths))
for name, img_paths in img_paths.items():
#image = mpimg.imread(img_paths) 만약 저장되는 의류가 보고싶을 떄 삽입코드
#plt.imshow(image)
#매개변수 False는 상의의 색상은 사용자가 먼저 볼 수 있게하고, 하의는 너무 많이 있으므로 색상을 보여주는 과정을 생략하기 위함임
down_color=image_color_cluster(img_paths,False)
#하의의 hsv값을 갖고온다.
colorsB =down_color[2]
colorsG = down_color[1]
colorsR = down_color[0]
down_hsv_color=convert_rgb_to_hsv(colorsR,colorsG,colorsB)
#npy파일에 저장하는것을 출력
print("저장되는 의류 :",name)
print("저장되는 의류 RGB Format: ", down_color)
print("저장되는 의류 HSV Format" ,down_hsv_color)
#상하의의 색상매치하는 함수
check_up_down (up_hsv_color,down_hsv_color,chkimg,img_paths)
descs[name] = down_hsv_color
#각사람의 이름에 맞게 인코딩결과를 저장
np.save('img/descs.npy', descs)
print(descs)
여기서 메인부분은 전 포스팅에 설명되어있으니까 건너뛰고
함수 부분을 설명드릴게요!
제가 알기 쉽게 주석처리도 각각 해놨는데
그래도 자세하게 적어볼게요!
- k-means 클러스터링
#클러스터의 수를 파악하고 히스토그램을 만듬(각 클러스터에 할당된 픽셀 수를 기반으로)
def centroid_histogram(clt):
numLabels = np.arange(0, len(np.unique(clt.labels_)) + 1)
(hist, _) = np.histogram(clt.labels_, bins=numLabels)
# 합이 1이 되도록 히스토그램을 정규화합니다.
hist = hist.astype("float")
hist /= hist.sum()
return hist
#-------------------------------------------현재 색상의 빈도에 따라 bar를 만드는 함수------------------------------
def plot_colors(hist, centroids):
# 각 색상의 상대 빈도를 나타내는 막대 차트 초기화
bar = np.zeros((50, 300, 3), dtype="uint8")
startX = 0
maxvalue=0
# 각 클러스터의 백분율과 색상을 반복합니다.
#zip은 병렬처리할때 여러 그룹의 데이터를 루프한번만 돌면서 처리 가능하다.(두 그룹의 데이터를 서로 엮어주는 것)
for (percent, color) in zip(hist, centroids):
# 각 군집의 상대 백분율을 표시합니다.
endX = startX + (percent * 300)
#startX는 bar의 처음부분 endx는 bar의 마지막 좌표부분임 그래서 막대의 크기를 통해 가장 많은색상을 비교해 추출함
if(maxvalue<(endX-startX)):
maxvalue=endX
maxcolor=color
maxcolor = maxcolor.astype(int)#여기가 가장 많은색상을 추출하는곳
#사각형으로 만듬
cv2.rectangle(bar, (int(startX), 0), (int(endX), 50),
color.astype("uint8").tolist(), -1)
startX = endX
return bar,maxcolor
#-------------------------------------------k값에 따라 bar를 통해 빈도가 높은 색상을 표현------------------------------
def image_color_cluster(image_path,checking, k = 3):
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = image.reshape((image.shape[0] * image.shape[1], 3))
#클러스터 생성 (n_clusters = k)는 정해진 명령어(fit로 클러스터링함)
clt = KMeans(n_clusters = k)
clt.fit(image)
hist = centroid_histogram(clt)
bar,maxcolor = plot_colors(hist, clt.cluster_centers_)
if(checking==True):
plt.figure()
plt.axis("off")
plt.imshow(bar)
plt.show()
return maxcolor
- 클러스트링 함수 부분
k-means 클러스트링을 활용했습니다.
#-------------------------------------------k값에 따라 bar를 통해 빈도가 높은 색상을 표현------------------------------
def image_color_cluster(image_path,checking, k = 3):
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = image.reshape((image.shape[0] * image.shape[1], 3))
#클러스터 생성 (n_clusters = k)는 정해진 명령어(fit로 클러스터링함)
clt = KMeans(n_clusters = k)
clt.fit(image)
hist = centroid_histogram(clt)
bar,maxcolor = plot_colors(hist, clt.cluster_centers_)
if(checking==True):
plt.figure()
plt.axis("off")
plt.imshow(bar)
plt.show()
return maxcolor
여기서 먼저 이미지를 읽어옵니다(상의 하의 둘 다 해당됨)
그리고 clt라는 변수에 kMeans클러스터를 생성합니다(k는 3으로 지정해주었습니다.)
그리고 clt.fit으로 클러스터링 합니다.
해당 클러스터로 히스토그램을 만들기 위해 히스토그램 함수를 호출합니다
그리고 해당 히스토그램과 클러스터를 이용해 plot차트를 만들어줍니다
checking==True는 하의를 넣었을 때 해당 plot 차트를 다 띄워주게 되면 실행결과가 너무 많이 나와
상의에만 checking에 True값을 주어서 상의만 plot차트를 보여주고 상의의 색상만 어떤지 사용자가 확인할 수 있게끔 하였습니다.
- 히스토그램 부분(. numpy의 histogram : 도수 분포도)
def centroid_histogram(clt):
numLabels = np.arange(0, len(np.unique(clt.labels_)) + 1)
(hist, _) = np.histogram(clt.labels_, bins=numLabels)
# 합이 1이 되도록 히스토그램을 정규화합니다.
hist = hist.astype("float")
hist /= hist.sum()
return hist
이 부분이 히스토그램을 만드는 부분입니다.
저는 numpy의 히스토그램을 이용했습니다.
이분 거를 보고 공부했습니다.
아래와 같이 히스토그램을 생성합니다.
도수, 구분 = np.histogram(data, 도수분포 구간 (bin))
이런 식으로 구성되어있다는 것만 이해하시면 될 것 같습니다.
각 도수를 총합으로 나누면 상대 도수가 나오는 부분입니다.
상위 링크에서 예를 들은 이미지를 가져와보았습니다.
해당 값을 리턴하는데요
이제 다음 함수를 살펴볼까요?
여기서 히스토그램의 상대 도수를 사용합니다!
그럼 plot_colors를 살펴봐야겠네요
def plot_colors(hist, centroids):
# 각 색상의 상대 빈도를 나타내는 막대 차트 초기화
bar = np.zeros((50, 300, 3), dtype="uint8")
startX = 0
maxvalue=0
# 각 클러스터의 백분율과 색상을 반복합니다.
#zip은 병렬처리할때 여러 그룹의 데이터를 루프한번만 돌면서 처리 가능하다.(두 그룹의 데이터를 서로 엮어주는 것)
for (percent, color) in zip(hist, centroids):
# 각 군집의 상대 백분율을 표시합니다.
endX = startX + (percent * 300)
#startX는 bar의 처음부분 endx는 bar의 마지막 좌표부분임 그래서 막대의 크기를 통해 가장 많은색상을 비교해 추출함
if(maxvalue<(endX-startX)):
maxvalue=endX
maxcolor=color
maxcolor = maxcolor.astype(int)#여기가 가장 많은색상을 추출하는곳
#사각형으로 만듬
cv2.rectangle(bar, (int(startX), 0), (int(endX), 50),
color.astype("uint8").tolist(), -1)
startX = endX
return bar,maxcolor
처음 파이썬 하시는 분들이 보기에는 정말 다양한 명령어가 쓰여서 이해하기가 어려울 수 있습니다.
저도 초보자이기 때문에! 하나하나씩 명령어를 검색하면서 공부했는데요
저는 이 링크를 보며 공부했습니다.
https://inyl.github.io/programming/2017/07/31/opencv_image_color_cluster.html
clt.cluster_centers_:실제 clustering 된 컬러 값이 들어가게 하는 명령어입니다.
그래서 상위 부분에 히스토그램의 상대 도수 값을 가져오면 클러스터 개수의 영역에 얼마만큼의 퍼센티지가 차지하고 있는지가 return 됩니다.
즉
image = cv2.imread(image_path)
1. 여기서 이미지를 읽어오고 scikit-learn의 k-mean 알고리즘으로 이미지를 학습시켜줍니다.
k-mean알고리즘은 머신러닝의 비지도 학습 중에 가장 일반적인 모델로 k개의 데이터 평균을 만들어 데이터를 clustering 하는 알고리즘입니다.
2. centroid histogram 함수를 이용해서 클러스터 개수의 영역에 얼마만큼의 퍼센티지가 차지하고 있는지가 return 됩니다.
3. 그리고 plot_colors 함수를 이용해서 추출한 color와 histogram 데이터로 화면에 그래프를 그립니다.
여기서 저는 해당 색상값의 가장 주된 색상값을 추출하기 위해 mavalue라는 변수를 만들어서 해당 그래프를 만들 때
사용하는 startX와 endX를 이용해서 막대그래프의 크기 정도를 알아내고 그중 가장 큰 값을 주된 색상으로 저장해 리턴하였습니다.
- RGB To HSV 함수
#-------------------------------------------rgb값을 HSV값으로 바꾸는 함수------------------------------
def convert_rgb_to_hsv(r,g,b):
#rgb기본 범위: (0-255, 0-255, 0.255)
#get rgb percentage: range (0-1, 0-1, 0-1 )
red_percentage= r / float(256)
green_percentage= g/ float(256)
blue_percentage=b / float(256)
#get hsv percentage: range (0-1, 0-1, 0-1)
color_hsv_percentage=colorsys.rgb_to_hsv(red_percentage, green_percentage, blue_percentage)
#get normal hsv: range (0-360, 0-255, 0-255)
color_h=round(360*color_hsv_percentage[0])
color_s=round(100*color_hsv_percentage[1])
color_v=round(100*color_hsv_percentage[2])
color_hsv=(color_h, color_s, color_v)
return color_hsv
먼저 rgb값을 hsv값으로 바꾸는 부분입니다.
이 부분은 간단하게 설명드리면
해당 명령어를 사용하게 되면 hsv 값으로 변환하게 되지만 그 값이 실수형이므로 아래에서 360,100,100으로 곱해줍니다.
정말 간단하게 rgb값을 hsv값으로 바꿔주는 공식을 코드화 한 거라고 보시면 됩니다!
근데 포스팅이 너무 길어져서...
다음 글에서 마무리 짓겠습니다!
'파이썬' 카테고리의 다른 글
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-5 (0) | 2021.12.22 |
---|---|
파이썬 VS_CODE 처음 설치 후 환경 설정하기(파이썬 오류) (0) | 2021.12.19 |
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-3 (0) | 2021.11.08 |
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-2 (0) | 2021.11.08 |
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-1 (0) | 2021.11.06 |