Basler Vision Connector: ZMQ JSON Test File with Image Viewer#
Info
Before you start the sample script: If you want to run the script in the Siemens ecosystem, make sure that you have installed the following nodes:
- node-red-contrib-zeromq
- node-red-contrib-image-tools
- node-red-contrib-libjpeg-turbo
- node-red-contrib-mp-function
Also, replace the camera ID in JSON commands according to your camera.
For further possible JSON commands, refer to the Messaging topics in this documentation.
[
{
"id": "4439601ca240ab0e",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "08dd196094de4ee6",
"type": "group",
"z": "4439601ca240ab0e",
"name": "Image Viewer",
"style": {
"stroke": "#00457C",
"fill": "#F59D21",
"label": true,
"color": "#00457C"
},
"nodes": [
"46316e67be47a571",
"743b7a4060ec2c74",
"da0d0e83e0311c49",
"91021863b76d9c46",
"aad40d0878b0ea7f"
],
"x": 864,
"y": 359,
"w": 312,
"h": 142
},
{
"id": "a15b8a9bdb1dd320",
"type": "group",
"z": "4439601ca240ab0e",
"name": "Step 1: Get Connected Devices",
"style": {
"stroke": "#00457C",
"fill": "#F59D21",
"label": true,
"color": "#00457C"
},
"nodes": [
"c5b9ca4503385cfd"
],
"x": 514,
"y": 199,
"w": 252,
"h": 82
},
{
"id": "13dba5f6169ea22e",
"type": "group",
"z": "4439601ca240ab0e",
"name": "Step 2: Open Desired Camera",
"style": {
"label": true,
"fill": "#F59D21",
"stroke": "#00457C",
"color": "#00457C"
},
"nodes": [
"03c4a7175a858618",
"744e687f5b1183d3"
],
"x": 514,
"y": 319,
"w": 212,
"h": 122
},
{
"id": "f680217c27365bd8",
"type": "group",
"z": "4439601ca240ab0e",
"name": "Step 3: Set Parameters",
"style": {
"fill": "#F59D21",
"label": true,
"stroke": "#00457C",
"color": "#00457C"
},
"nodes": [
"827fc4bc6437ee4e",
"e9ecfa108fe2adce"
],
"x": 514,
"y": 479,
"w": 232,
"h": 122
},
{
"id": "75469372ead30c41",
"type": "group",
"z": "4439601ca240ab0e",
"name": "Step 4: Start Streaming",
"style": {
"fill": "#F59D21",
"label": true,
"stroke": "#00457C",
"color": "#00457C"
},
"nodes": [
"d1f367f29f67972b",
"9e981d05d3086101"
],
"x": 514,
"y": 639,
"w": 232,
"h": 122
},
{
"id": "c5b9ca4503385cfd",
"type": "inject",
"z": "4439601ca240ab0e",
"g": "a15b8a9bdb1dd320",
"name": "EnumerateDevices",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"Action\":\"EnumerateDevices\"}",
"payloadType": "json",
"x": 650,
"y": 240,
"wires": [
[
"4477a70441e0a6e2"
]
]
},
{
"id": "f10a9f60cdbeb27f",
"type": "debug",
"z": "4439601ca240ab0e",
"name": "debug",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1125,
"y": 240,
"wires": [],
"l": false
},
{
"id": "4477a70441e0a6e2",
"type": "zeromq request",
"z": "4439601ca240ab0e",
"name": "",
"fields": "payload",
"server": "tcp://baslervisionconnector-multi-x86-64:5555",
"output": "string",
"isserver": false,
"intype": "req",
"x": 1020,
"y": 240,
"wires": [
[
"f10a9f60cdbeb27f"
]
]
},
{
"id": "03c4a7175a858618",
"type": "inject",
"z": "4439601ca240ab0e",
"g": "13dba5f6169ea22e",
"name": "OpenDevice",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"Action\":\"OpenDevice\",\"DeviceID\":\"1\"}",
"payloadType": "json",
"x": 630,
"y": 360,
"wires": [
[
"59b0af73730b5f7e"
]
]
},
{
"id": "744e687f5b1183d3",
"type": "inject",
"z": "4439601ca240ab0e",
"g": "13dba5f6169ea22e",
"name": "CloseDevice",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"Action\":\"CloseDevice\",\"DeviceID\":\"1\"}",
"payloadType": "json",
"x": 630,
"y": 400,
"wires": [
[
"59b0af73730b5f7e"
]
]
},
{
"id": "743b7a4060ec2c74",
"type": "zeromq in",
"z": "4439601ca240ab0e",
"g": "08dd196094de4ee6",
"name": "",
"topic": "40062774/stream",
"fields": "topic,image,metadata",
"server": "tcp://baslervisionconnector-multi-x86-64:5556",
"output": "buffer",
"isserver": false,
"intype": "sub",
"x": 970,
"y": 400,
"wires": [
[
"46316e67be47a571",
"da0d0e83e0311c49"
]
]
},
{
"id": "d1f367f29f67972b",
"type": "inject",
"z": "4439601ca240ab0e",
"g": "75469372ead30c41",
"name": "StartStreaming",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"Action\":\"StartStreaming\",\"DeviceID\":\"1\"}",
"payloadType": "json",
"x": 640,
"y": 680,
"wires": [
[
"59b0af73730b5f7e"
]
]
},
{
"id": "9e981d05d3086101",
"type": "inject",
"z": "4439601ca240ab0e",
"g": "75469372ead30c41",
"name": "StopStreaming",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"Action\":\"StopStreaming\",\"DeviceID\":\"1\"}",
"payloadType": "json",
"x": 640,
"y": 720,
"wires": [
[
"59b0af73730b5f7e"
]
]
},
{
"id": "46316e67be47a571",
"type": "debug",
"z": "4439601ca240ab0e",
"g": "08dd196094de4ee6",
"name": "Raw Data",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1115,
"y": 400,
"wires": [],
"l": false
},
{
"id": "da0d0e83e0311c49",
"type": "function",
"z": "4439601ca240ab0e",
"g": "08dd196094de4ee6",
"name": "extract data",
"func": "const meta = JSON.parse(String.fromCharCode.apply(String, msg.image)) \n\nif ((meta.detail[0].format == \"RGB8\") || (meta.detail[0].format == \"BGR8\")) \n{\nreturn {\n height: meta.detail[0].height,\n width: meta.detail[0].width,\n image: msg.metadata,\n\n };\n} \n\nif (meta.detail[0].format == \"Mono8\") \n{\n return {\n height: meta.detail[0].height,\n width: meta.detail[0].width,\n ...msg,\n image: Buffer.from([...msg.metadata].flatMap((pixel) => [pixel, pixel, pixel]))\n };\n}\n\nif (meta.detail[0].format == \"BayerRG8\") {\n // Convert Bayer RG8 to RGB (Demosaicing process)\n let bayerImage = msg.metadata;\n let width = meta.detail[0].width;\n let height = meta.detail[0].height;\n let rgbImage = [];\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n // Calculate the index of the Bayer pixel\n let index = y * width + x;\n\n let red = 0, green = 0, blue = 0;\n\n // Bayer RG8 pattern:\n // Odd x rows: Green at odd x, Red at even x\n // Even x rows: Green at even x, Blue at odd x\n\n if (x % 2 === 0 && y % 2 === 0) {\n // Red pixel (even x, even y)\n red = bayerImage[index];\n // Interpolate green (check boundary conditions)\n green = (y + 1 < height ? bayerImage[index + width] : bayerImage[index - width]) +\n (x + 1 < width ? bayerImage[index + 1] : bayerImage[index - 1]);\n green /= 2;\n // Interpolate blue (check boundary conditions)\n blue = (y + 1 < height && x + 1 < width) ? bayerImage[index + width + 1] : bayerImage[index - width - 1];\n } else if (x % 2 === 1 && y % 2 === 1) {\n // Green pixel (odd x, odd y)\n green = bayerImage[index];\n // Interpolate red (check boundary conditions)\n red = (y - 1 >= 0 && x - 1 >= 0) ? (bayerImage[index - 1] + bayerImage[index - width]) / 2 : bayerImage[index + 1];\n // Interpolate blue (check boundary conditions)\n blue = (y + 1 < height && x + 1 < width) ? bayerImage[index + width + 1] : bayerImage[index - width - 1];\n } else if (x % 2 === 0 && y % 2 === 1) {\n // Green pixel (even x, odd y)\n green = bayerImage[index];\n // Interpolate red (check boundary conditions)\n red = (y - 1 >= 0 && x - 1 >= 0) ? (bayerImage[index - 1] + bayerImage[index - width]) / 2 : bayerImage[index + 1];\n // Interpolate blue (check boundary conditions)\n blue = (y + 1 < height && x + 1 < width) ? bayerImage[index + width + 1] : bayerImage[index - width - 1];\n } else if (x % 2 === 1 && y % 2 === 0) {\n // Blue pixel (odd x, even y)\n blue = bayerImage[index];\n // Interpolate green (check boundary conditions)\n green = (y + 1 < height ? bayerImage[index + width] : bayerImage[index - width]) +\n (x + 1 < width ? bayerImage[index + 1] : bayerImage[index - 1]);\n green /= 2;\n // Interpolate red (check boundary conditions)\n red = (y - 1 >= 0 && x - 1 >= 0) ? bayerImage[index - 1] : bayerImage[index + 1];\n }\n\n // Push the interpolated RGB values to the output array\n rgbImage.push(red, green, blue);\n }\n }\n\n // Return the RGB image\n return {\n height: meta.detail[0].height,\n width: meta.detail[0].width,\n image: Buffer.from(rgbImage),\n };\n}\n\n\nelse \n{\n node.error(meta.detail[0].format + \" Pixel format is not supported\");\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 975,
"y": 460,
"wires": [
[
"91021863b76d9c46"
]
],
"l": false
},
{
"id": "91021863b76d9c46",
"type": "jpeg-turbo",
"z": "4439601ca240ab0e",
"g": "08dd196094de4ee6",
"name": "",
"action": "encode",
"image": "image",
"imageWidth": "width",
"imageWidthType": "msg",
"imageHeight": "height",
"imageHeightType": "msg",
"result": "payload",
"format": "rgb",
"quality": 40,
"subSampling": "gray",
"x": 1025,
"y": 460,
"wires": [
[
"aad40d0878b0ea7f"
]
],
"l": false
},
{
"id": "aad40d0878b0ea7f",
"type": "image",
"z": "4439601ca240ab0e",
"g": "08dd196094de4ee6",
"name": "Image Viewer",
"width": "400",
"data": "payload",
"dataType": "msg",
"thumbnail": false,
"active": true,
"pass": true,
"outputs": 1,
"x": 1075,
"y": 460,
"wires": [
[]
],
"inputLabels": [
"JPEG Image"
],
"l": false
},
{
"id": "59b0af73730b5f7e",
"type": "mp-function",
"z": "4439601ca240ab0e",
"name": "DeviceID",
"rqs": "",
"func": "let jsonMessage = msg.payload;\njsonMessage.DeviceID = \"40062774\";\n\nmsg.payload = jsonMessage;\n\nreturn msg;",
"persistent": false,
"outputs": 1,
"threads": 1,
"noerr": 0,
"x": 920,
"y": 320,
"wires": [
[
"4477a70441e0a6e2"
]
]
},
{
"id": "827fc4bc6437ee4e",
"type": "inject",
"z": "4439601ca240ab0e",
"g": "f680217c27365bd8",
"name": "SetPixelFormat",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"Action\":\"SetParameters\",\"DeviceID\":\"1\",\"ParameterList\":[{\"Name\":\"PixelFormat\",\"Value\":\"RGB8\"}]}",
"payloadType": "json",
"x": 640,
"y": 520,
"wires": [
[
"59b0af73730b5f7e"
]
]
},
{
"id": "e9ecfa108fe2adce",
"type": "inject",
"z": "4439601ca240ab0e",
"g": "f680217c27365bd8",
"name": "SetFPS",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"Action\":\"SetParameters\",\"DeviceID\":\"1\",\"ParameterList\":[{\"Name\":\"AcquisitionFrameRateEnable\",\"Value\":true},{\"Name\":\"AcquisitionFrameRate\",\"Value\":15}]}",
"payloadType": "json",
"x": 610,
"y": 560,
"wires": [
[
"59b0af73730b5f7e"
]
]
},
{
"id": "84e32ea6df0299b3",
"type": "comment",
"z": "4439601ca240ab0e",
"name": "Supported pixel formats: RGB8, BGR8, Mono8, BayerRG8",
"info": "",
"x": 730,
"y": 120,
"wires": []
}
]