{"id":3232,"date":"2021-05-24T13:03:46","date_gmt":"2021-05-24T05:03:46","guid":{"rendered":"http:\/\/www.magicandlove.com\/blog\/?p=3232"},"modified":"2021-05-24T21:56:12","modified_gmt":"2021-05-24T13:56:12","slug":"script-top-in-touchdesigner-canny","status":"publish","type":"post","link":"http:\/\/www.magicandlove.com\/blog\/2021\/05\/24\/script-top-in-touchdesigner-canny\/","title":{"rendered":"Script TOP in TouchDesigner &#8211; Canny Edge Detector"},"content":{"rendered":"\n<p>After the first introduction of the Script TOP, the coming example will implement the <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.opencv.org\/4.5.2\/da\/d5c\/tutorial_canny_detector.html\" target=\"_blank\">Canny Edge Detector<\/a> with OpenCV in TouchDesigner as a demonstration. TouchDesigner already includes its own <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.derivative.ca\/Edge_TOP\" target=\"_blank\">Edge TOP<\/a> for edge detection and visualisation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"577\" src=\"http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-1024x577.png\" alt=\"\" class=\"wp-image-3236\" srcset=\"http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-1024x577.png 1024w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-300x169.png 300w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-768x433.png 768w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-1536x866.png 1536w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-2048x1154.png 2048w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-690x389.png 690w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny01-980x552.png 980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We also implement a slider parameter <em>Threshold<\/em> in the Script TOP to control the variation of edge detection. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"578\" src=\"http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-1024x578.png\" alt=\"\" class=\"wp-image-3239\" srcset=\"http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-1024x578.png 1024w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-300x169.png 300w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-768x433.png 768w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-1536x866.png 1536w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-2048x1155.png 2048w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-690x389.png 690w, http:\/\/www.magicandlove.com\/blog\/wp-content\/uploads\/2021\/05\/Canny02-980x553.png 980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Here is the source code of the Script TOP. Note that we have made a lot of changes in the default function, onSetupParameters to include a custom parameter, <em>Threshold<\/em> as an integer slider. It will generate a value between 5 and 60, to be used in the <em>onCook<\/em> function as a threshold value for the Canny edge detection.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># me - this DAT\n# scriptOp - the OP which is cooking\nimport numpy as np\nimport cv2\n# press 'Setup Parameters' in the OP to call this function to re-create the parameters.\ndef onSetupParameters(scriptOp):\n    page = scriptOp.appendCustomPage('Custom')\n    p = page.appendInt('Threshold', label='Threshold')\n    t = p[0]\n    t.normMin = 5\n    t.normMax = 60\n    t.default = 10\n    t.min = 5\n    t.max = 60\n    t.clampMin = True\n    t.clampMax = True\n    return\n\n# called whenever custom pulse parameter is pushed\ndef onPulse(par):\n    return\n\ndef onCook(scriptOp):\n    thresh = scriptOp.par.Threshold.eval()\n    image = scriptOp.inputs[0].numpyArray(delayed=True, writable=True)\n    if image is None:\n        return\n\n    image *= 255\n    image = image.astype('uint8')\n    gray = cv2.cvtColor(image, cv2.COLOR_RGBA2GRAY)\n    gray = cv2.blur(gray, (3, 3))\n    edges = cv2.Canny(gray, thresh, 3*thresh, 3)\n    output = cv2.cvtColor(edges, cv2.COLOR_GRAY2RGBA)\n    scriptOp.copyNumpyArray(output)\n    return\n<\/pre>\n\n\n\n<p>The first line in the <em>onCook<\/em> function is to retrieve the integer value from the parameter, <em>Threshold<\/em>. We also exit the function when there is not valid video image coming in. For the edge detection, we convert the RGBA image into grayscale and then perform a blur function. the <em>cv2.Canny<\/em> function returns the detected edges in a grayscale image, <em>edges<\/em>. Finally, we convert the <em>edges<\/em> into a regular RGBA image, <em>output,<\/em> for subsequent output as before.<\/p>\n\n\n\n<p>The final TouchDesign project is available in this <a href=\"https:\/\/github.com\/chungbwc\/TouchDesigner\/tree\/main\/ScriptTOPCanny\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub repository<\/a>.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>After the first introduction of the Script TOP, the coming example will implement the Canny Edge Detector with OpenCV in TouchDesigner as a demonstration. TouchDesigner already includes its own Edge TOP for edge detection and visualisation. We also implement a slider parameter Threshold in the Script TOP to control the variation of edge detection. Here [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[179],"tags":[3,182,84],"class_list":["post-3232","post","type-post","status-publish","format-standard","hentry","category-tutorials","tag-opencv","tag-python","tag-touchdesigner"],"_links":{"self":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts\/3232","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/comments?post=3232"}],"version-history":[{"count":9,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts\/3232\/revisions"}],"predecessor-version":[{"id":3291,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/posts\/3232\/revisions\/3291"}],"wp:attachment":[{"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/media?parent=3232"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/categories?post=3232"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.magicandlove.com\/blog\/wp-json\/wp\/v2\/tags?post=3232"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}