Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
face
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Кубота
face
Commits
0bbd229b
Commit
0bbd229b
authored
May 22, 2020
by
Иван Кубота
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
switch matching to lab
parent
a403f608
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
941 additions
and
73 deletions
+941
-73
extract-colors.js
examples/examples-browser/public/js/extract-colors.js
+349
-69
let_my_people_go.js
examples/examples-browser/public/js/let_my_people_go.js
+585
-0
demo.html
examples/examples-browser/views/demo.html
+7
-4
No files found.
examples/examples-browser/public/js/extract-colors.js
View file @
0bbd229b
var
RGB2XYZ
=
function
(
R
,
G
,
B
)
{
if
(
R
>
255
)
{
console
.
warn
(
'Red value was higher than 255. It has been set to 255.'
);
R
=
255
;
}
else
if
(
R
<
0
)
{
console
.
warn
(
'Red value was smaller than 0. It has been set to 0.'
);
R
=
0
;
}
if
(
G
>
255
)
{
console
.
warn
(
'Green value was higher than 255. It has been set to 255.'
);
G
=
255
;
}
else
if
(
G
<
0
)
{
console
.
warn
(
'Green value was smaller than 0. It has been set to 0.'
);
G
=
0
;
}
if
(
B
>
255
)
{
console
.
warn
(
'Blue value was higher than 255. It has been set to 255.'
);
B
=
255
;
}
else
if
(
B
<
0
)
{
console
.
warn
(
'Blue value was smaller than 0. It has been set to 0.'
);
B
=
0
;
}
var
r
=
R
/
255
;
var
g
=
G
/
255
;
var
b
=
B
/
255
;
// step 1
if
(
r
>
0.04045
)
{
r
=
Math
.
pow
(((
r
+
0.055
)
/
1.055
),
2.4
);
}
else
{
r
=
r
/
12.92
;
}
if
(
g
>
0.04045
)
{
g
=
Math
.
pow
(((
g
+
0.055
)
/
1.055
),
2.4
);
}
else
{
g
=
g
/
12.92
;
}
if
(
b
>
0.04045
)
{
b
=
Math
.
pow
(((
b
+
0.055
)
/
1.055
),
2.4
);
}
else
{
b
=
b
/
12.92
;
}
// step 2
r
=
r
*
100
;
g
=
g
*
100
;
b
=
b
*
100
;
// step 3
var
X
=
(
r
*
0.4124
)
+
(
g
*
0.3576
)
+
(
b
*
0.1805
);
var
Y
=
(
r
*
0.2126
)
+
(
g
*
0.7152
)
+
(
b
*
0.0722
);
var
Z
=
(
r
*
0.0193
)
+
(
g
*
0.1192
)
+
(
b
*
0.9505
);
return
[
X
,
Y
,
Z
];
}
var
XYZ2LAB
=
function
(
X
,
Y
,
Z
)
{
// using 10o Observer (CIE 1964)
// CIE10_D65 = {94.811f, 100f, 107.304f} => Daylight
var
ReferenceX
=
94.811
;
var
ReferenceY
=
100
;
var
ReferenceZ
=
107.304
;
// step 1
var
x
=
X
/
ReferenceX
;
var
y
=
Y
/
ReferenceY
;
var
z
=
Z
/
ReferenceZ
;
// step 2
if
(
x
>
0.008856
)
{
x
=
Math
.
pow
(
x
,
(
1
/
3
));
}
else
{
x
=
(
7.787
*
x
)
+
(
16
/
116
);
}
if
(
y
>
0.008856
)
{
y
=
Math
.
pow
(
y
,
(
1
/
3
));
}
else
{
y
=
(
7.787
*
y
)
+
(
16
/
116
);
}
if
(
z
>
0.008856
)
{
z
=
Math
.
pow
(
z
,
(
1
/
3
));
}
else
{
z
=
(
7.787
*
z
)
+
(
16
/
116
);
}
// step 3
var
L
=
(
116
*
y
)
-
16
;
var
A
=
500
*
(
x
-
y
);
var
B
=
200
*
(
y
-
z
);
return
[
L
,
A
,
B
];
};
function
LAB2XYZ
(
L
,
A
,
B
)
{
// using 10o Observer (CIE 1964)
// CIE10_D65 = {94.811f, 100f, 107.304f} => Daylight
var
ReferenceX
=
94.811
;
var
ReferenceY
=
100
;
var
ReferenceZ
=
107.304
;
var
var_Y
=
(
L
+
16
)
/
116
;
var
var_X
=
A
/
500
+
var_Y
;
var
var_Z
=
var_Y
-
B
/
200
;
if
(
Math
.
pow
(
var_Y
,
3
)
>
0.008856
)
{
var_Y
=
Math
.
pow
(
var_Y
,
3
);
}
else
{
var_Y
=
(
var_Y
-
16
/
116
)
/
7.787
;
}
if
(
Math
.
pow
(
var_X
,
3
)
>
0.008856
)
{
var_X
=
Math
.
pow
(
var_X
,
3
);
}
else
{
var_X
=
(
var_X
-
16
/
116
)
/
7.787
;
}
if
(
Math
.
pow
(
var_Z
,
3
)
>
0.008856
)
{
var_Z
=
Math
.
pow
(
var_Z
,
3
);
}
else
{
var_Z
=
(
var_Z
-
16
/
116
)
/
7.787
;
}
var
X
=
var_X
*
ReferenceX
;
var
Y
=
var_Y
*
ReferenceY
;
var
Z
=
var_Z
*
ReferenceZ
;
return
[
X
,
Y
,
Z
];
}
var
XYZ2RGB
=
function
(
X
,
Y
,
Z
)
{
var
var_X
=
X
/
100
;
var
var_Y
=
Y
/
100
;
var
var_Z
=
Z
/
100
;
var
var_R
=
(
var_X
*
3.2406
)
+
(
var_Y
*
-
1.5372
)
+
(
var_Z
*
-
0.4986
);
var
var_G
=
(
var_X
*
-
0.9689
)
+
(
var_Y
*
1.8758
)
+
(
var_Z
*
0.0415
);
var
var_B
=
(
var_X
*
0.0557
)
+
(
var_Y
*
-
0.2040
)
+
(
var_Z
*
1.0570
);
if
(
var_R
>
0.0031308
)
{
var_R
=
1.055
*
Math
.
pow
(
var_R
,
(
1
/
2.4
)
)
-
0.055
;
}
else
{
var_R
=
12.92
*
var_R
;
}
if
(
var_G
>
0.0031308
)
{
var_G
=
1.055
*
Math
.
pow
(
var_G
,
(
1
/
2.4
)
)
-
0.055
;
}
else
{
var_G
=
12.92
*
var_G
;
}
if
(
var_B
>
0.0031308
)
{
var_B
=
1.055
*
Math
.
pow
(
var_B
,
(
1
/
2.4
)
)
-
0.055
;
}
else
{
var_B
=
12.92
*
var_B
;
}
var
R
=
Math
.
round
(
var_R
*
255
);
var
G
=
Math
.
round
(
var_G
*
255
);
var
B
=
Math
.
round
(
var_B
*
255
);
return
[
R
,
G
,
B
];
}
function
rgbToLab
(
r
,
g
,
b
)
{
return
XYZ2LAB
.
apply
(
null
,
RGB2XYZ
(
r
,
g
,
b
))
};
function
labToRgb
(
r
,
g
,
b
)
{
return
XYZ2RGB
.
apply
(
null
,
LAB2XYZ
(
r
,
g
,
b
))
};
function
rgbToHsv
(
r
,
g
,
b
)
{
r
/=
255
,
g
/=
255
,
b
/=
255
;
...
...
@@ -21,6 +174,79 @@ function rgbToHsv(r, g, b) {
return
[
h
,
s
,
v
];
}
var
labDistance
=
function
(
l1
,
l2
)
{
return
DeltaE00
(
l1
,
l2
);
};
var
DeltaE00
=
function
(
lab1
,
lab2
)
{
var
l1
=
lab1
[
0
],
a1
=
lab1
[
1
],
b1
=
lab1
[
2
],
l2
=
lab2
[
0
],
a2
=
lab2
[
1
],
b2
=
lab2
[
2
];
// Utility functions added to Math Object
Math
.
rad2deg
=
function
(
rad
)
{
return
360
*
rad
/
(
2
*
Math
.
PI
);
};
Math
.
deg2rad
=
function
(
deg
)
{
return
(
2
*
Math
.
PI
*
deg
)
/
360
;
};
// Start Equation
// Equation exist on the following URL http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE2000.html
var
avgL
=
(
l1
+
l2
)
/
2
;
var
C1
=
Math
.
sqrt
(
Math
.
pow
(
a1
,
2
)
+
Math
.
pow
(
b1
,
2
));
var
C2
=
Math
.
sqrt
(
Math
.
pow
(
a2
,
2
)
+
Math
.
pow
(
b2
,
2
));
var
avgC
=
(
C1
+
C2
)
/
2
;
var
G
=
(
1
-
Math
.
sqrt
(
Math
.
pow
(
avgC
,
7
)
/
(
Math
.
pow
(
avgC
,
7
)
+
Math
.
pow
(
25
,
7
))))
/
2
;
var
A1p
=
a1
*
(
1
+
G
);
var
A2p
=
a2
*
(
1
+
G
);
var
C1p
=
Math
.
sqrt
(
Math
.
pow
(
A1p
,
2
)
+
Math
.
pow
(
b1
,
2
));
var
C2p
=
Math
.
sqrt
(
Math
.
pow
(
A2p
,
2
)
+
Math
.
pow
(
b2
,
2
));
var
avgCp
=
(
C1p
+
C2p
)
/
2
;
var
h1p
=
Math
.
rad2deg
(
Math
.
atan2
(
b1
,
A1p
));
if
(
h1p
<
0
)
{
h1p
=
h1p
+
360
;
}
var
h2p
=
Math
.
rad2deg
(
Math
.
atan2
(
b2
,
A2p
));
if
(
h2p
<
0
)
{
h2p
=
h2p
+
360
;
}
var
avghp
=
Math
.
abs
(
h1p
-
h2p
)
>
180
?
(
h1p
+
h2p
+
360
)
/
2
:
(
h1p
+
h1p
)
/
2
;
var
T
=
1
-
0.17
*
Math
.
cos
(
Math
.
deg2rad
(
avghp
-
30
))
+
0.24
*
Math
.
cos
(
Math
.
deg2rad
(
2
*
avghp
))
+
0.32
*
Math
.
cos
(
Math
.
deg2rad
(
3
*
avghp
+
6
))
-
0.2
*
Math
.
cos
(
Math
.
deg2rad
(
4
*
avghp
-
63
));
var
deltahp
=
h2p
-
h1p
;
if
(
Math
.
abs
(
deltahp
)
>
180
)
{
if
(
h2p
<=
h1p
)
{
deltahp
+=
360
;
}
else
{
deltahp
-=
360
;
}
}
var
delta_lp
=
l2
-
l1
;
var
delta_cp
=
C2p
-
C1p
;
deltahp
=
2
*
Math
.
sqrt
(
C1p
*
C2p
)
*
Math
.
sin
(
Math
.
deg2rad
(
deltahp
)
/
2
);
var
Sl
=
1
+
((
0.015
*
Math
.
pow
(
avgL
-
50
,
2
))
/
Math
.
sqrt
(
20
+
Math
.
pow
(
avgL
-
50
,
2
)));
var
Sc
=
1
+
0.045
*
avgCp
;
var
Sh
=
1
+
0.015
*
avgCp
*
T
;
var
deltaro
=
30
*
Math
.
exp
(
-
(
Math
.
pow
((
avghp
-
275
)
/
25
,
2
)));
var
Rc
=
2
*
Math
.
sqrt
(
Math
.
pow
(
avgCp
,
7
)
/
(
Math
.
pow
(
avgCp
,
7
)
+
Math
.
pow
(
25
,
7
)));
var
Rt
=
-
Rc
*
Math
.
sin
(
2
*
Math
.
deg2rad
(
deltaro
));
var
kl
=
1
;
var
kc
=
1
;
var
kh
=
1
;
var
deltaE
=
Math
.
sqrt
(
Math
.
pow
(
delta_lp
/
(
kl
*
Sl
),
2
)
+
Math
.
pow
(
delta_cp
/
(
kc
*
Sc
),
2
)
+
Math
.
pow
(
deltahp
/
(
kh
*
Sh
),
2
)
+
Rt
*
(
delta_cp
/
(
kc
*
Sc
))
*
(
deltahp
/
(
kh
*
Sh
)));
return
deltaE
;
};
/**
...
...
@@ -56,7 +282,7 @@ function hsvToRgb(h, s, v) {
}
var
extractColors
=
function
(
ctx
,
where
,
k
,
debug
){
var
extractColors
=
function
(
ctx
,
where
,
k
,
production
){
var
points
=
[].
concat
.
apply
(
[],
where
.
map
(
function
(
polygon
){
...
...
@@ -80,44 +306,54 @@ var extractColors = function( ctx, where, k, debug){
var
r
,
g
,
b
;
var
colors
=
[];
var
debugPixels
=
document
.
getElementById
(
'ccolors'
).
getContext
(
'2d'
);
if
(
!
production
){
var
debugPixels
=
document
.
getElementById
(
'ccolors'
).
getContext
(
'2d'
);
var
debugData
=
debugPixels
.
getImageData
(
0
,
0
,
100
,
480
),
dd
=
debugData
.
data
;
var
pt
=
(
extracting
*
100
*
120
*
4
)
}
var
pt
=
(
extracting
*
100
*
120
*
4
)
for
(
var
i
=
0
,
_i
=
points
.
length
;
i
<
_i
;
i
++
){
var
p
=
points
[
i
],
pointer
=
(
p
[
0
]
-
minX
+
(
p
[
1
]
-
minY
)
*
w
)
*
4
;
r
=
data
[
pointer
];
g
=
data
[
pointer
+
1
];
b
=
data
[
pointer
+
2
];
pt
=
((
extracting
*
100
*
120
+
i
*
2
+
((
i
/
50
)
|
0
)
*
100
)
*
4
);
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
pt
=
((
extracting
*
100
*
120
+
i
*
2
+
((
i
/
50
)
|
0
)
*
100
)
*
4
)
+
100
*
4
;
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
if
(
!
production
){
pt
=
(
(
extracting
*
100
*
120
+
i
*
2
+
(
(
i
/
50
)
|
0
)
*
100
)
*
4
);
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
pt
=
(
(
extracting
*
100
*
120
+
i
*
2
+
(
(
i
/
50
)
|
0
)
*
100
)
*
4
)
+
100
*
4
;
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
dd
[
pt
++
]
=
r
;
dd
[
pt
++
]
=
g
;
dd
[
pt
++
]
=
b
;
dd
[
pt
++
]
=
255
;
}
//data[ pointer + 2 ] = 255
colors
.
push
(
rgbTo
Hsv
(
r
,
g
,
b
)
);
colors
.
push
(
rgbTo
Lab
(
r
,
g
,
b
)
);
}
if
(
!
production
){
debugPixels
.
putImageData
(
debugData
,
0
,
0
);
}
//ctx2.putImageData( imageData, minX, minY );
var
means
=
new
KMeans
();
var
result
=
{
means
:
means
,
clusters
:
means
.
cluster
(
colors
,
k
,
hsv
Distance
)
};
var
result
=
{
means
:
means
,
clusters
:
means
.
cluster
(
colors
,
k
,
lab
Distance
)
};
var
amount
=
0
;
for
(
var
i
=
0
,
_i
=
result
.
clusters
.
length
;
i
<
_i
;
i
++
){
var
cluster
=
result
.
clusters
[
i
]
||
[];
...
...
@@ -128,29 +364,41 @@ var extractColors = function( ctx, where, k, debug){
return
{
color
:
c
,
normalized
:
c
.
length
/
amount
};
}
)
.
filter
(
function
(
c
){
return
c
.
normalized
>
1
/
(
k
*
3
);
return
c
.
normalized
>
1
/
(
k
*
2.5
);
}
)
.
sort
(
function
(
a
,
b
){
return
a
.
normalized
-
b
.
normalized
;
}
)
.
map
(
function
(
c
){
return
c
.
color
.
sort
(
colorSort
)[
0
];
//result.means.centroids.slice().sort(distanceToHSV(c.color[0]))[0];
var
l
=
0
,
a
=
0
,
b
=
0
;
for
(
var
i
=
0
,
_i
=
c
.
color
.
length
;
i
<
_i
;
i
++
){
var
colorElement
=
c
.
color
[
i
];
l
+=
colorElement
[
0
];
a
+=
colorElement
[
1
];
b
+=
colorElement
[
2
];
}
return
[
l
/
c
.
color
.
length
,
a
/
c
.
color
.
length
,
b
/
c
.
color
.
length
];
//c.color.sort( colorSort )[ 0 ];//result.means.centroids.slice().sort(distanceToHSV(c.color[0]))[0];
}
);
var
similars
=
filteredResult
.
map
(
function
(
c
,
i
)
{
return
{
color
:
c
,
i
:
i
,
similar
:
[
i
]
}
});
var
similars
=
filteredResult
.
map
(
function
(
c
,
i
)
{
return
{
color
:
c
,
i
:
i
,
similar
:
[
i
]
}
}
);
// O^2 similarity search
for
(
var
i
=
0
,
_i
=
similars
.
length
;
i
<
_i
;
i
++
){
var
c1
=
similars
[
i
];
for
(
var
j
=
0
,
_j
=
similars
.
length
;
j
<
_j
;
j
++
){
if
(
i
===
j
)
if
(
i
===
j
)
continue
;
var
c2
=
similars
[
j
];
if
(
Math
.
abs
(
hsvDistance
(
c1
.
color
,
c2
.
color
))
<
similarColor
){
if
(
c1
.
similar
.
indexOf
(
j
)
===
-
1
){
if
(
Math
.
abs
(
labDistance
(
c1
.
color
,
c2
.
color
)
)
<
similarColor
){
if
(
c1
.
similar
.
indexOf
(
j
)
===
-
1
){
c1
.
similar
.
push
(
j
);
c2
.
similar
.
push
(
i
);
}
...
...
@@ -159,38 +407,35 @@ var extractColors = function( ctx, where, k, debug){
}
var
used
=
{};
var
different
=
similars
.
reduce
(
function
(
store
,
c
)
{
if
(
!
(
c
.
i
in
used
)
)
store
.
push
(
c
);
var
different
=
similars
.
reduce
(
function
(
store
,
c
)
{
if
(
!
(
c
.
i
in
used
)
)
store
.
push
(
c
);
for
(
var
i
=
0
,
_i
=
c
.
similar
.
length
;
i
<
_i
;
i
++
){
var
similarElement
=
c
.
similar
[
i
];
var
item
=
similars
[
similarElement
];
if
(
!
(
item
.
i
in
used
)
){
used
[
item
.
i
]
=
true
;
var
item
=
similars
[
similarElement
];
if
(
!
(
item
.
i
in
used
)
){
used
[
item
.
i
]
=
true
;
}
}
return
store
;
},
[]);
},
[]
);
if
(
debug
){
similars
,
result
}
filteredResult
=
different
.
map
(
function
(
item
)
{
filteredResult
=
different
.
map
(
function
(
item
)
{
return
item
.
color
;
});
}
);
return
filteredResult
.
map
(
function
(
color
)
{
return
{
color
:
color
,
distance
:
hsvDistance
(
color
,
filteredResult
[
0
])
};
}
).
filter
(
function
(
color
)
{
var
delta
=
Math
.
abs
(
color
.
distance
);
return
delta
<
0.0000001
||
delta
>
0.03
;
});
return
filteredResult
.
map
(
function
(
color
)
{
return
{
color
:
color
,
distance
:
labDistance
(
color
,
filteredResult
[
0
]
)
};
}
).
filter
(
function
(
color
)
{
var
delta
=
Math
.
abs
(
color
.
distance
);
return
delta
<
0.0000001
||
delta
>
15
;
}
);
};
var
colorSort
=
function
(
a
,
b
){
return
(
-
(
a
[
2
]
-
b
[
2
]))
+
(
-
(
a
[
1
]
-
b
[
1
])
/
2
)};
var
similarColor
=
0.05
;
var
similarColor
=
5
;
//
0.05;
var
abs
=
Math
.
abs
,
min
=
Math
.
min
;
var
hsvDistance
=
function
(
c1
,
c2
){
var
dh
=
min
(
abs
(
c2
[
0
]
-
c1
[
0
]
),
1
-
abs
(
c2
[
0
]
-
c1
[
0
]
)
),
...
...
@@ -213,11 +458,11 @@ function rgbToHex(r, g, b) {
return
((
r
<<
16
)
|
(
g
<<
8
)
|
b
).
toString
(
16
);
}
var
binds
=
[];
var
extractor
=
function
(
partName
,
ctx
,
from
,
k
,
debug
)
{
var
extractor
=
function
(
partName
,
ctx
,
from
,
k
,
production
)
{
extracting
++
;
var
colors
=
extractColors
(
ctx
,
from
,
k
,
debug
)
var
colors
=
extractColors
(
ctx
,
from
,
k
,
production
)
.
map
(
function
(
m
)
{
return
{
color
:
hsv
ToRgb
.
apply
(
null
,
m
.
color
).
map
(
function
(
a
){
return
a
|
0
}),
hsv
:
m
.
color
,
distance
:
m
.
distance
};
return
{
color
:
lab
ToRgb
.
apply
(
null
,
m
.
color
).
map
(
function
(
a
){
return
a
|
0
}),
hsv
:
m
.
color
,
distance
:
m
.
distance
};
});
binds
.
forEach
(
function
(
b
)
{
...
...
@@ -225,19 +470,39 @@ var extractor = function(partName, ctx, from, k, debug) {
});
binds
=
[];
if
(
production
){
D
.
div
({
cls
:
'colors'
,
renderTo
:
document
.
getElementById
(
partName
+
'-bg'
)
},
colors
.
map
(
function
(
m
){
return
D
.
div
({
style
:
'background:rgb('
+
m
.
color
.
join
(
','
)
+
');width:'
+
100
/
colors
.
length
+
'%'
,
cls
:
'color-preview'
},
'L: '
+
Math
.
floor
(
m
.
hsv
[
0
]),
D
.
h
(
'br'
),
'A: '
+
Math
.
round
(
m
.
hsv
[
1
]),
D
.
h
(
'br'
),
'B: '
+
Math
.
round
(
m
.
hsv
[
2
])
);
})
);
loadJSONcollection
(
partName
,
colors
);
return
;
}
return
D
.
div
({
cls
:
'colors'
},
colors
.
map
(
function
(
m
){
return
D
.
span
({
style
:
'background:rgb('
+
m
.
color
.
join
(
','
)
+
');'
,
cls
:
'color-preview'
},
'H: '
+
Math
.
floor
(
m
.
hsv
[
0
]
*
360
),
D
.
h
(
'br'
),
'L: '
+
Math
.
floor
(
m
.
hsv
[
0
]),
D
.
h
(
'br'
),
'A: '
+
Math
.
round
(
m
.
hsv
[
1
]),
D
.
h
(
'br'
),
'B: '
+
Math
.
round
(
m
.
hsv
[
2
])
/*'H: '+Math.floor(m.hsv[0]*360),D.h('br'),
'S: '+Math.round(m.hsv[1]*100)+'%', D.h('br'),
'V: '
+
Math
.
round
(
m
.
hsv
[
2
]
*
100
)
+
'%'
'V: '+Math.round(m.hsv[2]*100)+'%'
*/
);
}),
function
(
draw
)
{
getData
(
partName
,
function
(
res
){
var
b
=
store
.
sub
(
[
'threshold'
,
'maxCount'
],
function
(
threshold
,
maxCount
){
var
b
=
store
.
sub
(
[
'threshold'
,
'maxCount'
,
'maxThreshold'
],
function
(
threshold
,
maxCount
,
maxThreshold
){
var
list
=
[];
res
.
products
.
forEach
(
function
(
product
){
...
...
@@ -256,7 +521,7 @@ var extractor = function(partName, ctx, from, k, debug) {
colorName
:
variant
.
option1
,
img
:
variant
.
featured_image
&&
variant
.
featured_image
.
src
||
(
product
.
images
[
0
]
||
{}
).
src
,
sku
:
variant
.
option3
,
hsv
:
rgbTo
Hsv
(
r
,
g
,
b
)
hsv
:
rgbTo
Lab
(
r
,
g
,
b
)
}
);
}
);
}
);
...
...
@@ -265,28 +530,43 @@ var extractor = function(partName, ctx, from, k, debug) {
colors
.
map
(
function
(
clr
){
var
epsilon
=
threshold
;
var
matched
=
list
.
map
(
function
(
i
){
return
{
i
:
i
,
d
:
hsv
Distance
(
i
.
hsv
,
clr
.
hsv
),
c
:
clr
};
return
{
i
:
i
,
d
:
lab
Distance
(
i
.
hsv
,
clr
.
hsv
),
c
:
clr
};
}
)
.
filter
(
function
(
i
){
return
Math
.
max
(
0
,
Math
.
min
(
100
,
(
1
-
i
.
d
*
3
)
*
100
)
)
>=
t
hreshold
;
return
i
.
d
<=
maxT
hreshold
;
}
)
.
sort
(
function
(
a
,
b
){
return
a
.
d
-
b
.
d
;
}
);
var
allMatched
=
matched
.
slice
();
if
(
maxCount
===
0
)
return
matched
;
matched
=
allMatched
.
filter
(
function
(
a
)
{
return
a
.
d
<=
threshold
;
});
var
lastMatched
=
matched
;
while
(
matched
.
length
>
maxCount
){
epsilon
=
100
-
(
100
-
epsilon
)
/
3
*
2
;
var
m
=
0
,
step
=
0
;
while
(
matched
.
length
<
maxCount
){
step
++
;
epsilon
=
epsilon
+
0.25
;
matched
=
matched
.
filter
(
function
(
i
){
return
Math
.
max
(
0
,
Math
.
min
(
100
,
(
1
-
i
.
d
*
3
)
*
100
)
)
>=
epsilon
;
}
);
if
(
matched
.
length
===
0
){
matched
=
lastMatched
.
slice
(
0
,
maxCount
);
if
(
epsilon
>
maxThreshold
)
break
;
}
if
(
m
*
step
/
5
+
epsilon
>
maxThreshold
)
break
;
if
(
matched
.
length
&&
epsilon
>
(
threshold
+
maxThreshold
)
/
2
)
break
;
matched
=
allMatched
.
filter
(
function
(
i
){
return
i
.
d
<=
epsilon
;
}
);
m
=
Math
.
max
(
m
,
matched
.
length
);
lastMatched
=
matched
;
}
/*if(!matched.length>3){
...
...
@@ -298,7 +578,7 @@ var extractor = function(partName, ctx, from, k, debug) {
}else{
return matched.slice(0, 2);
}*/
return
matched
;
return
matched
.
slice
(
0
,
maxCount
)
;
}
)
).
filter
(
function
(
item
){
if
(
!
(
item
.
i
.
vid
in
used
)
){
used
[
item
.
i
.
vid
]
=
true
;
...
...
@@ -322,14 +602,14 @@ var extractor = function(partName, ctx, from, k, debug) {
D
.
div
(
{
cls
:
'cp2'
,
style
:
{
background
:
item
.
i
.
color
}
}
),
D
.
h
(
'img'
,
{
cls
:
'preview-img'
,
src
:
item
.
i
.
img
}
),
D
.
div
(
{
cls
:
'name'
},
item
.
i
.
title
),
D
.
div
(
{
cls
:
'accuracy'
},
(
Math
.
max
(
0
,
Math
.
min
(
100
,
(
1
-
item
.
d
*
3
)
*
100
)
)
).
toFixed
(
2
)
+
'%'
)
D
.
div
(
{
cls
:
'accuracy'
},
(
100
-
item
.
d
).
toFixed
(
2
)
+
'%'
)
)
}
)
)
)
);
}
);
console
.
log
(
b
)
//
console.log(b)
binds
.
push
(
b
);
});
...
...
examples/examples-browser/public/js/let_my_people_go.js
0 → 100644
View file @
0bbd229b
var
store
=
new
Store
({
threshold
:
75
,
maxCount
:
5
});
var
TINY_FACE_DETECTOR
=
1
;
var
SSD_MOBILENETV1
=
2
function
getCurrentFaceDetectionNet
()
{
selectedFaceDetector
=
TINY_FACE_DETECTOR
if
(
selectedFaceDetector
===
SSD_MOBILENETV1
)
{
return
faceapi
.
nets
.
ssdMobilenetv1
}
if
(
selectedFaceDetector
===
TINY_FACE_DETECTOR
)
{
return
faceapi
.
nets
.
tinyFaceDetector
}
}
function
isFaceDetectionModelLoaded
()
{
return
!!
getCurrentFaceDetectionNet
().
params
}
window
.
s0
=
224
;
var
canvas
=
document
.
getElementById
(
"chosen_img"
);
var
cc
=
canvas
.
getContext
(
"2d"
);
var
detection
=
document
.
getElementById
(
"detection"
);
var
detectionCtx
=
detection
.
getContext
(
"2d"
);
var
overlay
=
document
.
getElementById
(
"overlay"
);
var
overlayCC
=
overlay
.
getContext
(
"2d"
);
var
canvas_container
=
document
.
getElementById
(
"canvas_container"
);
var
img
=
new
Image
();
img
.
onload
=
function
()
{
console
.
log
(
this
,
'ghm'
);
// check if the picture is taken landscope.
if
(
img
.
width
>
img
.
height
)
{
// Change max width and max height depends on screen width.
if
(
screen
<
414
)
{
// for Mobile
imgSizeFit
(
img
,
256
,
300
);
}
else
{
imgSizeFit
(
img
,
640
,
480
);
}
}
else
{
// Change max width and max height depends on screen width.
if
(
screen
<
414
)
{
// for Mobile
imgSizeFit
(
img
,
256
,
450
);
}
else
{
imgSizeFit
(
img
,
480
,
640
);
}
}
cc
.
drawImage
(
img
,
0
,
0
,
canvas
.
width
,
canvas
.
height
);
doMatching
(
canvas
,
cc
);
};
// set Image src that user chose.
img
.
src
=
localStorage
.
getItem
(
"image_data"
);
function
imgSizeFit
(
img
,
maxWidth
,
maxHeight
)
{
var
ratio
=
Math
.
min
(
1
,
maxWidth
/
img
.
naturalWidth
,
maxHeight
/
img
.
naturalHeight
);
var
neww
=
img
.
naturalWidth
*
ratio
;
var
newh
=
img
.
naturalHeight
*
ratio
;
canvas_container
.
style
.
width
=
`
${
neww
}
px`
;
canvas
.
setAttribute
(
"width"
,
neww
);
canvas
.
setAttribute
(
"height"
,
newh
);
overlay
.
setAttribute
(
"width"
,
neww
);
overlay
.
setAttribute
(
"height"
,
newh
);
detection
.
setAttribute
(
"width"
,
neww
);
detection
.
setAttribute
(
"height"
,
newh
);
}
async
function
doMatching
(
el
,
ctx
)
{
var
inputSize
=
s0
;
var
scoreThreshold
=
0.4
;
if
(
!
isFaceDetectionModelLoaded
()){
await
getCurrentFaceDetectionNet
().
load
(
assetDir
);
await
faceapi
.
loadFaceLandmarkModel
(
assetDir
);
}
var
options
=
new
faceapi
.
TinyFaceDetectorOptions
(
{
inputSize
,
scoreThreshold
}
);
var
dims
=
{
width
:
640
,
height
:
480
};
detectionCtx
.
clearRect
(
0
,
0
,
dims
.
width
,
dims
.
height
);
if
(
img
.
width
/
dims
.
width
*
dims
.
height
>
img
.
height
){
var
h
=
img
.
height
/
(
img
.
width
/
dims
.
width
);
detectionCtx
.
drawImage
(
img
,
0
,
(
dims
.
height
-
h
)
/
2
,
dims
.
width
,
h
);
}
else
{
var
w
=
img
.
width
/
(
img
.
height
/
dims
.
height
);
detectionCtx
.
drawImage
(
img
,
(
dims
.
width
-
w
)
/
2
,
0
,
w
,
dims
.
height
);
}
let
result
=
await
faceapi
.
detectSingleFace
(
detection
,
options
).
withFaceLandmarks
();
//.withFaceDescriptor();
if
(
result
){
var
toPoint
=
function
(
p
)
{
return
new
Point
(
p
.
x
,
p
.
y
)
};
var
jaw
=
result
.
landmarks
.
getJawOutline
(),
nose
=
result
.
landmarks
.
getNose
(),
mouth
=
result
.
landmarks
.
getMouth
(),
leftBrow
=
result
.
landmarks
.
getLeftEyeBrow
(),
rightBrow
=
result
.
landmarks
.
getRightEyeBrow
(),
leftEye
=
result
.
landmarks
.
getLeftEye
(),
rightEye
=
result
.
landmarks
.
getRightEye
();
var
top
=
toPoint
(
nose
[
6
]).
lerp
(
nose
[
0
],
2
).
y
;
if
(
top
<
0
){
var
dtop
=
-
top
/
dims
.
height
;
detectionCtx
.
drawImage
(
img
,
dtop
*
dims
.
width
/
2
,
-
top
,
dims
.
width
-
dtop
*
dims
.
width
,
dims
.
height
+
top
);
detectionCtx
.
fillStyle
=
GetPixel
(
detectionCtx
,
4
,
4
);
detectionCtx
.
fillRect
(
0
,
0
,
dims
.
width
,
-
top
);
result
=
await
faceapi
.
detectSingleFace
(
detection
,
options
).
withFaceLandmarks
();
//.withFaceDescriptor();
if
(
!
result
){
return
setTimeout
(
f
,
300
);
}
jaw
=
result
.
landmarks
.
getJawOutline
(),
nose
=
result
.
landmarks
.
getNose
(),
mouth
=
result
.
landmarks
.
getMouth
(),
leftBrow
=
result
.
landmarks
.
getLeftEyeBrow
(),
rightBrow
=
result
.
landmarks
.
getRightEyeBrow
(),
leftEye
=
result
.
landmarks
.
getLeftEye
(),
rightEye
=
result
.
landmarks
.
getRightEye
();
}
overlayCC
.
clearRect
(
0
,
0
,
dims
.
width
,
dims
.
height
);
faceapi
.
draw
.
drawFaceLandmarks
(
overlay
,
faceapi
.
resizeResults
(
result
,
dims
)
);
overlayCC
.
fillStyle
=
'blue'
;
mouth
.
forEach
(
function
(
p
,
i
)
{
overlayCC
.
fillText
(
i
+
''
,
p
.
x
,
p
.
y
)
});
overlayCC
.
fillStyle
=
'red'
;
jaw
.
forEach
(
function
(
p
,
i
)
{
overlayCC
.
fillText
(
i
+
''
,
p
.
x
,
p
.
y
)
});
overlayCC
.
fillStyle
=
'yellow'
;
leftEye
.
forEach
(
function
(
p
,
i
)
{
overlayCC
.
fillText
(
i
+
''
,
p
.
x
,
p
.
y
)
});
overlayCC
.
fillStyle
=
'yellow'
;
rightEye
.
forEach
(
function
(
p
,
i
)
{
overlayCC
.
fillText
(
i
+
''
,
p
.
x
,
p
.
y
)
});
overlayCC
.
fillStyle
=
'red'
;
leftBrow
.
forEach
(
function
(
p
,
i
)
{
overlayCC
.
fillText
(
i
+
''
,
p
.
x
,
p
.
y
)
});
overlayCC
.
fillStyle
=
'red'
;
rightBrow
.
forEach
(
function
(
p
,
i
)
{
overlayCC
.
fillText
(
i
+
''
,
p
.
x
,
p
.
y
)
});
overlayCC
.
fillStyle
=
'blue'
;
nose
.
forEach
(
function
(
p
,
i
)
{
overlayCC
.
fillText
(
i
+
''
,
p
.
x
,
p
.
y
)
});
var
faceMarks
=
new
FaceMarks
(
result
.
landmarks
);
var
cheek
=
faceMarks
.
marks
.
cheek
;
var
ratio
=
(
cheek
.
left
.
base
[
0
].
distance
(
cheek
.
left
.
base
[
1
])
/
cheek
.
right
.
base
[
0
].
distance
(
cheek
.
right
.
base
[
1
]));
var
bad
=
2
;
var
lips
=
[];
lips
=
lips
.
concat
(
faceMarks
.
marks
.
lips
.
top
);
lips
=
lips
.
concat
(
faceMarks
.
marks
.
lips
.
bottom
);
var
browsSearchArea
=
[];
browsSearchArea
.
push
([
toPoint
(
leftBrow
[
4
]),
toPoint
(
leftEye
[
2
]).
middle
(
toPoint
(
leftBrow
[
4
])),
toPoint
(
leftBrow
[
1
])
]);
browsSearchArea
.
push
([
toPoint
(
rightBrow
[
0
]),
toPoint
(
rightEye
[
1
]).
middle
(
toPoint
(
rightBrow
[
0
])),
toPoint
(
rightBrow
[
3
])
]);
var
eyes
=
[];
if
(
ratio
>
bad
){
cheek
=
[
cheek
.
left
.
base
,
cheek
.
left
.
bonus1
,
cheek
.
left
.
bonus2
];
browsSearchArea
.
pop
();
eyes
=
[
faceMarks
.
marks
.
eyes
.
left
.
t1
,
faceMarks
.
marks
.
eyes
.
left
.
t2
,
faceMarks
.
marks
.
eyes
.
left
.
t3
,
faceMarks
.
marks
.
eyes
.
left
.
t4
];
}
else
if
(
ratio
<
1
/
bad
){
cheek
=
[
cheek
.
right
.
base
,
cheek
.
right
.
bonus1
,
cheek
.
right
.
bonus2
];
browsSearchArea
.
shift
();
eyes
=
[
faceMarks
.
marks
.
eyes
.
right
.
t1
,
faceMarks
.
marks
.
eyes
.
right
.
t2
,
faceMarks
.
marks
.
eyes
.
right
.
t3
,
faceMarks
.
marks
.
eyes
.
right
.
t4
];
}
else
{
cheek
=
[
cheek
.
left
.
base
,
cheek
.
left
.
bonus1
,
cheek
.
left
.
bonus2
,
cheek
.
right
.
base
,
cheek
.
right
.
bonus1
,
cheek
.
right
.
bonus2
];
eyes
=
[
faceMarks
.
marks
.
eyes
.
left
.
t1
,
faceMarks
.
marks
.
eyes
.
left
.
t2
,
faceMarks
.
marks
.
eyes
.
left
.
t3
,
faceMarks
.
marks
.
eyes
.
left
.
t4
,
faceMarks
.
marks
.
eyes
.
right
.
t1
,
faceMarks
.
marks
.
eyes
.
right
.
t2
,
faceMarks
.
marks
.
eyes
.
right
.
t3
,
faceMarks
.
marks
.
eyes
.
right
.
t4
];
}
var
drawPoly
=
function
(
poly
)
{
overlayCC
.
beginPath
();
for
(
var
i
=
0
,
_i
=
poly
.
length
;
i
<=
_i
;
i
++
){
if
(
i
===
0
){
overlayCC
.
moveTo
(
poly
[
i
].
x
,
poly
[
i
].
y
);
}
else
{
overlayCC
.
lineTo
(
poly
[
i
%
_i
].
x
,
poly
[
i
%
_i
].
y
);
}
}
overlayCC
.
stroke
();
};
cheek
.
forEach
(
drawPoly
);
lips
.
forEach
(
drawPoly
);
browsSearchArea
.
forEach
(
drawPoly
);
eyes
.
forEach
(
drawPoly
);
//document.getElementById('ccolors').getContext('2d').clearRect(0,0,120,480);
extracting
=
-
1
;
extractor
(
'lips'
,
detectionCtx
,
lips
,
5
,
1
);
extractor
(
'blush'
,
detectionCtx
,
cheek
,
3
,
1
);
extractor
(
'brows'
,
detectionCtx
,
browsSearchArea
,
2
,
1
);
extractor
(
'eyes'
,
detectionCtx
,
eyes
,
6
,
1
);
}
document
.
getElementById
(
"loading"
).
classList
.
add
(
"d-none"
);
// make loading gif disappear
document
.
getElementById
(
"color_matching_products-container"
).
style
.
display
=
'block'
;
}
function
matchingProductsFormat
(
product
,
index
)
{
// If the variants doesn't have Image src
var
out_put
=
""
;
out_put
=
`<div id="color_matching_
${
product
.
pid
}
" class="grid__item grid-product small--one-half cd-medium-up--one-third grid-product__has-quick-shop aos-init aos-animate" data-aos="row-of-3">
<div class="grid-product__content">
<a class="grid-product__link " href="/products/
${
product
.
p
.
handle
}
" target="_blank">
<div class="grid-product__image-mask">
<div class="grid__image-ratio grid__image-ratio--portrait lazyloaded" data-bgset="
${
product
.
img
}
" style="background-image: url(
${
product
.
img
}
);"">
</div>
</div>
<div class="grid-product__meta">
<div class="grid-product__title grid-product__title--body">
${
product
.
title
}
</div>
<div class="grid-product__vendor">
${
product
.
p
.
vendor
}
</div>
<div class="grid-product__price">$
${
product
.
v
.
price
}
</div>
</div>
</a>
<!-- ============= add custom button ( quick view, love, add to cart ) =============-->
<div class="quick-product__menus quick-product__btn cssgrid w-100">
<!-- add wishlist -->
<div class="d-flex quick-product__icon-bg">
<div class="ssw-faveiticon sswfaveicon
${
product
.
pid
}
">
<i data-product-id="
${
product
.
pid
}
" data-count="0" class="ssw-icon-heart-o ssw-fave-icon ssw-wishlist-element ssw-not-synch" title="{{ 'socialshopwave.fave' | t }}" data-params="{'product_id':'
${
product
.
pid
}
','event':'fave_button','page':'product_profile'}"></i>
<span class="faves-count">...</span>
</div>
</div>
<!-- end of add wishlist -->
<div aria-expanded class="quick-product__btn js-modal-open-quick-modal-
${
product
.
pid
}
d-flex quick-product__icon-bg quick-product__view" data-product-id="
${
product
.
pid
}
">
<a href="/products/
${
product
.
p
.
handle
}
" target="_blank" class="w-100 h-100">
<span class="quick-product__label d-flex align-self-center quick-try-on w-100 h-100"></span>
</a>
</div>
<form action="/cart/add" class="d-flex quick-product__icon-bg" id="product-form-
${
product
.
pid
}
" method="post">
<input name="id" type="hidden" value="
${
product
.
vid
}
">
<div>
<button class="quick_add_cart_icon d-flex quick-product__icon-bg" name="add" type="submit">
<span class="quick_add_cart_icon_span"></span>
</button>
</div>
</form>
</div>
<!-- ============= end of custom button =============-->
</div>
<div class="grid-product__colors grid-product__colors--
${
product
.
pid
}
">
<div id="color_squares_container-
${
product
.
pid
}
" class="d-flex">
</div>
</div>
</div>
</div>`
;
return
out_put
;
}
function
colorSquareFormat
(
product
,
color
,
showSameColorName
)
{
var
output
=
""
;
var
count
=
0
;
var
LIMIT_SHOWING_COLOR_SWATCHES
=
5
;
for
(
let
i
=
0
;
i
<
product
.
variants
.
length
;
i
++
)
{
const
variant
=
product
.
variants
[
i
];
const
option2_value
=
variant
.
option2
;
const
option2_name
=
closest_color
(
option2_value
,
showSameColorName
);
if
(
typeof
color
!=
"string"
)
{
for
(
let
i
=
0
;
i
<
color
.
length
;
i
++
)
{
const
eye_cl
=
color
[
i
];
if
(
eye_cl
==
option2_name
)
{
count
++
;
if
(
count
<
LIMIT_SHOWING_COLOR_SWATCHES
)
{
output
+=
`<button class="color-swatch color-swatch--small color-swatch--cabbage-rose color-swatch--with-image" data-variant-id="
${
variant
.
id
}
" style="background-color:
${
option2_value
}
;"></button>`
;
}
}
}
}
else
{
if
(
color
==
option2_name
)
{
count
++
;
if
(
count
<
LIMIT_SHOWING_COLOR_SWATCHES
)
{
output
+=
`<button class="color-swatch color-swatch--small color-swatch--cabbage-rose color-swatch--with-image" data-variant-id="
${
variant
.
id
}
" style="background-color:
${
option2_value
}
;"></button>`
;
}
}
}
}
if
(
count
>=
LIMIT_SHOWING_COLOR_SWATCHES
)
{
output
+=
` +
${
count
-
LIMIT_SHOWING_COLOR_SWATCHES
+
1
}
`
;
}
return
output
;
}
function
miloAnswer
(
bool
)
{
var
milo_answer
=
""
;
if
(
bool
)
{
milo_answer
=
"Here are products matching the colours that you are looking for. Try them on!"
;
document
.
getElementById
(
"milo-answer-text"
).
innerText
=
milo_answer
;
}
else
{
milo_answer
=
`<button class="bg-yellow option_btn"><a href="/pages/color-detection" class="text-white">Choose another file</a></button>`
;
document
.
getElementById
(
"milo-answer-text"
).
innerHTML
=
milo_answer
;
document
.
getElementById
(
"color_results_holder"
).
classList
.
add
(
"d-none"
);
}
}
function
loadJSONcollection
(
fpart
,
colors
)
{
//}, html_cl, showSameColorName) {
var
xmlhttp
=
new
XMLHttpRequest
();
var
url
=
`/collections/cd-
${
fpart
}
-results/products.json?limit=250?page=1`
;
xmlhttp
.
open
(
"GET"
,
url
,
true
);
try
{
xmlhttp
.
send
();
xmlhttp
.
onreadystatechange
=
function
()
{
if
(
this
.
readyState
==
4
&&
this
.
status
==
200
)
{
var
products
=
JSON
.
parse
(
this
.
responseText
);
colorMatchProductChecker
(
products
,
fpart
,
colors
);
miloAnswer
(
true
);
}
};
}
catch
(
err
)
{
// instead of onerror
alert
(
"Ajax Error. Please check your Internet connection."
);
}
function
colorMatchProductChecker
(
res
,
fp
,
colors
)
{
var
threshold
=
75
,
maxCount
=
5
;
var
list
=
[];
res
.
products
.
forEach
(
function
(
product
){
product
.
variants
.
forEach
(
function
(
variant
){
var
color
=
variant
.
option2
.
substr
(
1
),
r
=
parseInt
(
color
[
0
]
+
color
[
1
],
16
),
g
=
parseInt
(
color
[
2
]
+
color
[
3
],
16
),
b
=
parseInt
(
color
[
4
]
+
color
[
4
],
16
);
list
.
push
(
{
v
:
variant
,
p
:
product
,
pid
:
product
.
id
,
vid
:
variant
.
id
,
description
:
product
.
body_html
,
title
:
product
.
title
,
color
:
variant
.
option2
,
colorName
:
variant
.
option1
,
img
:
variant
.
featured_image
&&
variant
.
featured_image
.
src
||
(
product
.
images
[
0
]
||
{}
).
src
||
"https://cdn.shopify.com/s/files/1/0275/8036/6900/files/2_Main_Vertical_Transparent.png?v=1575867010"
,
sku
:
variant
.
option3
,
hsv
:
rgbToHsv
(
r
,
g
,
b
)
}
);
}
);
}
);
var
used
=
{};
var
all
=
[].
concat
.
apply
(
[],
colors
.
map
(
function
(
clr
){
var
epsilon
=
threshold
;
var
matched
=
list
.
map
(
function
(
i
){
return
{
i
:
i
,
d
:
hsvDistance
(
i
.
hsv
,
clr
.
hsv
),
c
:
clr
};
}
)
.
filter
(
function
(
i
){
return
Math
.
max
(
0
,
Math
.
min
(
100
,
(
1
-
i
.
d
*
3
)
*
100
)
)
>=
threshold
;
}
)
.
sort
(
function
(
a
,
b
){
return
a
.
d
-
b
.
d
;
}
);
if
(
maxCount
===
0
)
return
matched
;
var
lastMatched
=
matched
;
while
(
matched
.
length
>
maxCount
){
epsilon
=
100
-
(
100
-
epsilon
)
/
3
*
2
;
matched
=
matched
.
filter
(
function
(
i
){
return
Math
.
max
(
0
,
Math
.
min
(
100
,
(
1
-
i
.
d
*
3
)
*
100
)
)
>=
epsilon
;
}
);
if
(
matched
.
length
===
0
){
matched
=
lastMatched
.
slice
(
0
,
maxCount
);
break
;
}
lastMatched
=
matched
;
}
/*if(!matched.length>3){
matched = matched.f;
return matched;
}*/
/*if(matched[0].d<0.02){
return matched.slice( 0, 1 )
}else{
return matched.slice(0, 2);
}*/
return
matched
;
}
)
).
filter
(
function
(
item
){
if
(
!
(
item
.
i
.
vid
in
used
)
){
used
[
item
.
i
.
vid
]
=
true
;
return
true
;
}
return
false
;
}
);
var
count
=
all
.
length
;
all
.
map
(
function
(
item
){
document
.
getElementById
(
`
${
fp
}
-result`
)
.
insertAdjacentHTML
(
"beforeend"
,
matchingProductsFormat
(
item
.
i
)
);
/*document.getElementById(
`color_squares_container-${product.id}`
).innerHTML = colorSquareFormat(
product,
cl,
showSameColorName
);*/
}
);
/*
var count = 0;
// reset
document.getElementById(`${fp}-result`).innerHTML = "";
for (let product_i = 0; product_i < data.products.length; product_i++) {
const product = data.products[product_i];
for (
let variant_i = 0;
variant_i < product.variants.length;
variant_i++
) {
const variant = product.variants[variant_i];
const option2_value = variant.option2;
const option2_name = closest_color(
option2_value,
showSameColorName
);
// if eye's color arr
if (typeof cl != "string") {
for (let cl_i = 0; cl_i < cl.length; cl_i++) {
const eye_cl = cl[cl_i];
if (eye_cl == option2_name) {
count++;
document
.getElementById(`${fp}-result`)
.insertAdjacentHTML(
"beforeend",
matchingProductsFormat(product, variant_i)
);
document.getElementById(
`color_squares_container-${product.id}`
).innerHTML = colorSquareFormat(
product,
cl,
showSameColorName
);
cl_i = cl.length - 1;
variant_i = product.variants.length - 1;
}
}
} else {
if (cl == option2_name) {
count++;
document
.getElementById(`${fp}-result`)
.insertAdjacentHTML(
"beforeend",
matchingProductsFormat(product, variant_i)
);
document.getElementById(
`color_squares_container-${product.id}`
).innerHTML = colorSquareFormat(
product,
cl,
showSameColorName
);
variant_i = product.variants.length - 1;
}
}
}
}*/
var
showSameColorName
=
true
;
var
option_button_out
=
""
;
var
product_output
=
""
;
// No matching products
json_FaceDetectionResults
=
count
;
if
(
count
===
0
)
{
product_output
+=
"<span style='color: darkgrey;'>no match...</span>"
;
document
.
getElementById
(
`
${
fp
}
-result`
).
innerHTML
=
product_output
;
}
else
if
(
showSameColorName
)
{
// show similar or close color products
option_button_out
+=
`<p class="milo-text text-center">Do you want to see products of close colours?
<br>The may suit you better.</p>
<div class="d-flex jc-sb">
<button class="text-white bg-yellow option_btn" onclick="setJSON(false)">Yes, show me.</button>
<button class="bg-black option_btn"><a href="/pages/color-detection" class="text-white">No, go back.</a></button>
</div>`
;
document
.
getElementById
(
"cd_option_button_container"
).
innerHTML
=
option_button_out
;
}
else
if
(
!
showSameColorName
)
{
// back to same color products result or back to initial page.
option_button_out
+=
`<div class="d-flex jc-sb">
<button class="text-white bg-yellow option_btn" onclick="setJSON(true)">Back</button>
<button class="bg-black option_btn"><a href="/pages/color-detection" class="text-white">Back to Miro</a></button>
</div>`
;
document
.
getElementById
(
"cd_option_button_container"
).
innerHTML
=
option_button_out
;
}
else
{
return
;
}
}
}
var
json_FaceDetectionResults
=
false
;
function
setJSON
(
bool
)
{
document
.
getElementById
(
"loading"
).
classList
.
add
(
"d-none"
);
// make loading gif disappear
document
.
getElementById
(
"color_results_holder"
).
classList
.
remove
(
"d-none"
);
// if the face detection success
if
(
json_FaceDetectionResults
)
{
//setResultsAndJSON(json_FaceDetectionResults, bool);
document
.
getElementById
(
"color_matching_products-container"
).
style
=
"block"
;
}
else
{
// if face detection failed,
document
.
getElementById
(
"color_results_holder"
).
classList
.
add
(
"d-none"
);
}
}
\ No newline at end of file
examples/examples-browser/views/demo.html
View file @
0bbd229b
...
...
@@ -128,8 +128,9 @@
</div>
<script>
var
store
=
new
Store
({
threshold
:
60
,
maxCount
:
5
threshold
:
0.25
,
maxCount
:
5
,
maxThreshold
:
15
});
...
...
@@ -409,13 +410,12 @@ var videoEl = inputVideo;
),
block
(
'Eyes'
,
extractor
(
'eyes'
,
ctx2
,
eyes
,
6
,
1
)
extractor
(
'eyes'
,
ctx2
,
eyes
,
6
)
)
]);
//ctx2.putImageData(imageData, minX, minY);
// debugger;
...
...
@@ -474,6 +474,9 @@ var videoEl = inputVideo;
),
D
.
h
(
'label'
,
{},
'Threshold: '
,
D
.
h
(
Input
,
{
bind
:
store
.
bind
(
'threshold'
)})
),
D
.
h
(
'label'
,
{},
'maxThreshold: '
,
D
.
h
(
Input
,
{
bind
:
store
.
bind
(
'maxThreshold'
)})
)
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment