From e32e2f1f3c43df09c1a7c995da5f29483b51a592 Mon Sep 17 00:00:00 2001 From: Aleksandra Zhuravleva Date: Fri, 8 Nov 2019 16:22:07 +0200 Subject: [PATCH] [Color segmentation] Add sliders for hue, saturation and value (brightness) --- samples/css/base.css | 4 +++- samples/css/settings.css | 25 +++++++++++++++----- samples/funnyHats/js/index.js | 2 +- samples/invisibilityCloak/index.html | 31 ++++++++++++++++++++++++ samples/invisibilityCloak/index.js | 35 ++++++++++++++++++---------- 5 files changed, 77 insertions(+), 20 deletions(-) diff --git a/samples/css/base.css b/samples/css/base.css index f4c6ab5..ddeb6a4 100644 --- a/samples/css/base.css +++ b/samples/css/base.css @@ -19,7 +19,9 @@ body { } .stats-settings, .threads-control, .jitter-limit, .edge-error, -.downscale-level, .threshold-block-size, .threshold-offset, .demo-state { +.downscale-level, .threshold-block-size, .threshold-offset, .demo-state, +.lower-hue-control, .upper-hue-control, .lower-saturation-control, +.upper-saturation-control, .lower-value-control, .upper-value-control { padding: 10px; width: 100%; border-bottom: dotted silver 1px; diff --git a/samples/css/settings.css b/samples/css/settings.css index 37e1ad3..4184fb1 100644 --- a/samples/css/settings.css +++ b/samples/css/settings.css @@ -78,7 +78,8 @@ display: block; position: relative; } -#jitterLimit, #edgeError, #thresholdBlockSize, #thresholdOffset { +#jitterLimit, #edgeError, #thresholdBlockSize, #thresholdOffset, +#lowerHue, #upperHue, #lowerSaturation, #upperSaturation, #lowerValue, #upperValue { width: 130px; } #downscaleLevel { @@ -89,7 +90,8 @@ } .settings-bar input[type=range], #jitterLimit, #edgeError, #downscaleLevel, -#thresholdBlockSize,#thresholdOffset { +#thresholdBlockSize,#thresholdOffset, +#lowerHue, #upperHue, #lowerSaturation, #upperSaturation, #lowerValue, #upperValue { display: block; -webkit-appearance: none; margin: 7px 2px; @@ -99,7 +101,9 @@ } .settings-bar input[type=range]:focus, #jitterLimit:focus, #edgeError:focus, #downscaleLevel:focus, -#thresholdBlockSize:focus, #thresholdOffset:focus { +#thresholdBlockSize:focus, #thresholdOffset:focus, +#lowerHue:focus, #upperHue:focus, #lowerSaturation:focus, +#upperSaturation:focus, #lowerValue:focus, #upperValue:focus { outline: none; } .settings-bar input[type=range]::-webkit-slider-runnable-track, @@ -107,7 +111,10 @@ #edgeError::-webkit-slider-runnable-track, #downscaleLevel::-webkit-slider-runnable-track, #thresholdBlockSize::-webkit-slider-runnable-track, -#thresholdOffset::-webkit-slider-runnable-track { +#thresholdOffset::-webkit-slider-runnable-track, +#lowerHue::-webkit-slider-runnable-track, #upperHue::-webkit-slider-runnable-track, +#lowerSaturation::-webkit-slider-runnable-track, #upperSaturation::-webkit-slider-runnable-track, +#lowerValue::-webkit-slider-runnable-track, #upperValue::-webkit-slider-runnable-track { width: 100%; height: 4px; background: white; @@ -121,7 +128,10 @@ #edgeError::-webkit-slider-thumb, #downscaleLevel::-webkit-slider-thumb, #thresholdBlockSize::-webkit-slider-thumb, -#thresholdOffset::-webkit-slider-thumb { +#thresholdOffset::-webkit-slider-thumb, +#lowerHue::-webkit-slider-thumb, #upperHue::-webkit-slider-thumb, +#lowerSaturation::-webkit-slider-thumb, #upperSaturation::-webkit-slider-thumb, +#lowerValue::-webkit-slider-thumb, #upperValue::-webkit-slider-thumb { width: 9px; height: 20px; -webkit-appearance: none; @@ -137,7 +147,10 @@ #edgeError:focus::-webkit-slider-runnable-track, #downscaleLevel:focus::-webkit-slider-runnable-track, #thresholdBlockSize:focus::-webkit-slider-runnable-track, -#thresholdOffset:focus::-webkit-slider-runnable-track { +#thresholdOffset:focus::-webkit-slider-runnable-track, +#lowerHue:focus::-webkit-slider-runnable-track, #upperHue:focus::-webkit-slider-runnable-track, +#lowerSaturation:focus::-webkit-slider-runnable-track, #upperSaturation:focus::-webkit-slider-runnable-track, +#lowerValue:focus::-webkit-slider-runnable-track, #upperValue:focus::-webkit-slider-runnable-track { background: white; } @media screen and (max-width: 960px) { diff --git a/samples/funnyHats/js/index.js b/samples/funnyHats/js/index.js index 9e2b52f..251d00e 100644 --- a/samples/funnyHats/js/index.js +++ b/samples/funnyHats/js/index.js @@ -20,7 +20,7 @@ const imageHeight = 240; let nImagesLoaded = 0; // NOTE! Update this value if you add or remove files // from hatsData and glassesData in ui.js. -const N_IMAGES = 34; +const N_IMAGES = 33; function initOpencvObjects() { diff --git a/samples/invisibilityCloak/index.html b/samples/invisibilityCloak/index.html index b58fcb2..506cfd1 100644 --- a/samples/invisibilityCloak/index.html +++ b/samples/invisibilityCloak/index.html @@ -51,6 +51,37 @@ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
diff --git a/samples/invisibilityCloak/index.js b/samples/invisibilityCloak/index.js index 9c8aca5..cdc2797 100644 --- a/samples/invisibilityCloak/index.js +++ b/samples/invisibilityCloak/index.js @@ -13,8 +13,6 @@ let canvasInputCtx = null; let src = null; let background = null; let dst = null; -let lowerRedRange = null; -let upperRedRange = null; // Camera parameters are not stable when the camera is just getting started. // So we execute a loop where we capture background and use the last frame @@ -26,19 +24,32 @@ function initOpencvObjects() { src = new cv.Mat(video.height, video.width, cv.CV_8UC4); background = new cv.Mat(video.height, video.width, cv.CV_8UC4); dst = new cv.Mat(); +} +function inRange(hsv, mask) { // In OpenCV, Hue range is [0,179], Saturation range is [0,255] - // and Value range is [0,255]. We use 0-33 range for blue color, - // 100-255 for saturation and 70-255 for brigtness. - lowerRedRange = new cv.Mat(video.height, video.width, cv.CV_8UC3, - new cv.Scalar(0, 100, 70, 255)); - upperRedRange = new cv.Mat(video.height, video.width, cv.CV_8UC3, - new cv.Scalar(33, 255, 255, 255)); + // and Value range is [0,255]. We use 0-33 range for BLUE color, + // 100-255 for saturation and 70-255 for brigtness as default settings. + + let lh = parseInt(document.getElementById('lowerHue').value); + let uh = parseInt(document.getElementById('upperHue').value); + let ls = parseInt(document.getElementById('lowerSaturation').value); + let us = parseInt(document.getElementById('upperSaturation').value); + let lv = parseInt(document.getElementById('lowerValue').value); + let uv = parseInt(document.getElementById('upperValue').value); + + let lowerRange = new cv.Mat(video.height, video.width, cv.CV_8UC3, + new cv.Scalar(lh, ls, lv, 255)); + let upperRange = new cv.Mat(video.height, video.width, cv.CV_8UC3, + new cv.Scalar(uh, us, uv, 255)); + + cv.inRange(hsv, lowerRange, upperRange, mask); + + lowerRange.delete(); upperRange.delete(); } function deleteOpencvObjects() { src.delete(); background.delete(); dst.delete(); - lowerRedRange.delete(); upperRedRange.delete(); } function completeStyling() { @@ -69,7 +80,7 @@ function captureBackground() { } function removeBlueColor(source, destination) { - let hsv = new cv.Mat(); + let hsv = new cv.Mat(video.height, video.width, cv.CV_8UC3); let mask = new cv.Mat(); let maskInv = new cv.Mat(); let sourceResult = new cv.Mat(); @@ -79,8 +90,8 @@ function removeBlueColor(source, destination) { // HSV - Hue (color information), Saturation (intensity), Value (brightness). cv.cvtColor(source, hsv, cv.COLOR_BGR2HSV); - // Apply lower and upper boundary of a blue color to inRange filter. - cv.inRange(hsv, lowerRedRange, upperRedRange, mask); + // Apply lower and upper boundaries of HSV channels to inRange filter. + inRange(hsv, mask); // Dilation increases area of filtered object. let kernel = cv.Mat.ones(3, 3, cv.CV_32F);