이수빈

t2t3

Showing 38 changed files with 479 additions and 206 deletions
자가진단 서비스와 tensorflow를 활용한 퍼스널 컬러 찾아주는 React 기반의 웹
# Find your Personal Color
OpenCV를 활용한 퍼스널 컬러 찾아주는 서비스
# Find your Personal Color
## 요약
자가진단 설문와 openCV를 활용한 퍼스널 컬러 찾아주는 React 기반의 웹 서비스
## 상세
### 1. 서비스
기존에 있는 퍼스널 컬러 진단 서비스는 대부분 사용자 이미지를 분석하고 퍼스널 컬러를 찾아주거나, 자가진단 설문을 통해 퍼스널 컬러를 알려주는 두 형태 중 한가지 형태로 진행되는 경우가 많았습니다. 저희는 두가지 서비스 모두를 구현하여 사용자들이 좀 더 정확한 퍼스널 컬러를 확인할 수 있도록 했습니다.
### 2. front
### 3. back
# 전체 서비스
// 전체 서비스 동작 이미지//
# 알고리즘
💻마더 프로젝트에서 가져온 알고리즘을 수정 및 개선하였습니다.💻
유저 이미지의 피부 사진을 가져와 평균 색깔을 추출합니다. 이를 토대로 이미지 RGB 값을 Lab 색 공간을 변환합니다. Lab b 값(푸른색의 정도)을 웜톤, 쿨톤의 스탠다드 값과의 거리를 계산하여 웜톤과 쿨톤을 구별합니다.
<img src="algorithm/color_data/algoimg.png" width="60%" height="60%">
원본 알고리즘은 눈썹과 눈동자도 계산하여 가중치를 곱한 후, 계절을 구별하도록 하였는데, 이는 저희가 생각한 limit 정확도보다 떨어져서 계절 구별은 이미지 분석이 아닌 자가진단 설문에서만 구현했습니다.
또한, 원본 알고리즘은 웜톤과 쿨톤의 스탠다드 값을 연예인들의 이미지를 학습시켜 평균치를 구했는데, 본래 이미지를 통해서 확인하는 퍼스널 컬러는 조명, 화이트 밸런스, 화장 여부 등에 의해 영향을 많이 받기 때문에 이 부분을 수정하였습니다. 퍼스널 컬러 대표 색 이미지들의 Lab b값을 training시켜, 그 평균치를 스탠다드 값으로 업데이트 하였습니다.
# 빌드 방법
......@@ -9,3 +30,4 @@ OpenCV를 활용한 퍼스널 컬러 찾아주는 서비스
# LICENSE
마더 프로젝트 https://github.com/starbucksdolcelatte/ShowMeTheColor.git
\ No newline at end of file
......
#!/usr/bin/env python
# coding: utf-8
# In[72]:
# 평균 색상 추출
import cv2
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from skimage import io
from itertools import compress
# tone 구별
from scipy.spatial import distance
import copy
import math
import operator
# main함수
from colormath.color_objects import LabColor, sRGBColor, HSVColor
from colormath.color_conversions import convert_color
# color extract 클래스
class DominantColors:
CLUSTERS = None
IMAGE = None
COLORS = None
LABELS = None
def __init__(self, image, clusters=3):
self.CLUSTERS = clusters
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
self.IMAGE = img.reshape((img.shape[0] * img.shape[1], 3))
#using k-means to cluster pixels
kmeans = KMeans(n_clusters = self.CLUSTERS)
kmeans.fit(self.IMAGE)
#the cluster centers are our dominant colors.
self.COLORS = kmeans.cluster_centers_
self.LABELS = kmeans.labels_
def rgb_to_hex(self, rgb):
return '#%02x%02x%02x' % (int(rgb[0]), int(rgb[1]), int(rgb[2]))
# Return a list in order of color that appeared most often.
def getHistogram(self):
numLabels = np.arange(0, self.CLUSTERS+1)
#create frequency count tables
(hist, _) = np.histogram(self.LABELS, bins = numLabels)
hist = hist.astype("float")
hist /= hist.sum()
colors = self.COLORS
#descending order sorting as per frequency count
colors = colors[(-hist).argsort()]
hist = hist[(-hist).argsort()]
for i in range(self.CLUSTERS):
colors[i] = colors[i].astype(int)
# Blue mask 제거
fil = [colors[i][2] < 250 and colors[i][0] > 10 for i in range(self.CLUSTERS)]
colors = list(compress(colors, fil))
return colors, hist
def plotHistogram(self):
colors, hist = self.getHistogram()
#creating empty chart
chart = np.zeros((50, 500, 3), np.uint8)
start = 0
#creating color rectangles
for i in range(len(colors)):
end = start + hist[i] * 500
r,g,b = colors[i]
#using cv2.rectangle to plot colors
cv2.rectangle(chart, (int(start), 0), (int(end), 50), (r,g,b), -1)
start = end
#display chart
plt.figure()
plt.axis("off")
plt.imshow(chart)
plt.show()
return colors
#tone analysis 함수
def is_warm(lab_b, a):
'''
파라미터 lab_b = [skin_b, hair_b, eye_b]
a = 가중치 [skin, hair, eye]
질의색상 lab_b값에서 warm의 lab_b, cool의 lab_b값 간의 거리를
각각 계산하여 warm이 가까우면 1, 반대 경우 0 리턴
'''
# standard of skin, eyebrow, eye (눈썹, 눈동자는 0으로)
warm_b_std = [38.022000000000006, 0, 0]
cool_b_std = [17, 0, 0]
warm_dist = 0
cool_dist = 0
body_part = ['skin', 'eyebrow', 'eye']
for i in range(1):
warm_dist += abs(lab_b[i] - warm_b_std[i]) * a[i]
print(body_part[i],"의 warm 기준값과의 거리")
print(abs(lab_b[i] - warm_b_std[i]))
cool_dist += abs(lab_b[i] - cool_b_std[i]) * a[i]
print(body_part[i],"의 cool 기준값과의 거리")
print(abs(lab_b[i] - cool_b_std[i]))
if(warm_dist <= cool_dist):
return 1 #warm
else:
return 0 #cool
# 이미지 자르는 함수
def trimming (img):
x = 100;
y = 100;
w = 100;
h = 100;
img_trim = img[y:y+h, x:x+w]
return img_trim
# 원래 main
def analysis(imgpath):
#######################################
# Face detection #
#######################################
img=cv2.imread(imgpath)
h,w,c=img.shape
if((h>500) and (w>500)):
img = trimming(img) # 이미지가 너무 크면 잘라서 확인
face = [img, img,
img, img,
img, img]
#######################################
# Get Dominant Colors #
#######################################
temp = []
clusters = 4
for f in face:
dc = DominantColors(f, clusters)
face_part_color, _ = dc.getHistogram()
#dc.plotHistogram()
temp.append(np.array(face_part_color[0]))
cheek1 = np.mean([temp[0], temp[1]], axis=0)
cheek2 = np.mean([temp[2], temp[3]], axis=0)
cheek3 = np.mean([temp[4], temp[5]], axis=0)
Lab_b, hsv_s = [], []
color = [cheek1, cheek2, cheek3]
for i in range(3):
rgb = sRGBColor(color[i][0], color[i][1], color[i][2], is_upscaled=True)
lab = convert_color(rgb, LabColor, through_rgb_type=sRGBColor)
hsv = convert_color(rgb, HSVColor, through_rgb_type=sRGBColor)
Lab_b.append(float(format(lab.lab_b,".2f")))
hsv_s.append(float(format(hsv.hsv_s,".2f"))*100)
Lab_b[1]=0
Lab_b[2]=0
print('Lab_b[skin]',Lab_b[0])
#######################################
# Personal color Analysis #
#######################################
Lab_weight = [100, 0, 0]
hsv_weight = [10, 0, 0]
if(is_warm(Lab_b, Lab_weight)):
tone = '웜톤(warm)'
else:
tone = '쿨톤(cool)'
# Print Result
print('{}의 퍼스널 컬러는 {}입니다.'.format(imgpath, tone))
def main():
analysis('color_data\warm_spring.png')
if __name__ == '__main__':
main()
# In[ ]:
cool
14
19
24
13
6
11
28
22
14
19
17
warm
46.47
35.13
29.34
36.69
29.44
25.49
29.32
36.6
45.54
21.43
21.52
23.25
86
\ No newline at end of file
[{"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\App.js":"1","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\Home.js":"2","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test.js":"3","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\index.js":"4"},{"size":450,"mtime":1606821338165,"results":"5","hashOfConfig":"6"},{"size":493,"mtime":1606821338174,"results":"7","hashOfConfig":"6"},{"size":5504,"mtime":1606845175132,"results":"8","hashOfConfig":"6"},{"size":238,"mtime":1606589880919,"results":"9","hashOfConfig":"6"},{"filePath":"10","messages":"11","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"pqxpq",{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"14","messages":"15","errorCount":0,"warningCount":8,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"16","messages":"17","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\App.js",[],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\Home.js",[],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test.js",["18","19","20","21","22","23","24","25"],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\index.js",[],{"ruleId":"26","severity":1,"message":"27","line":1,"column":17,"nodeType":"28","messageId":"29","endLine":1,"endColumn":26},{"ruleId":"26","severity":1,"message":"30","line":38,"column":8,"nodeType":"28","messageId":"29","endLine":38,"endColumn":22},{"ruleId":"26","severity":1,"message":"31","line":69,"column":8,"nodeType":"28","messageId":"29","endLine":69,"endColumn":22},{"ruleId":"26","severity":1,"message":"32","line":107,"column":9,"nodeType":"28","messageId":"29","endLine":107,"endColumn":18},{"ruleId":"26","severity":1,"message":"33","line":107,"column":20,"nodeType":"28","messageId":"29","endLine":107,"endColumn":40},{"ruleId":"26","severity":1,"message":"34","line":108,"column":9,"nodeType":"28","messageId":"29","endLine":108,"endColumn":18},{"ruleId":"26","severity":1,"message":"35","line":108,"column":20,"nodeType":"28","messageId":"29","endLine":108,"endColumn":40},{"ruleId":"26","severity":1,"message":"36","line":146,"column":7,"nodeType":"28","messageId":"29","endLine":146,"endColumn":31},"no-unused-vars","'useEffect' is defined but never used.","Identifier","unusedVar","'questions_cool' is assigned a value but never used.","'questions_warm' is assigned a value but never used.","'score_w_s' is assigned a value but never used.","'setScore_warm_spring' is assigned a value but never used.","'score_w_a' is assigned a value but never used.","'setScore_warm_autumn' is assigned a value but never used.","'handlePersonalScore_cool' is assigned a value but never used."]
\ No newline at end of file
[{"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\App.js":"1","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\Home.js":"2","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test.js":"3","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\index.js":"4","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test2.js":"5","C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test3.js":"6"},{"size":536,"mtime":1606848159635,"results":"7","hashOfConfig":"8"},{"size":493,"mtime":1606821338174,"results":"9","hashOfConfig":"8"},{"size":3347,"mtime":1606849098689,"results":"10","hashOfConfig":"8"},{"size":238,"mtime":1606589880919,"results":"11","hashOfConfig":"8"},{"size":3249,"mtime":1606848650428,"results":"12","hashOfConfig":"8"},{"size":3312,"mtime":1606849310943,"results":"13","hashOfConfig":"8"},{"filePath":"14","messages":"15","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"pqxpq",{"filePath":"16","messages":"17","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"18","messages":"19","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"20","messages":"21","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"22","messages":"23","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"24","messages":"25","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\App.js",[],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\Home.js",[],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test.js",["26"],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\index.js",[],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test2.js",["27"],"C:\\Users\\subin\\Desktop\\khuhub_color\\Find_your_own_personal_color\\front\\src\\test3.js",["28"],{"ruleId":"29","severity":1,"message":"30","line":1,"column":17,"nodeType":"31","messageId":"32","endLine":1,"endColumn":26},{"ruleId":"29","severity":1,"message":"33","line":2,"column":8,"nodeType":"31","messageId":"32","endLine":2,"endColumn":15},{"ruleId":"29","severity":1,"message":"33","line":2,"column":8,"nodeType":"31","messageId":"32","endLine":2,"endColumn":15},"no-unused-vars","'useEffect' is defined but never used.","Identifier","unusedVar","'console' is defined but never used."]
\ No newline at end of file
......
......@@ -2,6 +2,8 @@ import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import Home from './Home';
import Test from './test';
import Test2 from './test2';
import Test3 from './test3';
class App extends Component {
......@@ -10,7 +12,9 @@ class App extends Component {
<div>
<BrowserRouter>
<Route path="/" exact component={Home} />
<Route path="/test" exact component={Test} />
<Route path="/test" exact component={Test} />
<Route path="/test2" exact component={Test2} />
<Route path="/test3" exact component={Test3} />
</BrowserRouter>
</div>
)
......
......@@ -35,89 +35,20 @@ const Test = ( { history } ) =>
},
]; //웜,쿨 파악
const questions_cool = [
{
questionText: '머리카락 색이 검정에 가깝다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '피부에 붉은 기가 많다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '손목 혈관 색이 초록색이다',
answerOptions: [
{ answerText: '예', isCorrect: false },
{ answerText: '아니오', isCorrect: true }
],
},
{
questionText: '햇볕에 장시간 있으면 피부가 붉어진다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
]; //여름쿨톤, 겨울쿨톤 파악
const questions_warm = [
{
questionText: '머리카락 색이 검정에 가깝다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '피부에 붉은 기가 많다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '손목 혈관 색이 초록색이다',
answerOptions: [
{ answerText: '예', isCorrect: false },
{ answerText: '아니오', isCorrect: true }
],
},
{
questionText: '햇볕에 장시간 있으면 피부가 붉어진다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
]; //봄웜톤, 가을웜톤 파악
const [currentQuestion, setCurrentQuestion] = useState(0); //현재 문제 번호 [변수, 함수]
const [showScore, setShowScore] = useState(false); //결과 보여줄까?
const [score_c, setScore_cool] = useState(0); //쿨톤 점수 -> 웜,쿨 리스트에서 사용
const [score_w, setScore_warm] = useState(0); //웜톤 점수 -> 웜,쿨 리스트에서 사용
const [score_c_s, setScore_cool_summer] = useState(0);
const [score_c_w, setScore_cool_winter] = useState(0);
const [score_w_s, setScore_warm_spring] = useState(0);
const [score_w_a, setScore_warm_autumn] = useState(0);
const [score, setPersonal] = useState(""); //퍼스널컬러 결과
const handleAnswerOptionClick = (isCorrect) => { //main 함수 1_웜쿨 검사
if (isCorrect) {
setScore_cool(score_c + 1);
setScore_cool_summer(score_c_s + 1);
console.log('c' + score_c);
}
else{
setScore_warm(score_w + 1);
setScore_cool_winter(score_c_w + 1);
console.log('w' + score_w);
} ///웜,쿨 if문으로 점수 올리기
......@@ -143,24 +74,14 @@ const Test = ( { history } ) =>
}
}; //함수2 끝.
const handlePersonalScore_cool = (score_c_s,score_c_w) =>{ //함수3_여쿨, 겨쿨 점수로 결과 구하기
if(score_c_s>score_c_w){
setPersonal('summer cool');
}
else if(score_c_s<score_c_w){
setPersonal('winter cool');
}
else{
setPersonal('restart');
}
}; //함수3 끝.
return (
<div className='app'>
{showScore ? (
<span className='score-section'>
You scored {score} out of {questions.length}
<button onClick={() => handlePersonalScore(score_c,score_w)}>result</button>
{score === "cool" ? <button onClick={ () => {history.push("/test2")}}>next</button>
: <button onClick={ () => {history.push("/test3")}}>next</button>}
</span>
) : (
<>
......
import React, { useState } from 'react'; //리액트 불러오기
import console from 'react-console'; //리액트 콘솔_크롬으로 실행
import './test.css';//test.css 불러오기
const Test2 = ( { history } ) =>
{
const questions_cool = [
{
questionText: '머리카락 색이 검정에 가깝다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '피부에 붉은 기가 많다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '손목 혈관 색이 초록색이다',
answerOptions: [
{ answerText: '예', isCorrect: false },
{ answerText: '아니오', isCorrect: true }
],
},
{
questionText: '햇볕에 장시간 있으면 피부가 붉어진다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
]; //여름쿨톤, 겨울쿨톤 파악
const [currentQuestion_c, setCurrentQuestion] = useState(0); //현재 문제 번호 [변수, 함수]
const [showScore_c, setShowScore] = useState(false); //결과 보여줄까?
const [score_c_s, setScore_cool_summer] = useState(0);
const [score_c_w, setScore_cool_winter] = useState(0);
const [score, setPersonal] = useState(""); //퍼스널컬러 결과
const handleAnswerOptionClick = (isCorrect) => {
if (isCorrect) {
setScore_cool_summer(score_c_s + 1);
}
else{
setScore_cool_winter(score_c_w + 1);
}
const nextQuestion = currentQuestion_c + 1;
if (nextQuestion < questions_cool.length) {
setCurrentQuestion(nextQuestion);
}
else{
setShowScore(true); //questions 끝나면 점수 보여줄까? true -> className='score-section'
}
}; //함수1 끝.
const handlePersonalScore_cool = (score_c_s,score_c_w) =>{ //함수3_여쿨, 겨쿨 점수로 결과 구하기
if(score_c_s>score_c_w){
setPersonal('summer cool');
}
else if(score_c_s<score_c_w){
setPersonal('winter cool');
}
else{
setPersonal('restart');
}
}; //함수3 끝.
return (
<div className='app'>
{showScore_c ? (
<span className='score-section'>
You scored {score} out of {questions_cool.length}
<button onClick={() => handlePersonalScore_cool(score_c_s,score_c_w)}>result</button>
{score === "cool" ? <button onClick={ () => {history.push("/test2")}}>next</button>
: <button onClick={ () => {history.push("/test3")}}>next</button>}
</span>
) : (
<>
<div className='question-section'>
<div className='question-count'>
<span>Question {currentQuestion_c + 1}</span>/{questions_cool.length}
</div>
<div className='question-text'>{questions_cool[currentQuestion_c].questionText}</div>
</div>
<div className='answer-section'>
{questions_cool[currentQuestion_c].answerOptions.map((answerOption) => (
<button onClick={() => handleAnswerOptionClick(answerOption.isCorrect)}>{answerOption.answerText}</button>
))}
</div>
</>
)}
</div>
);
}
export default Test2;
\ No newline at end of file
import React, { useState } from 'react'; //리액트 불러오기
import console from 'react-console'; //리액트 콘솔_크롬으로 실행
import './test.css';//test.css 불러오기
const Test3 = ( { history } ) =>
{
const questions_warm = [
{
questionText: '머리카락 색이 검정에 가깝다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '피부에 붉은 기가 많다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
{
questionText: '손목 혈관 색이 초록색이다',
answerOptions: [
{ answerText: '예', isCorrect: false },
{ answerText: '아니오', isCorrect: true }
],
},
{
questionText: '햇볕에 장시간 있으면 피부가 붉어진다',
answerOptions: [
{ answerText: '예', isCorrect: true },
{ answerText: '아니오', isCorrect: false }
],
},
]; //봄웜톤, 가을웜톤 파악
const [currentQuestion_w, setCurrentQuestion] = useState(0); //현재 문제 번호 [변수, 함수]
const [showScore_w, setShowScore] = useState(false); //결과 보여줄까?
const [score_w_s, setScore_warm_spring] = useState(0);
const [score_w_a, setScore_warm_autumn] = useState(0);
const [score, setPersonal] = useState(""); //퍼스널컬러 결과
const handleAnswerOptionClick = (isCorrect) => { //main 함수 1_웜쿨 검사
if (isCorrect) {
setScore_warm_spring(score_w_s+1);
}
else{
setScore_warm_autumn(score_w_a+1);
} ///웜,쿨 if문으로 점수 올리기
const nextQuestion = currentQuestion_w + 1;
if (nextQuestion < questions_warm.length) {
setCurrentQuestion(nextQuestion);
}
else{
setShowScore(true); //questions 끝나면 점수 보여줄까? true -> className='score-section'
}
}; //함수1 끝.
const handlePersonalScore_warm = (score_w_s,score_w_a) =>{ //함수3_여쿨, 겨쿨 점수로 결과 구하기
if(score_w_s>score_w_a){
setPersonal('spring warm');
}
else if(score_w_s<score_w_a){
setPersonal('autumn warm');
}
else{
setPersonal('restart');
}
}; //함수3 끝.
return (
<div className='app'>
{showScore_w ? (
<span className='score-section'>
You scored {score} out of {questions_warm.length}
<button onClick={() => handlePersonalScore_warm(score_w_s,score_w_a)}>result</button>
{score === "cool" ? <button onClick={ () => {history.push("/test2")}}>next</button>
: <button onClick={ () => {history.push("/test3")}}>next</button>}
</span>
) : (
<>
<div className='question-section'>
<div className='question-count'>
<span>Question {currentQuestion_w + 1}</span>/{questions_warm.length}
</div>
<div className='question-text'>{questions_warm[currentQuestion_w].questionText}</div>
</div>
<div className='answer-section'>
{questions_warm[currentQuestion_w].answerOptions.map((answerOption) => (
<button onClick={() => handleAnswerOptionClick(answerOption.isCorrect)}>{answerOption.answerText}</button>
))}
</div>
</>
)}
</div>
);
}
export default Test3;
\ No newline at end of file
import cv2 as cv
import numpy as np
hsv = 0
lower_blue1 = 0
upper_blue1 = 0
lower_blue2 = 0
upper_blue2 = 0
lower_blue3 = 0
upper_blue3 = 0
def mouse_callback(event, x, y, flags, param):
global hsv, lower_blue1, upper_blue1, lower_blue2, upper_blue2, lower_blue3, upper_blue3
# 마우스 왼쪽 버튼 누를시 위치에 있는 픽셀값을 읽어와서 HSV로 변환합니다.
if event == cv.EVENT_LBUTTONDOWN:
print(img_color[y, x])
color = img_color[y, x]
one_pixel = np.uint8([[color]])
hsv = cv.cvtColor(one_pixel, cv.COLOR_BGR2HSV)
hsv = hsv[0][0]
# HSV 색공간에서 마우스 클릭으로 얻은 픽셀값과 유사한 필셀값의 범위를 정합니다.
if hsv[0] < 10:
print("case1")
lower_blue1 = np.array([hsv[0]-10+180, 30, 30])
upper_blue1 = np.array([180, 255, 255])
lower_blue2 = np.array([0, 30, 30])
upper_blue2 = np.array([hsv[0], 255, 255])
lower_blue3 = np.array([hsv[0], 30, 30])
upper_blue3 = np.array([hsv[0]+10, 255, 255])
# print(i-10+180, 180, 0, i)
# print(i, i+10)
elif hsv[0] > 170:
print("case2")
lower_blue1 = np.array([hsv[0], 30, 30])
upper_blue1 = np.array([180, 255, 255])
lower_blue2 = np.array([0, 30, 30])
upper_blue2 = np.array([hsv[0]+10-180, 255, 255])
lower_blue3 = np.array([hsv[0]-10, 30, 30])
upper_blue3 = np.array([hsv[0], 255, 255])
# print(i, 180, 0, i+10-180)
# print(i-10, i)
else:
print("case3")
lower_blue1 = np.array([hsv[0], 30, 30])
upper_blue1 = np.array([hsv[0]+10, 255, 255])
lower_blue2 = np.array([hsv[0]-10, 30, 30])
upper_blue2 = np.array([hsv[0], 255, 255])
lower_blue3 = np.array([hsv[0]-10, 30, 30])
upper_blue3 = np.array([hsv[0], 255, 255])
# print(i, i+10)
# print(i-10, i)
print(hsv[0])
print("@1", lower_blue1, "~", upper_blue1)
print("@2", lower_blue2, "~", upper_blue2)
print("@3", lower_blue3, "~", upper_blue3)
cv.namedWindow('img_color')
cv.setMouseCallback('img_color', mouse_callback)
while(True):
img_color = cv.imread('cool_summer.png')
height, width = img_color.shape[:2]
img_color = cv.resize(img_color, (width, height), interpolation=cv.INTER_AREA)
# 원본 영상을 HSV 영상으로 변환합니다.
img_hsv = cv.cvtColor(img_color, cv.COLOR_BGR2HSV)
# 범위 값으로 HSV 이미지에서 마스크를 생성합니다.
img_mask1 = cv.inRange(img_hsv, lower_blue1, upper_blue1)
img_mask2 = cv.inRange(img_hsv, lower_blue2, upper_blue2)
img_mask3 = cv.inRange(img_hsv, lower_blue3, upper_blue3)
img_mask = img_mask1 | img_mask2 | img_mask3
# 마스크 이미지로 원본 이미지에서 범위값에 해당되는 영상 부분을 획득합니다.
img_result = cv.bitwise_and(img_color, img_color, mask=img_mask)
cv.imshow('img_color', img_color)
cv.imshow('img_mask', img_mask)
cv.imshow('img_result', img_result)
# ESC 키누르면 종료
if cv.waitKey(1) & 0xFF == 27:
break
cv.destroyAllWindows()
import numpy as np
import cv2 as cv
img_color = cv.imread('cool_summer.png')
print('shape: ', img_color.shape)
height, width = img_color.shape[:2]
img_hsv = cv.cvtColor(img_color, cv.COLOR_BGR2HSV)
lower_blue = (120-10, 50, 50)
upper_blue = (120+10, 255, 255)
img_mask = cv.inRange(img_hsv, lower_blue, upper_blue)
img_result = cv.bitwise_and(img_color, img_color, mask = img_mask)
cv.imshow('img_origin', img_color)
cv.imshow('img_mask', img_mask)
cv.imshow('img_color', img_result)
cv.waitKey(0)
cv.destroyAllWindows()