diff --git a/cartoon/LICENSE b/cartoon/LICENSE new file mode 100644 index 0000000..22c130a --- /dev/null +++ b/cartoon/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Vladimir Mandic + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/cartoon/whitebox.bin b/cartoon/whitebox.bin new file mode 100644 index 0000000..e88b528 Binary files /dev/null and b/cartoon/whitebox.bin differ diff --git a/cartoon/whitebox.json b/cartoon/whitebox.json new file mode 100644 index 0000000..192aab0 --- /dev/null +++ b/cartoon/whitebox.json @@ -0,0 +1,136 @@ +{ + "format": "graph-model", + "generatedBy": "https://github.com/SystemErrorWang/White-box-Cartoonization", + "convertedBy": "https://github.com/vladmandic", + "signature": + { + "inputs": + { + "input": {"name":"input:0","dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"3"}]}} + }, + "outputs": + { + "add_1": {"name":"add_1:0","dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"3"}]}} + } + }, + "modelTopology": + { + "node": + [ + {"name":"depthwise_5/filter_in","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"3"},{"size":"1"}]}}}}}, + {"name":"ConstantFolding/truediv_5_recip","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"1"}]}}}}}, + {"name":"depthwise_3/filter_in","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"3"},{"size":"1"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"ConstantFolding/truediv_2_recip","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"1"}]}}}}}, + {"name":"generator/block_3/conv1/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_3/conv1/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}}}}, + {"name":"generator/block_3/conv2/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}}}}, + {"name":"generator/block_3/conv2/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}}}}, + {"name":"generator/block_2/conv1/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_2/conv1/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}}}}, + {"name":"generator/block_2/conv2/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}}}}, + {"name":"generator/block_2/conv2/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}}}}, + {"name":"generator/block_1/conv1/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_1/conv1/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_1/conv2/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}}}}, + {"name":"generator/block_1/conv2/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_0/conv1/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_0/conv1/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}}}}, + {"name":"generator/block_0/conv2/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"128"}]}}}}}, + {"name":"generator/block_0/conv2/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_3/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"64"},{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_3/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_4/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"64"},{"size":"128"}]}}}}}, + {"name":"generator/Conv_4/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"128"}]}}}}}, + {"name":"generator/Conv_5/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"128"},{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_5/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/ResizeBilinear/size","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_INT32","tensorShape":{"dim":[{"size":"2"}]}}},"dtype":{"type":"DT_INT32"}}}, + {"name":"generator/Conv_1/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"32"},{"size":"32"}]}}}}}, + {"name":"generator/Conv_1/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}}}}, + {"name":"generator/Conv_2/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"32"},{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_2/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_6/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"64"},{"size":"64"}]}}}}}, + {"name":"generator/Conv_6/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"64"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_7/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"64"},{"size":"32"}]}}}}}, + {"name":"generator/Conv_7/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}}}}, + {"name":"generator/ResizeBilinear_1/size","op":"Const","attr":{"dtype":{"type":"DT_INT32"},"value":{"tensor":{"dtype":"DT_INT32","tensorShape":{"dim":[{"size":"2"}]}}}}}, + {"name":"generator/Conv/weights","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"7"},{"size":"7"},{"size":"3"},{"size":"32"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv/biases","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}}}}, + {"name":"generator/Conv_8/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"32"},{"size":"32"}]}}}}}, + {"name":"generator/Conv_8/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"32"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_9/weights","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"7"},{"size":"7"},{"size":"32"},{"size":"3"}]}}}}}, + {"name":"generator/Conv_9/biases","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"depthwise_2/filter_in","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"3"},{"size":"1"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"ConstantFolding/truediv_1_recip","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"1"}]}}}}}, + {"name":"depthwise_4/filter_in","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"3"},{"size":"1"}]}}}}}, + {"name":"ConstantFolding/truediv_3_recip","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"1"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"add/y","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"depthwise_1/filter_in","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"3"},{"size":"1"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"ConstantFolding/truediv_recip","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"1"}]}}}}}, + {"name":"depthwise_6/filter_in","op":"Const","attr":{"dtype":{"type":"DT_FLOAT"},"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"3"},{"size":"3"},{"size":"3"},{"size":"1"}]}}}}}, + {"name":"ConstantFolding/truediv_6_recip","op":"Const","attr":{"value":{"tensor":{"dtype":"DT_FLOAT","tensorShape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"1"}]}}},"dtype":{"type":"DT_FLOAT"}}}, + {"name":"input","op":"Placeholder","attr":{"dtype":{"type":"DT_FLOAT"},"shape":{"shape":{"dim":[{"size":"1"},{"size":"720"},{"size":"720"},{"size":"3"}]}}}}, + {"name":"generator/LeakyRelu","op":"_FusedConv2D","input":["input","generator/Conv/weights","generator/Conv/biases"],"device":"/device:CPU:0","attr":{"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"data_format":{"s":"TkhXQw=="},"leakyrelu_alpha":{"f":0.2},"use_cudnn_on_gpu":{"b":true},"T":{"type":"DT_FLOAT"},"padding":{"s":"U0FNRQ=="},"explicit_paddings":{"list":{}},"dilations":{"list":{"i":["1","1","1","1"]}},"num_args":{"i":"1"},"strides":{"list":{"i":["1","1","1","1"]}},"epsilon":{"f":0}}}, + {"name":"ArithmeticOptimizer/ReplaceMulWithSquare_mul_2","op":"Square","input":["input"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"depthwise_1","op":"DepthwiseConv2dNative","input":["input","depthwise_1/filter_in"],"attr":{"T":{"type":"DT_FLOAT"},"strides":{"list":{"i":["1","1","1","1"]}},"explicit_paddings":{"list":{}},"data_format":{"s":"TkhXQw=="},"dilations":{"list":{"i":["1","1","1","1"]}},"padding":{"s":"U0FNRQ=="}}}, + {"name":"generator/LeakyRelu_1","op":"_FusedConv2D","input":["generator/LeakyRelu","generator/Conv_1/weights","generator/Conv_1/biases"],"device":"/device:CPU:0","attr":{"leakyrelu_alpha":{"f":0.2},"dilations":{"list":{"i":["1","1","1","1"]}},"num_args":{"i":"1"},"epsilon":{"f":0},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"T":{"type":"DT_FLOAT"},"padding":{"s":"U0FNRQ=="},"use_cudnn_on_gpu":{"b":true},"explicit_paddings":{"list":{}},"data_format":{"s":"TkhXQw=="},"strides":{"list":{"i":["1","2","2","1"]}}}}, + {"name":"depthwise_4","op":"DepthwiseConv2dNative","input":["ArithmeticOptimizer/ReplaceMulWithSquare_mul_2","depthwise_4/filter_in"],"attr":{"strides":{"list":{"i":["1","1","1","1"]}},"padding":{"s":"U0FNRQ=="},"data_format":{"s":"TkhXQw=="},"explicit_paddings":{"list":{}},"T":{"type":"DT_FLOAT"},"dilations":{"list":{"i":["1","1","1","1"]}}}}, + {"name":"truediv","op":"Mul","input":["depthwise_1","ConstantFolding/truediv_recip"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/LeakyRelu_2","op":"_FusedConv2D","input":["generator/LeakyRelu_1","generator/Conv_2/weights","generator/Conv_2/biases"],"device":"/device:CPU:0","attr":{"dilations":{"list":{"i":["1","1","1","1"]}},"leakyrelu_alpha":{"f":0.2},"num_args":{"i":"1"},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"T":{"type":"DT_FLOAT"},"padding":{"s":"U0FNRQ=="},"epsilon":{"f":0},"data_format":{"s":"TkhXQw=="},"explicit_paddings":{"list":{}},"strides":{"list":{"i":["1","1","1","1"]}},"use_cudnn_on_gpu":{"b":true}}}, + {"name":"truediv_3","op":"Mul","input":["depthwise_4","ConstantFolding/truediv_3_recip"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"ArithmeticOptimizer/ReplaceMulWithSquare_mul_3","op":"Square","input":["truediv"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/LeakyRelu_3","op":"_FusedConv2D","input":["generator/LeakyRelu_2","generator/Conv_3/weights","generator/Conv_3/biases"],"device":"/device:CPU:0","attr":{"leakyrelu_alpha":{"f":0.2},"dilations":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"padding":{"s":"U0FNRQ=="},"explicit_paddings":{"list":{}},"strides":{"list":{"i":["1","2","2","1"]}},"T":{"type":"DT_FLOAT"},"epsilon":{"f":0},"num_args":{"i":"1"},"use_cudnn_on_gpu":{"b":true}}}, + {"name":"sub_1","op":"Sub","input":["add/y","ArithmeticOptimizer/ReplaceMulWithSquare_mul_3"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/LeakyRelu_4","op":"_FusedConv2D","input":["generator/LeakyRelu_3","generator/Conv_4/weights","generator/Conv_4/biases"],"device":"/device:CPU:0","attr":{"use_cudnn_on_gpu":{"b":true},"data_format":{"s":"TkhXQw=="},"explicit_paddings":{"list":{}},"epsilon":{"f":0},"padding":{"s":"U0FNRQ=="},"num_args":{"i":"1"},"leakyrelu_alpha":{"f":0.2},"strides":{"list":{"i":["1","1","1","1"]}},"dilations":{"list":{"i":["1","1","1","1"]}},"T":{"type":"DT_FLOAT"},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}}}}, + {"name":"add","op":"Add","input":["truediv_3","sub_1"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_0/LeakyRelu","op":"_FusedConv2D","input":["generator/LeakyRelu_4","generator/block_0/conv1/weights","generator/block_0/conv1/biases"],"device":"/device:CPU:0","attr":{"explicit_paddings":{"list":{}},"dilations":{"list":{"i":["1","1","1","1"]}},"strides":{"list":{"i":["1","1","1","1"]}},"use_cudnn_on_gpu":{"b":true},"epsilon":{"f":0},"data_format":{"s":"TkhXQw=="},"num_args":{"i":"1"},"padding":{"s":"U0FNRQ=="},"T":{"type":"DT_FLOAT"},"leakyrelu_alpha":{"f":0.2},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}}}}, + {"name":"generator/block_0/conv2/BiasAdd","op":"_FusedConv2D","input":["generator/block_0/LeakyRelu","generator/block_0/conv2/weights","generator/block_0/conv2/biases"],"device":"/device:CPU:0","attr":{"data_format":{"s":"TkhXQw=="},"use_cudnn_on_gpu":{"b":true},"padding":{"s":"U0FNRQ=="},"fused_ops":{"list":{"s":["Qmlhc0FkZA=="]}},"strides":{"list":{"i":["1","1","1","1"]}},"explicit_paddings":{"list":{}},"dilations":{"list":{"i":["1","1","1","1"]}},"epsilon":{"f":0},"T":{"type":"DT_FLOAT"},"num_args":{"i":"1"}}}, + {"name":"generator/block_0/add","op":"AddV2","input":["generator/block_0/conv2/BiasAdd","generator/LeakyRelu_4"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_1/LeakyRelu","op":"_FusedConv2D","input":["generator/block_0/add","generator/block_1/conv1/weights","generator/block_1/conv1/biases"],"device":"/device:CPU:0","attr":{"epsilon":{"f":0},"data_format":{"s":"TkhXQw=="},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"padding":{"s":"U0FNRQ=="},"strides":{"list":{"i":["1","1","1","1"]}},"leakyrelu_alpha":{"f":0.2},"explicit_paddings":{"list":{}},"use_cudnn_on_gpu":{"b":true},"T":{"type":"DT_FLOAT"},"dilations":{"list":{"i":["1","1","1","1"]}},"num_args":{"i":"1"}}}, + {"name":"generator/block_1/conv2/BiasAdd","op":"_FusedConv2D","input":["generator/block_1/LeakyRelu","generator/block_1/conv2/weights","generator/block_1/conv2/biases"],"device":"/device:CPU:0","attr":{"fused_ops":{"list":{"s":["Qmlhc0FkZA=="]}},"epsilon":{"f":0},"num_args":{"i":"1"},"dilations":{"list":{"i":["1","1","1","1"]}},"use_cudnn_on_gpu":{"b":true},"explicit_paddings":{"list":{}},"strides":{"list":{"i":["1","1","1","1"]}},"T":{"type":"DT_FLOAT"},"padding":{"s":"U0FNRQ=="},"data_format":{"s":"TkhXQw=="}}}, + {"name":"generator/block_1/add","op":"AddV2","input":["generator/block_1/conv2/BiasAdd","generator/block_0/add"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_2/LeakyRelu","op":"_FusedConv2D","input":["generator/block_1/add","generator/block_2/conv1/weights","generator/block_2/conv1/biases"],"device":"/device:CPU:0","attr":{"padding":{"s":"U0FNRQ=="},"explicit_paddings":{"list":{}},"num_args":{"i":"1"},"use_cudnn_on_gpu":{"b":true},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"T":{"type":"DT_FLOAT"},"epsilon":{"f":0},"dilations":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="},"strides":{"list":{"i":["1","1","1","1"]}},"leakyrelu_alpha":{"f":0.2}}}, + {"name":"generator/block_2/conv2/BiasAdd","op":"_FusedConv2D","input":["generator/block_2/LeakyRelu","generator/block_2/conv2/weights","generator/block_2/conv2/biases"],"device":"/device:CPU:0","attr":{"epsilon":{"f":0},"dilations":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="},"strides":{"list":{"i":["1","1","1","1"]}},"use_cudnn_on_gpu":{"b":true},"padding":{"s":"U0FNRQ=="},"fused_ops":{"list":{"s":["Qmlhc0FkZA=="]}},"explicit_paddings":{"list":{}},"num_args":{"i":"1"},"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_2/add","op":"AddV2","input":["generator/block_2/conv2/BiasAdd","generator/block_1/add"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/block_3/LeakyRelu","op":"_FusedConv2D","input":["generator/block_2/add","generator/block_3/conv1/weights","generator/block_3/conv1/biases"],"device":"/device:CPU:0","attr":{"leakyrelu_alpha":{"f":0.2},"padding":{"s":"U0FNRQ=="},"use_cudnn_on_gpu":{"b":true},"dilations":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"strides":{"list":{"i":["1","1","1","1"]}},"num_args":{"i":"1"},"T":{"type":"DT_FLOAT"},"epsilon":{"f":0},"explicit_paddings":{"list":{}}}}, + {"name":"generator/block_3/conv2/BiasAdd","op":"_FusedConv2D","input":["generator/block_3/LeakyRelu","generator/block_3/conv2/weights","generator/block_3/conv2/biases"],"device":"/device:CPU:0","attr":{"num_args":{"i":"1"},"use_cudnn_on_gpu":{"b":true},"strides":{"list":{"i":["1","1","1","1"]}},"T":{"type":"DT_FLOAT"},"epsilon":{"f":0},"data_format":{"s":"TkhXQw=="},"explicit_paddings":{"list":{}},"padding":{"s":"U0FNRQ=="},"dilations":{"list":{"i":["1","1","1","1"]}},"fused_ops":{"list":{"s":["Qmlhc0FkZA=="]}}}}, + {"name":"generator/block_3/add","op":"AddV2","input":["generator/block_3/conv2/BiasAdd","generator/block_2/add"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/LeakyRelu_5","op":"_FusedConv2D","input":["generator/block_3/add","generator/Conv_5/weights","generator/Conv_5/biases"],"device":"/device:CPU:0","attr":{"data_format":{"s":"TkhXQw=="},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"padding":{"s":"U0FNRQ=="},"num_args":{"i":"1"},"use_cudnn_on_gpu":{"b":true},"leakyrelu_alpha":{"f":0.2},"dilations":{"list":{"i":["1","1","1","1"]}},"strides":{"list":{"i":["1","1","1","1"]}},"explicit_paddings":{"list":{}},"epsilon":{"f":0},"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/ResizeBilinear","op":"ResizeBilinear","input":["generator/LeakyRelu_5","generator/ResizeBilinear/size"],"attr":{"align_corners":{"b":false},"half_pixel_centers":{"b":false},"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/add","op":"AddV2","input":["generator/ResizeBilinear","generator/LeakyRelu_2"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/LeakyRelu_6","op":"_FusedConv2D","input":["generator/add","generator/Conv_6/weights","generator/Conv_6/biases"],"device":"/device:CPU:0","attr":{"leakyrelu_alpha":{"f":0.2},"padding":{"s":"U0FNRQ=="},"explicit_paddings":{"list":{}},"strides":{"list":{"i":["1","1","1","1"]}},"use_cudnn_on_gpu":{"b":true},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"T":{"type":"DT_FLOAT"},"epsilon":{"f":0},"data_format":{"s":"TkhXQw=="},"num_args":{"i":"1"},"dilations":{"list":{"i":["1","1","1","1"]}}}}, + {"name":"generator/LeakyRelu_7","op":"_FusedConv2D","input":["generator/LeakyRelu_6","generator/Conv_7/weights","generator/Conv_7/biases"],"device":"/device:CPU:0","attr":{"T":{"type":"DT_FLOAT"},"strides":{"list":{"i":["1","1","1","1"]}},"leakyrelu_alpha":{"f":0.2},"explicit_paddings":{"list":{}},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"padding":{"s":"U0FNRQ=="},"epsilon":{"f":0},"use_cudnn_on_gpu":{"b":true},"num_args":{"i":"1"},"dilations":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="}}}, + {"name":"generator/ResizeBilinear_1","op":"ResizeBilinear","input":["generator/LeakyRelu_7","generator/ResizeBilinear_1/size"],"attr":{"half_pixel_centers":{"b":false},"T":{"type":"DT_FLOAT"},"align_corners":{"b":false}}}, + {"name":"generator/add_1","op":"AddV2","input":["generator/ResizeBilinear_1","generator/LeakyRelu"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/LeakyRelu_8","op":"_FusedConv2D","input":["generator/add_1","generator/Conv_8/weights","generator/Conv_8/biases"],"device":"/device:CPU:0","attr":{"leakyrelu_alpha":{"f":0.2},"num_args":{"i":"1"},"dilations":{"list":{"i":["1","1","1","1"]}},"epsilon":{"f":0},"use_cudnn_on_gpu":{"b":true},"padding":{"s":"U0FNRQ=="},"strides":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="},"fused_ops":{"list":{"s":["Qmlhc0FkZA==","TGVha3lSZWx1"]}},"explicit_paddings":{"list":{}},"T":{"type":"DT_FLOAT"}}}, + {"name":"generator/Conv_9/BiasAdd","op":"_FusedConv2D","input":["generator/LeakyRelu_8","generator/Conv_9/weights","generator/Conv_9/biases"],"device":"/device:CPU:0","attr":{"use_cudnn_on_gpu":{"b":true},"T":{"type":"DT_FLOAT"},"num_args":{"i":"1"},"padding":{"s":"U0FNRQ=="},"dilations":{"list":{"i":["1","1","1","1"]}},"epsilon":{"f":0},"data_format":{"s":"TkhXQw=="},"explicit_paddings":{"list":{}},"strides":{"list":{"i":["1","1","1","1"]}},"fused_ops":{"list":{"s":["Qmlhc0FkZA=="]}}}}, + {"name":"depthwise_2","op":"DepthwiseConv2dNative","input":["generator/Conv_9/BiasAdd","depthwise_2/filter_in"],"attr":{"dilations":{"list":{"i":["1","1","1","1"]}},"padding":{"s":"U0FNRQ=="},"T":{"type":"DT_FLOAT"},"explicit_paddings":{"list":{}},"data_format":{"s":"TkhXQw=="},"strides":{"list":{"i":["1","1","1","1"]}}}}, + {"name":"mul","op":"Mul","input":["input","generator/Conv_9/BiasAdd"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"truediv_1","op":"Mul","input":["depthwise_2","ConstantFolding/truediv_1_recip"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"depthwise_3","op":"DepthwiseConv2dNative","input":["mul","depthwise_3/filter_in"],"attr":{"dilations":{"list":{"i":["1","1","1","1"]}},"explicit_paddings":{"list":{}},"data_format":{"s":"TkhXQw=="},"padding":{"s":"U0FNRQ=="},"T":{"type":"DT_FLOAT"},"strides":{"list":{"i":["1","1","1","1"]}}}}, + {"name":"mul_1","op":"Mul","input":["truediv","truediv_1"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"truediv_2","op":"Mul","input":["depthwise_3","ConstantFolding/truediv_2_recip"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"sub","op":"Sub","input":["truediv_2","mul_1"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"truediv_4","op":"RealDiv","input":["sub","add"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"depthwise_5","op":"DepthwiseConv2dNative","input":["truediv_4","depthwise_5/filter_in"],"attr":{"strides":{"list":{"i":["1","1","1","1"]}},"padding":{"s":"U0FNRQ=="},"explicit_paddings":{"list":{}},"T":{"type":"DT_FLOAT"},"data_format":{"s":"TkhXQw=="},"dilations":{"list":{"i":["1","1","1","1"]}}}}, + {"name":"mul_4","op":"Mul","input":["truediv_4","truediv"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"truediv_5","op":"Mul","input":["depthwise_5","ConstantFolding/truediv_5_recip"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"sub_2","op":"Sub","input":["truediv_1","mul_4"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"mul_5","op":"Mul","input":["truediv_5","input"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"depthwise_6","op":"DepthwiseConv2dNative","input":["sub_2","depthwise_6/filter_in"],"attr":{"explicit_paddings":{"list":{}},"dilations":{"list":{"i":["1","1","1","1"]}},"data_format":{"s":"TkhXQw=="},"T":{"type":"DT_FLOAT"},"padding":{"s":"U0FNRQ=="},"strides":{"list":{"i":["1","1","1","1"]}}}}, + {"name":"truediv_6","op":"Mul","input":["depthwise_6","ConstantFolding/truediv_6_recip"],"attr":{"T":{"type":"DT_FLOAT"}}}, + {"name":"add_1","op":"AddV2","input":["mul_5","truediv_6"],"attr":{"T":{"type":"DT_FLOAT"}}} + ], + "library": {}, + "versions": + { + "producer": 1087 + } + }, + "weightsManifest": + [ + { + "paths": ["whitebox.bin"], + "weights": [{"name":"depthwise_5/filter_in","shape":[3,3,3,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"ConstantFolding/truediv_5_recip","shape":[1,720,720,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"depthwise_3/filter_in","shape":[3,3,3,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"ConstantFolding/truediv_2_recip","shape":[1,720,720,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_3/conv1/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_3/conv1/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_3/conv2/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_3/conv2/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_2/conv1/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_2/conv1/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_2/conv2/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_2/conv2/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_1/conv1/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_1/conv1/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_1/conv2/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_1/conv2/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_0/conv1/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_0/conv1/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_0/conv2/weights","shape":[3,3,128,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/block_0/conv2/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_3/weights","shape":[3,3,64,64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_3/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_4/weights","shape":[3,3,64,128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_4/biases","shape":[128],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_5/weights","shape":[3,3,128,64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_5/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/ResizeBilinear/size","shape":[2],"dtype":"int32"},{"name":"generator/Conv_1/weights","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_1/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_2/weights","shape":[3,3,32,64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_2/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_6/weights","shape":[3,3,64,64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_6/biases","shape":[64],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_7/weights","shape":[3,3,64,32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_7/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/ResizeBilinear_1/size","shape":[2],"dtype":"int32"},{"name":"generator/Conv/weights","shape":[7,7,3,32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_8/weights","shape":[3,3,32,32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_8/biases","shape":[32],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_9/weights","shape":[7,7,32,3],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"generator/Conv_9/biases","shape":[3],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"depthwise_2/filter_in","shape":[3,3,3,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"ConstantFolding/truediv_1_recip","shape":[1,720,720,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"depthwise_4/filter_in","shape":[3,3,3,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"ConstantFolding/truediv_3_recip","shape":[1,720,720,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"add/y","shape":[],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"depthwise_1/filter_in","shape":[3,3,3,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"ConstantFolding/truediv_recip","shape":[1,720,720,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"depthwise_6/filter_in","shape":[3,3,3,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}},{"name":"ConstantFolding/truediv_6_recip","shape":[1,720,720,1],"dtype":"float32","quantization":{"dtype":"float16","original_dtype":"float32"}}] + } + ] +} \ No newline at end of file diff --git a/index.html b/index.html index 173aec1..ce47fce 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,7 @@ + diff --git a/script.js b/script.js index e40d166..abc448a 100644 --- a/script.js +++ b/script.js @@ -5,6 +5,10 @@ import { DrawingUtils } from 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.14/vision_bundle.mjs' +import 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.20.0/dist/tf.min.js' +import 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgpu@4.20.0/dist/tf-backend-webgpu.min.js' +import 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgl@4.20.0/dist/tf-backend-webgl.min.js' + video_url.addEventListener('change', e => get_video(e.currentTarget)) video_url.addEventListener('keydown', e => {if (e.key == 'Enter' || e.key == 'Tab') get_video(e.currentTarget)}) video_url.addEventListener('focus', e => {if (e.currentTarget.value) capture_select(e.currentTarget)}) @@ -90,7 +94,7 @@ const effect_funcs = { } }, - 'chest_xray': (W, H, stride, Voffset, Uoffset, yuv, rgba, videoFrame, models) => { + 'chest_xray': (W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame) => { for (let y = 0; y < H; y++) { const yUV = (y >> 1) * stride for (let x = 0; x < W; x++) { @@ -99,8 +103,8 @@ const effect_funcs = { const U = yuv[Voffset + xUV + yUV] const V = yuv[Uoffset + xUV + yUV] const offset4 = (x+y*W) * 4 - ;[rgba[offset4], rgba[1 + offset4], rgba[2 + offset4]] = yuv2rgb(Y, U, V) - rgba[3 + offset4] = 255 + ;[rgba[offset4], rgba[offset4 + 1], rgba[offset4 + 2]] = yuv2rgb(Y, U, V) + rgba[offset4 + 3] = 255 } } const orig_rgba = new Uint8ClampedArray(rgba) @@ -128,8 +132,8 @@ const effect_funcs = { if (is_inside_convex([x, y], vertices)) { const offset4 = (x+y*W) * 4 rgba[offset4] = 255 - orig_rgba[offset4] - rgba[1 + offset4] = 255 - orig_rgba[1 + offset4] - rgba[2 + offset4] = 255 - orig_rgba[2 + offset4] + rgba[offset4 + 1] = 255 - orig_rgba[offset4 + 1] + rgba[offset4 + 2] = 255 - orig_rgba[offset4 + 2] } } }) @@ -137,7 +141,7 @@ const effect_funcs = { } }, - 'background_removal': (W, H, stride, Voffset, Uoffset, yuv, rgba, videoFrame, models) => { + 'background_removal': (W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame) => { const startTimeMs = performance.now() if (lastVideoTime != videoFrame.timestamp) { lastVideoTime = videoFrame.timestamp @@ -152,14 +156,54 @@ const effect_funcs = { const U = yuv[Voffset + xUV + yUV] const V = yuv[Uoffset + xUV + yUV] const offset4 = offset * 4 - ;[rgba[offset4], rgba[1 + offset4], rgba[2 + offset4]] = yuv2rgb(Y, U, V) - rgba[3 + offset4] = 255 + ;[rgba[offset4], rgba[offset4 + 1], rgba[offset4 + 2]] = yuv2rgb(Y, U, V) + rgba[offset4 + 3] = 255 } }) ) } }, + 'cartoonization': (W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame) => { + let rgb = new Float32Array(W * H * 3) + for (let y = 0; y < H; y++) { + const yUV = (y >> 1) * stride + for (let x = 0; x < W; x++) { + const xUV = x >> 1 + const Y = yuv[x + y*W] + const U = yuv[Voffset + xUV + yUV] + const V = yuv[Uoffset + xUV + yUV] + const offset3 = (x+y*W) * 3 + const [R, G, B] = yuv2rgb(Y, U, V) + rgb[offset3] = R + rgb[offset3 + 1] = G + rgb[offset3 + 2] = B + } + } + + tf.tidy(() => { + rgb = models['cartoon'].execute(tf.tensor4d(rgb, [1, H, W, 3]) + .resizeBilinear([720, 720]) + .div(127.5) + .sub(1)) + .add(1) + .mul(127.5) + .cast('int32') + .resizeBilinear([H, W]) + .dataSync() + }) + + for (let y = 0; y < H; y++) + for (let x = 0; x < W; x++) { + const offset3 = (x+y*W) * 3 + const offset4 = (x+y*W) * 4 + rgba[offset4] = rgb[offset3] + rgba[offset4 + 1] = rgb[offset3 + 1] + rgba[offset4 + 2] = rgb[offset3 + 2] + rgba[offset4 + 3] = 255 + } + }, + 'pixel_sorting': (W, H, stride, Voffset, Uoffset, yuv, rgba) => { for (let y = 0; y < H; y++) { const yUV = (y >> 1) * stride @@ -175,18 +219,19 @@ const effect_funcs = { for (let x = 0; x < W; x++) { const {Y, U, V} = line[x] const offset4 = (x+y*W) * 4 - ;[rgba[offset4], rgba[1 + offset4], rgba[2 + offset4]] = yuv2rgb(Y, U, V) - rgba[3 + offset4] = 255 + ;[rgba[offset4], rgba[offset4 + 1], rgba[offset4 + 2]] = yuv2rgb(Y, U, V) + rgba[offset4 + 3] = 255 } } }, 'bayer_dithering': (W, H, stride, Voffset, Uoffset, yuv, rgba) => { - const bayer_r = 128 - const threshold = 128 - const matrix = - [[ -0.5 , 0 ], - [ 0.25, -0.25 ]] + const bayer_r = 96 + const threshold = 144 + const matrix = [[ -0.5 , 0 , -0.375 , 0.125 ], + [ 0.25 , -0.25 , 0.375 , -0.125 ], + [ -0.3125, 0.1875, -0.4375, 0.0625 ], + [ 0.4375, -0.0625, 0.3125, -0.1875 ]] const bayer_n = matrix.length for (let y = 0; y < H; y++) { const yUV = (y >> 1) * stride @@ -207,9 +252,9 @@ const effect_funcs = { } const offset4 = (x+y*W) * 4 rgba[offset4] = R - rgba[1 + offset4] = G - rgba[2 + offset4] = B - rgba[3 + offset4] = 255 + rgba[offset4 + 1] = G + rgba[offset4 + 2] = B + rgba[offset4 + 3] = 255 } } }, @@ -223,8 +268,8 @@ const effect_funcs = { const U = yuv[Voffset + xUV + yUV] const V = yuv[Uoffset + xUV + yUV] const offset4 = (x+y*W) * 4 - ;[rgba[offset4], rgba[1 + offset4], rgba[2 + offset4]] = yuv2rgb(Y, U, V) - rgba[3 + offset4] = 255 + ;[rgba[offset4], rgba[offset4 + 1], rgba[offset4 + 2]] = yuv2rgb(Y, U, V) + rgba[offset4 + 3] = 255 } } }, @@ -233,7 +278,7 @@ const effect_funcs = { effect_funcs['recode_landmarks'] = effect_funcs['recode_original'] let capture_started -const unsupported = '

Not supported by your browser :(

Try in Chromium desktop!

' +const unsupported_message = '

Not supported by your browser :(

Try in Chromium desktop!

' async function capture() { if (capture_started) @@ -245,11 +290,13 @@ async function capture() { preferCurrentTab: true }) } catch (e) { - console.error(e) - if (e instanceof TypeError) - out_video.outerHTML = unsupported - else + if (e instanceof TypeError) { + console.error(e) + out_video.outerHTML = unsupported_message + } else { + console.warn(e) capture_started = false + } return } const [track] = stream.getVideoTracks() @@ -263,13 +310,13 @@ async function capture() { out_container.oncontextmenu = e => toggle_fullscreen(e) out_container.title = 'Right-click to enter/exit fullscreen' } catch (e) { - console.error(e) + console.warn(e) try { const cropTarget = await CropTarget.fromElement(orig_video) await track.cropTo(cropTarget) } catch (e){ console.error(e) - out_video.outerHTML = unsupported + out_video.outerHTML = unsupported_message return } } @@ -303,9 +350,20 @@ async function capture() { runningMode: 'VIDEO', }) - const models = {'pose': poseLandmarker, 'segment': imageSegmenter} - const canvasCtx = canvas.getContext('2d'); - const drawingUtils = new DrawingUtils(canvasCtx); + try { + await tf.setBackend('webgpu') + } catch (e) { + console.warn(e) + await tf.setBackend('webgl') + } + + // https://github.com/SystemErrorWang/White-box-Cartoonization + // https://github.com/vladmandic/anime + const cartoon = await tf.loadGraphModel('cartoon/whitebox.json') + + const models = {'pose': poseLandmarker, 'segment': imageSegmenter, 'cartoon': cartoon} + const canvasCtx = canvas.getContext('2d') + const drawingUtils = new DrawingUtils(canvasCtx) const trackProcessor = new MediaStreamTrackProcessor({ track: track }) const trackGenerator = new MediaStreamTrackGenerator({ kind: 'video' }) @@ -326,7 +384,7 @@ async function capture() { const copyResult = await videoFrame.copyTo(yuv) const { stride, offset: Voffset } = copyResult[1] const { offset: Uoffset } = copyResult[2] - effect_funcs[effect.value](W, H, stride, Voffset, Uoffset, yuv, rgba, videoFrame, models) + effect_funcs[effect.value](W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame) } const init = { codedHeight: H, @@ -352,7 +410,7 @@ function capture_select(input_elem) { let wake_lock function request_wake_lock() { - navigator.wakeLock?.request('screen').then(lock => wake_lock = lock).catch(e => console.error(e.message)) + navigator.wakeLock?.request('screen').then(lock => wake_lock = lock).catch(e => console.warn(e.message)) } function visibility_change_handler() { @@ -371,14 +429,14 @@ function toggle_fullscreen(event_or_elem, landscape=true, elem) { elem.addEventListener('fullscreenchange', () => { if (elem.classList.toggle('fullscreen')) { if (landscape) - screen.orientation.lock('landscape').catch(e => console.error(e.message)) // Works only in Chrome Android. See: https://bugzilla.mozilla.org/show_bug.cgi?id=1744125 + screen.orientation.lock('landscape').catch(e => console.warn(e.message)) // Works only in Chrome Android. See: https://bugzilla.mozilla.org/show_bug.cgi?id=1744125 request_wake_lock() document.addEventListener('visibilitychange', visibility_change_handler) } else wake_lock?.release().then(() => wake_lock = null) }) } - elem.requestFullscreen({navigationUI: 'hide'}).catch(e => console.error(e.message)) + elem.requestFullscreen({navigationUI: 'hide'}).catch(e => console.warn(e.message)) } else document.exitFullscreen() return was_not_fullscreen_before diff --git a/style.css b/style.css index a82d689..1ae5fc2 100644 --- a/style.css +++ b/style.css @@ -11,25 +11,32 @@ body { padding-block: 2rem; } +footer { + display: flex; + gap: 2em; +} + .fullscreen { background-color: canvas !important; } iframe { + border: none; isolation: isolate; + min-height: 0; } iframe, #out_container { aspect-ratio: 16 / 9; background-color: black; - border: none; - flex-shrink: 0; height: 100%; - max-height: 40%; + max-height: 50vw; } #inp_container { display: flex; + flex-wrap: wrap; + justify-content: center; gap: 1rem; } @@ -51,9 +58,4 @@ iframe, #out_container { #out_container > div { align-content: center; font-family: sans-serif; -} - -footer { - display: flex; - gap: 2em; } \ No newline at end of file