1 /* 2 Copyright (c) 2013-2021 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 /** 30 * Filters that remove background from images 31 * 32 * Copyright: Timur Gafarov 2013-2021. 33 * License: $(LINK2 boost.org/LICENSE_1_0.txt, Boost License 1.0). 34 * Authors: Timur Gafarov 35 */ 36 module dlib.image.filters.chromakey; 37 38 import dlib.math.utils; 39 import dlib.image.image; 40 import dlib.image.color; 41 import dlib.image.hsv; 42 import dlib.math.vector; 43 import dlib.math.utils; 44 45 /// Euclidean distance chroma key 46 SuperImage chromaKeyEuclidean( 47 SuperImage img, 48 SuperImage outp, 49 Color4f keyColor, 50 float minDist, 51 float maxDist) 52 { 53 SuperImage res; 54 if (outp) 55 res = outp; 56 else 57 res = img.dup; 58 59 foreach(y; img.col) 60 foreach(x; img.row) 61 { 62 Color4f col = img[x, y]; 63 64 Color4f delta = col - keyColor; 65 float distSqr = dot(delta, delta); 66 col.a = clamp( 67 (distSqr - minDist) / (maxDist - minDist), 68 0.0f, 1.0f); 69 res[x, y] = col; 70 } 71 72 return res; 73 } 74 75 /// ditto 76 SuperImage chromaKeyEuclidean( 77 SuperImage img, 78 Color4f keyColor, 79 float minDist, 80 float maxDist) 81 { 82 return chromaKeyEuclidean(img, null, keyColor, minDist, maxDist); 83 } 84 85 /// HSV selective scale chroma key 86 SuperImage chromaKey( 87 SuperImage img, 88 SuperImage outp, 89 float hue, 90 float hueToleranceMin = -20.0f, 91 float hueToleranceMax = 20.0f, 92 float satThres = 0.2f, 93 float valThres = 0.3f) 94 { 95 SuperImage res; 96 if (outp) 97 res = outp; 98 else 99 res = img.dup; 100 101 foreach(x; 0..img.width) 102 foreach(y; 0..img.height) 103 { 104 Color4f col = res[x, y]; 105 ColorHSVAf hsva = ColorHSVAf(col); 106 107 hsva.selectiveScale( 108 hue, 109 HSVAChannel.A, 110 0.0f, 111 false, 112 hueToleranceMin, 113 hueToleranceMax, 114 satThres, 115 valThres); 116 117 res[x, y] = hsva.rgba; 118 } 119 120 return res; 121 } 122 123 /// ditto 124 SuperImage chromaKey( 125 SuperImage img, 126 float hue, 127 float hueToleranceMin = -20.0f, 128 float hueToleranceMax = 20.0f, 129 float satThres = 0.2f, 130 float valThres = 0.3f) 131 { 132 return chromaKey(img, null, hue, hueToleranceMin, hueToleranceMax, satThres, valThres); 133 } 134 135 /// Turns image into b&w where only one color left, using HSV selective scale 136 SuperImage colorPass( 137 SuperImage img, 138 SuperImage outp, 139 float hue, 140 float hueToleranceMin = -20.0f, 141 float hueToleranceMax = 20.0f, 142 float satThres = 0.2f, 143 float valThres = 0.3f) 144 in 145 { 146 assert (img.data.length); 147 } 148 do 149 { 150 SuperImage res; 151 if (outp) 152 res = outp; 153 else 154 res = img.dup; 155 156 foreach(y; 0..img.height) 157 foreach(x; 0..img.width) 158 { 159 Color4f col = res[x, y]; 160 ColorHSVAf hsva = ColorHSVAf(col); 161 hsva.selectiveScale( 162 hue, 163 HSVAChannel.S, 164 0.0f, 165 true, 166 hueToleranceMin, 167 hueToleranceMax, 168 satThres, 169 valThres); 170 171 res[x, y] = hsva.rgba; 172 } 173 174 return res; 175 } 176 177 /// ditto 178 SuperImage colorPass( 179 SuperImage img, 180 float hue, 181 float hueToleranceMin = -20.0f, 182 float hueToleranceMax = 20.0f, 183 float satThres = 0.2f, 184 float valThres = 0.3f) 185 { 186 return colorPass(img, null, hue, hueToleranceMin, hueToleranceMax, satThres, valThres); 187 } 188 189 private: 190 191 void selectiveScale(ref ColorHSVAf col, 192 float hue, 193 HSVAChannel chan, 194 float scale, 195 bool inverse, 196 float hueToleranceMin = -20.0f, 197 float hueToleranceMax = 20.0f, 198 float satThres = 0.2f, 199 float valThres = 0.3f) 200 { 201 while (hue >= 360.0f) 202 hue -= 360.0f; 203 while (hue < 0.0f) 204 hue += 360.0f; 205 206 if (col.hueInRange(hue, hueToleranceMin, hueToleranceMax) 207 && col.s > satThres 208 && col.v > valThres) 209 { 210 if (!inverse) 211 col.arrayof[chan] *= scale; 212 } 213 else 214 { 215 if (inverse) 216 col.arrayof[chan] *= scale; 217 } 218 }