일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- dp알고리즘
- 백준알고리즘
- 리액트커뮤니티
- CSS
- HTML
- 백준골드
- 자바스크립트
- 안드로이드 스튜디오
- css기초
- 프로그래머스
- 알고리즘
- JS
- 다이나믹프로그래밍
- 몽고DB
- js코테
- 백준nodejs
- 코테
- 포이마웹
- 백준
- 리액트
- 프로그래머스JS
- 프로그래머스코테
- 백준구현문제
- 익스프레스
- 리액트댓글기능
- HTML5
- 백준js
- 백준구현
- JS프로그래머스
- 코딩테스트
- Today
- Total
개발새발 로그
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-5 본문
마지막 소스 코드 설명입니다!
제가 만든 알고리즘 부분인데요
정말 제가 색상코드 보면서 규칙성을 찾아보면서
맘대로(?) 만들어낸 알고리즘입니다
마지막으로 전체 소스코드 올릴게요!
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):
up_img=cv2.imread(up_img,1)
down_img=cv2.imread(down_img,1)
if up_hsv[1]<10 or up_hsv[2]<10: #무채색은 s값이나 v값이 10보다 크면 색을 얻어서(육안으로) 무채색이 아니게 되므로 10 이하여야한다.
print("상의가 무채색")
if down[1]<10 or down[2]<10: #그냥 상의는무채색인걸 인지하고 무채색의 톤온톤은 무채색이므로 무채색인것만 거르면 톤온톤
print("무채색 톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#무채색의 톤인톤같은 경우는 유채색은 s와 v가 번갈아서 20씩증가하는데 무채색은 v의 값만 13씩 혹은 12씩 증가한다. 그래서 유채색의 톤이 20이하로 떨어지지 않는 점을 고려하여
#유채색의 s나 v의 값에서 20을 빼고 0.65를 곱하므로써
#유채색의 s나 v의 값이 1이 증가함과 무채색의 v값의 증가값을 같게하여
#그 차이가 3정도의 차이가 날때 톤인톤으로 정한다.
elif (up_hsv[2]<=52 and abs((down[2]-20)*0.65-up_hsv[2])<10) or up_hsv[2]>52 and abs(((100-down[1])+(down[2]-20))*0.65-up_hsv[2])<10 :
print("무채색 톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
elif down[1]<10: #하의 무채색은 고려해야댐 없애야할지
print("하의가 무채색")
if up_hsv[1]<10 or up_hsv[2]<10: #하의가 무채색이면 상의가 무채색이여야 톤온톤이므로 상의 값만 조건으로 둔다
print("톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#하의가 무채색일경우. 상의는 무채색이 무조건 아닌 경우다. 상의가 무채색이면 톤온톤으로 가버리므로 톤인톤이 될 수 없다.
#하의의 조건의 경우 상의 무채색 하의 유채색의 조건과 반대로 해야한다.
# 하의가 무채색인 기준으로 해야한다!
elif (down[2]<=52 and abs((up_hsv[2]-20)*0.65-down[2])<10) or down[2]>52 and abs(((100-up_hsv[1])+(up_hsv[2]-20))*0.65-down[2])<10 :
print("톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#모든 톤온톤은 무채색을 제외하고 0 100 20 <->0 20 100 다음 톤온톤이 29 100 20 <-> 29 20 100 이다.
#H값은 무조건 같고, s와 v는 20이하로만 가지않으면 톤온톤이다.(20이하는 무채색)
elif abs(down[0]-up_hsv[0])<30 and (abs(down[1]-up_hsv[1])>=20 or abs(down[2]-up_hsv[2])>=20):
print("톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
elif abs(down[1]-up_hsv[1])<15 and abs(down[2]-up_hsv[2])<15:
#톤인톤은 0 100 100 <-> 30 100 100 <->60 100 100 이 톤인톤이 성사된다
#그래서 s와 v값은 동일(혹은 15이상[20이상은 다른 톤인톤이 됨])해야하고 h값이 30이면 톤인톤이다.
print("톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#-----------------------------메인부분---체크하는 의류(상의)--------------------------------------
#여기가 내가 선택한 상의를 넣는 곳 상의를 넣게되면 저장되어 있는 하의들과 비교하는 시나리오임
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)
이제 여기서 색상이 톤온톤인지 톤인톤인지 걸러내는 함수부분을 확인해볼까요??
#-----------------------------------체크하는곳------------------------------------------
def check_up_down (up_hsv,down,up_img,down_img):
up_img=cv2.imread(up_img,1)
down_img=cv2.imread(down_img,1)
if up_hsv[1]<10 or up_hsv[2]<10: #무채색은 s값이나 v값이 10보다 크면 색을 얻어서(육안으로) 무채색이 아니게 되므로 10 이하여야한다.
print("상의가 무채색")
if down[1]<10 or down[2]<10: #그냥 상의는무채색인걸 인지하고 무채색의 톤온톤은 무채색이므로 무채색인것만 거르면 톤온톤
print("무채색 톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#무채색의 톤인톤같은 경우는 유채색은 s와 v가 번갈아서 20씩증가하는데 무채색은 v의 값만 13씩 혹은 12씩 증가한다. 그래서 유채색의 톤이 20이하로 떨어지지 않는 점을 고려하여
#유채색의 s나 v의 값에서 20을 빼고 0.65를 곱하므로써
#유채색의 s나 v의 값이 1이 증가함과 무채색의 v값의 증가값을 같게하여
#그 차이가 3정도의 차이가 날때 톤인톤으로 정한다.
elif (up_hsv[2]<=52 and abs((down[2]-20)*0.65-up_hsv[2])<10) or up_hsv[2]>52 and abs(((100-down[1])+(down[2]-20))*0.65-up_hsv[2])<10 :
print("무채색 톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
elif down[1]<10: #하의 무채색은 고려해야댐 없애야할지
print("하의가 무채색")
if up_hsv[1]<10 or up_hsv[2]<10: #하의가 무채색이면 상의가 무채색이여야 톤온톤이므로 상의 값만 조건으로 둔다
print("톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#하의가 무채색일경우. 상의는 무채색이 무조건 아닌 경우다. 상의가 무채색이면 톤온톤으로 가버리므로 톤인톤이 될 수 없다.
#하의의 조건의 경우 상의 무채색 하의 유채색의 조건과 반대로 해야한다.
# 하의가 무채색인 기준으로 해야한다!
elif (down[2]<=52 and abs((up_hsv[2]-20)*0.65-down[2])<5) or down[2]>52 and abs(((100-up_hsv[1])+up_hsv[2])*0.65-down[2])<5 :
print("톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#모든 톤온톤은 무채색을 제외하고 0 100 20 <->0 20 100 다음 톤온톤이 29 100 20 <-> 29 20 100 이다.
#H값은 무조건 같고, s와 v는 20이하로만 가지않으면 톤온톤이다.(20이하는 무채색)
elif abs(down[0]-up_hsv[0])<30 and (abs(down[1]-up_hsv[1])>=20 or abs(down[2]-up_hsv[2])>=20):
print("톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
elif abs(down[1]-up_hsv[1])<15 and abs(down[2]-up_hsv[2])<15:
#톤인톤은 0 100 100 <-> 30 100 100 <->60 100 100 이 톤인톤이 성사된다
#그래서 s와 v값은 동일(혹은 15이상[20이상은 다른 톤인톤이 됨])해야하고 h값이 30이면 톤인톤이다.
print("톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
이 부분이 톤온톤과 톤인톤을 결정하는 함수입니다
하나하나 살펴볼게요!
up_img=cv2.imread(up_img,1)
down_img=cv2.imread(down_img,1)
이 부분은 상의와 하의의 이미지를 갖고오는 부분입니다! 톤온톤과 톤인톤이 맞다면 해당 상의와 하의를 출력해줘야겠죠??
- 상의가 무채색일 때
먼저 상의가 무채색일 때를 결정지어주는 조건문입니다!
색상들은 유채색과 무채색으로 나뉘는데 무채색은 유채색과 달리 채도와 명도의 규칙성이 달라서
톤온톤, 톤인톤을 결정지을 때 다른 알고리즘으로 결정지어줘야 합니다!
이는 제가 처음에 포스팅한 글을 보면 알 수 있을거에요!
https://ydoag2003.tistory.com/3
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-1
파이썬 첫 프로젝트~ 파이썬을 이용해 상의와 하의의 색상을 추출하여 톤온톤과 톤인톤을 매칭하는 프로그램을 만들어보겠습니다! 먼저 알아야할 것은? 톤온톤 톤인톤이란? 톤온톤은 옷 색상의
ydoag2003.tistory.com
if up_hsv[1]<10 or up_hsv[2]<10: #무채색은 s값이나 v값이 10보다 크면 색을 얻어서(육안으로) 무채색이 아니게 되므로 10 이하여야한다.
print("상의가 무채색")
if down[1]<10 or down[2]<10: #그냥 상의는무채색인걸 인지하고 무채색의 톤온톤은 무채색이므로 무채색인것만 거르면 톤온톤
print("무채색 톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#무채색의 톤인톤같은 경우는 유채색은 s와 v가 번갈아서 20씩증가하는데 무채색은 v의 값만 13씩 혹은 12씩 증가한다. 그래서 유채색의 톤이 20이하로 떨어지지 않는 점을 고려하여
#유채색의 s나 v의 값에서 20을 빼고 0.65를 곱하므로써
#유채색의 s나 v의 값이 1이 증가함과 무채색의 v값의 증가값을 같게하여
#그 차이가 3정도의 차이가 날때 톤인톤으로 정한다.
elif (up_hsv[2]<=52 and abs((down[2]-20)*0.65-up_hsv[2])<10) or up_hsv[2]>52 and abs(((100-down[1])+(down[2]-20))*0.65-up_hsv[2])<10 :
print("무채색 톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
먼저 HSV에서 무채색은 H값에 상관없이 S와 V가 10이하정도일 때 모두 육안으로 무채색으로 보임을 확인하였습니다.
그래서 저는 "육안으로 봤을 때 무채색일 때"라는 기준을 10으로 정해서 상의의 S와 V값이 10이하일 때
"해당 상의의 색상은 무채색이므로 다른 조건에서 톤온톤 톤인톤을 결정지어야한다."
라는 조건을 만들었습니다.
if up_hsv[1]<10 or up_hsv[2]<10:
#무채색은 s값이나 v값이 10보다 크면 색을 얻어서(육안으로) 무채색이 아니게 되므로 10 이하여야한다.
print("상의가 무채색")
if down[1]<10 or down[2]<10:
#그냥 상의는무채색인걸 인지하고 무채색의 톤온톤은 무채색이므로 무채색인것만 거르면 톤온톤
if down[1]<10 or down[2]<10: : 이 부분이 바로 무채색 상의와 맞는 톤온톤 하의를 찾는 조건입니다.
하의의 S와 V의 값이 10 이하인 하의는 해당 상의의 톤온톤인데요
이유는 바로 무채색이기때문입니다!
무채색의 톤온톤은 무채색일 수 밖에 없기 때문에!
그럼 이제 상의가 무채색일 때 톤인톤을 볼까요??
elif (up_hsv[1]<=52 and abs((down[2]-20)*0.65-up_hsv[2])<5) or up_hsv[1]>52 and abs(((100-down[1])+down[2])*0.65-up_hsv[2])<5 :
이 조건이 바로 무채색상의의 톤인톤 하의를 결정짓는 조건문입니다
전체코드에서 제가 달아 놓은 주석을 한번 볼까요??
#무채색의 톤인톤같은 경우는 유채색은 s와 v가 번갈아서 20씩증가하는데 무채색은 v의 값만 13씩 혹은 12씩 증가한다. 그래서 유채색의 톤(V)이 20이하로 떨어지지 않는 점을 고려하여
#유채색의 s나 v의 값에서 20을 빼고 0.65를 곱하므로써
#유채색의 s나 v의 값이 1이 증가함과 무채색의 v값의 증가값을 같게하여
#그 차이가 10정도의 차이가 날때 톤인톤으로 정한다.
글로 보니까 모르겠죠..?
아래 그림을 볼까요?
톤인톤은 색상코드를 보았을 때
가로선상에 있는 색상끼리가 바로 톤인톤입니다.
유채색의 증가폭을 보면 H값만 변하고 S와 V의 값은 그대로 고정되어있죠??
근데 무채색은 그 규칙에 상관없이 H와 S의 값은 0이고 V값만 변하고 있습니다.
또한 아까 말했듯이 육안으로 보았을때 H의 값과 상관없이 S와 V의 값만 10이하일 때 무채색으로 보일 수 있다. 라는 기준을 제가 정했었죠?? 그 기준도 포함을 해야합니다!
하나하나 보겠습니다!
up_hsv[2]<=52 and abs((down[2]-20)*0.65-up_hsv[2])<10)
or up_hsv[2]>52 and abs(((100-down[1])+(down[2]-20))*0.65-up_hsv[2])<10
- 왜 52 이하인가요!
이유는 유채색의 세로패턴을 보게되면
V의값이 증가하다가 S와V가 100이 되면
S의 값이 20씩 감소하는 패턴을 보이게 됩니다.
하지만 무채색의 패턴은 계속해서 13혹은 12의 값이 증가합니다.
이를 걸러내기위해서는
유채색 하의의 S와V가 100인 시점을
무채색 하의의 52로 정하고 그 기준에 따라
그 이상일때와 이하일때의 시점에서는 다른 조건으로 해야 합니다
- down[2]-20에서 20을 뺀 이유는??
이유는 상위 가로선상을 보게되면
무채색은 0에서 시작하는데 유채색은 모두 20으로 고정되어있죠??
그럼 동일선상에서 증가를 하게해서 무채색의 V가 0일때 유채색의 V가 20이고 그 차이가 10정도면 같다로 해야하니까
(여기서 S의 값은 위 52이하로 걸러주었습니다! S값은 비교안해도 됨)
일단 유채색도 0으로 시작하면 보기도 편하고 계산하기도 편하겠죠?!
- 0.65를 곱한 이유는??
다시 색상코드를 보게되면 유채색(*,*,20) 하고 무채색(0,0,0) 이 톤인톤이죠??
근데 증가값을 보게되면 유채색은(*,*,40)이고 무채색은(0,0,13)이에요..
증가값 자체가 달라서 어떻게하면 유채색의 값이 달라짐에따라 무채색도 같은 범위내로 달라질까를 고민하다가!
0.65*20을 하게되면 13이 되는 것을 이용했어요!
유채색에서 1이 증가하게 되면 무채색은 0.65가 증가하게 되고
이 두개의 값들은 어느정도 범위내에서 톤인톤이 되는거죠!
- 상의의 V값이 52이상일 때의 조건은 무슨 뜻?
이 경우는 이제 비교하는 유채색의 HSV값중 S와 V가 둘다 100 일 때 달라지는 경우를 뜻합니다
유채색은 중간에 두 개의 값이 100이 되면 V가 증가하던 패턴이 S가 감소하는 패턴으로 바뀌게 됩니다.
무채색의 경우에는 그저 13혹은 12씩 증가하고 있는 패턴입니다.
그래서 이 경우를 무시하고 유채색과 무채색의 값이 온전히 비교될 수 있도록하기위해 아까 위에 설명드렸던 것처럼
기준을 나누었고, 조건을 달리하였습니다
- abs(((100-down[1])+(down[2]-20))*0.65-up_hsv[2])<10 하위 기준에 대해서 설명
위에서 설명드렸듯이 비교하는 유채색의 S와 V의 증가 감소가 바뀌어도
온전히 유채색 값과 무채색 값이 비교되어야하므로
유채색의 S값에 100을 빼서 남은 값을 V에서 20을 뺀 값에 더해서
증가와 감소가 바뀌었지만 이 식으로 인해 계속해서 유채색이 무채색과 함께 증가하고 있게 해줍니다.
예를 들어 (*,60,100)인 유채색이 있다면 비교되는 무채색은 (0,0,75) 입니다.
저 공식에 대입해보면
(100-60)+(100-20)=120
120*0.65=78
78-75= 3
이와 같이 마지막에는 정확하지는 않지만 3이라는 값이 나옵니다
육안으로 확인했을 때는 구별이 불가능한정도입니다.
그래서 저는 육안으로 확인할 수 있는 값인 10까지를 정해서
그 차이가 10 이하면 톤인톤으로 결정될 수 있게 하였습니다.
밑의 결과 값인
226,7,71(상의 HSV)
205,33,49(하의 HSV)
로 예를 들어 볼게요!
어떤가요?? 육안으로 확인했을 때 톤이 비슷하지 않나요??
상의의 V값이 71이므로 먼저 52이라는 기준에 이상이므로 그에 맞는 공식을 써야합니다
((100-33)+(49-20))*0.65-71=-8.6
그 차이가 10 이하이므로 톤인톤에 적합하다고 판별하게 하였습니다!
이번에는 하의가 무채색일 때 입니다.
elif down[1]<10: #하의 무채색은 고려해야댐 없애야할지
print("하의가 무채색")
if up_hsv[1]<10 or up_hsv[2]<10: #하의가 무채색이면 상의가 무채색이여야 톤온톤이므로 상의 값만 조건으로 둔다
print("톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
#하의가 무채색일경우. 상의는 무채색이 무조건 아닌 경우다. 상의가 무채색이면 톤온톤으로 가버리므로 톤인톤이 될 수 없다.
#하의의 조건의 경우 상의 무채색 하의 유채색의 조건과 반대로 해야한다.
# 하의가 무채색인 기준으로 해야한다!
elif (down[2]<=52 and abs((up_hsv[2]-20)*0.65-down[2])<5) or down[2]>52 and abs(((100-up_hsv[1])+(up_hsv[2]-20))*0.65-down[2])<5 :
print("톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
이 경우는 사실 위에서 설명드린 상의가 무채색일 때와 반대로 생각하시면 됩니다.
그러므로 이 설명은 넘어가도록 할게요!
elif abs(down[0]-up_hsv[0])<30 and (abs(down[1]-up_hsv[1])>=20 or abs(down[2]-up_hsv[2])>=20):
print("톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
elif abs(down[1]-up_hsv[1])<15 and abs(down[2]-up_hsv[2])<15:
#톤인톤은 0 100 100 <-> 30 100 100 <->60 100 100 이 톤인톤이 성사된다
#그래서 s와 v값은 동일(혹은 15이상[20이상은 다른 톤인톤이 됨])해야하고 h값이 30이면 톤인톤이다.
print("톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
이제 상의와 하의 모두 유채색일 경우에 톤온톤과 톤인톤입니다.
톤온톤부터 확인해볼게요!
색상코드를 보면서 설명해드릴게요!
- 상의와 하의 모두 유채색일 경우 톤온톤
elif abs(down[0]-up_hsv[0])<30 and (abs(down[1]-up_hsv[1])>=20 or abs(down[2]-up_hsv[2])>=20):
print("톤온톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton on ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
먼저 톤온톤의 조건으로는 세로선상에서 S값과 V값이 20씩 증가 혹은 감소하게 됩니다.
그리고 세로 선상으로 보게되면 H의 값이 30이 차이나게 됩니다
이 두가지 조건을 이용해서
1. H값이 30이 차이나면 다른 색상의 톤온톤으로 넘어가므로 H의 차이가 30이하이도록 합니다.
2. S와 V값의 차이가 20이상이기면 하면 된다.(20의 차이를 준 이유는 20 이하이게 되면 톤온톤이 아님 그저 같은 색이기 때문입니다. 예를 들어 올블랙 의상을 생각하시면 됩니다.)
- 상의와 하의 모두 유채색일 경우 톤인톤
elif abs(down[1]-up_hsv[1])<15 and abs(down[2]-up_hsv[2])<15:
#톤인톤은 0 100 100 <-> 30 100 100 <->60 100 100 이 톤인톤이 성사된다
#그래서 s와 v값은 동일(혹은 15이상[20이상은 다른 톤인톤이 됨])해야하고 h값이 30이면 톤인톤이다.
print("톤인톤 조합 좋음")
up_img=cv2.resize(up_img,(500,500))
down_img=cv2.resize(down_img,(500,500))
add=cv2.vconcat([up_img,down_img])
cv2.imshow('ton in ton',add)
cv2.waitKey(0)
cv2.destroyAllWindows()
톤인톤의 조건을 보게되면 세로선상에서 S와 V의 값은 항상 같고 H값만 변동하는 것을 볼 수 있습니다.
그리고 세로선상에서 보게되면 S혹은 V의 값이 20이 차이나게 됩니다.
이 두가지 조건을 이용해서
1. 상의와 하의의 S와 V의 값의 차이가 15 이하일 때 톤인톤을 결정합니다
이는 두가지 이유가 있습니다
-15이상일 경우 다른 색상의 톤인톤으로 넘어가게되므로
-15를 차이로 둔 이유 톤인톤 자체가 톤만 같고 색이 다른 것이므로 육안으로 확인 했을 때 15정도로 두면 톤인톤을 결정하기에 적당하다고 판단했음
2. 톤온톤처럼 H값은 조건을 두지 않은 이유
- 톤인톤은 위에서 말했듯이 그저 같은톤이고 색만 다르므로 광범위합니다. 그저 톤만 같으면 된다고 판단하였습니다.
- 임의로 의상 이미지를 넣어 했을 때 톤인톤의 조건이 까다롭기에 넣지않았습니다.(기호에따라 넣으셔도 됩니다.)
여기까지 알고리즘 설명이 끝났습니다!
두서없이 설명하였는데
모두 이해하셨으면 좋겠네요..
이제 결과화면을 한번 확인해보겠습니다.
- 선택한 상의의 추출한 색상을 알려준다
- 비교 결과
어떤가요??
잘 구별한거 같나요??
포스팅하면서도 알고리즘에 변화를 좀 단단하게 구성하면 더 정확하고, 색 구별을 잘할 것 같다는 생각이 들었습니다.
실제로도 하면서 코드변경이 있었구요.
제가 직접 짜본 알고리즘인데
남이 보면 조금 난해할 수 있다고 생각이 듭니다.
그래도 재밌게 봐주세요!
'파이썬' 카테고리의 다른 글
OPENCV와 K-MEANS CLUSTERING을 이용한 상 하의 색상 매칭-4 (0) | 2021.12.19 |
---|---|
파이썬 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 |