# Creating a node for License Plate Recognition

**URL:** https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946
**Category:** Developing Nodes
**Created:** [18 February 2020 21:25 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946 "2020-02-18T21:25:10Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [18 February 2020 21:25 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/1 "2020-02-18T21:25:11Z")

</div>

I am using the following service: [http://platerecognizer.com](http://platerecognizer.com)  
And while I successfully created a flow that will use the curl in the exec node, and then the JSON node to read the plates from the image I am just not satisfied with how it all looks together. And would love to create a node.  
But from where should I start, the only setting the node should have is an API field and a name field, and the only input should be the image itself, and the output is a simple JSON, and all of the output content is useful for someone building software for an example public parking.  
Could somebody help me out here? Could I somehow use the existing code for javascript from their website?  
I have created the package.json and the lpr.html  
Tried reading the documentation, but I still have a lot of question.

```auto
<script type="text/javascript">
    RED.nodes.registerType('license-plate-recognition',{
        category: 'recognition',
        color: '#349eeb',
        inputs:1,
        outputs:1,
        icon: "icons/icon.png",
        label: function() {
            return this.name||"license-plate-recognition";
        }
    });
</script>

<script type="text/html" data-template-name="license-plate-recognition">
    <div class="form-row">
        <label for="node-input-name"><i class="icon-tag"></i> Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
         <label for="pwd">API Token:</label>
        <input type="password" id="API" name="API"> 
    </div>
</script>

<script type="text/html" data-help-name="lower-case">
    <p>Automatic Number Plate Recognition software that works in all environments, optimized for your location.</p>
</script>

```

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [18 February 2020 22:01 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/2 "2020-02-18T22:01:59Z")

</div>

Hi @lizzardguki,

That would be a nice node! By coincidence I have been reading about the plate-recognizer last weekend. Don't forget to mention in the info panel that the number of free images per month is [limited](https://platerecognizer.com/pricing/) to 2500 recognitions...

You can always have a look at my (old) [node-red-contrib-openalpr](https://github.com/bartbutenaers/node-red-contrib-openalpr-cloud/blob/master/openalpr_cloud.js) node as an example. That one uses the OpenAlpr cloud service, but it also produces a json output. But my json is a bit more complex, since it also recognizes the vehicle itself (brand ...).

I assume you can implement the http POST request with authorization header, by using [this](https://gist.github.com/SunboX/882547660bea86d280d7) code snippet.

Bart

---

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [18 February 2020 22:09 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/3 "2020-02-18T22:09:37Z")

</div>

Thanks Bart for your help , will checkout your contribution , it was really easy for me to write functions inside node red, but writing a node itself is a little problem , and i hope openalpr will help me.

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [18 February 2020 22:24 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/4 "2020-02-18T22:24:21Z")

</div>

You are welcome!  
Some quick tips to get you started:

- 1 input port where you receive images as binary buffers or base64 string, to make it widely usable. Since you need to send it base64 encoded to the cloud service, you can use our code snippet from the [node-red-contrib-image-output](https://github.com/rikukissa/node-red-contrib-image-output/blob/master/image/image.js#L17) node as an example:

```auto
if (Buffer.isBuffer(image)) {
    image = image.toString("base64");
}

```

- 1 output port. Don't know if your output messages will only contain the json? Personally I would prefer to have both the image **AND** the json in the output. Then (in the next nodes in the flow) the output message could be used e.g. to mail the image when a number plate is not in some list of known number plates ...
- perhaps also avoid parallel recognitions? E.g. keep a boolean `isRecognizing`: when you the previous image is still underway from the cloud service, then isRecognizing is true. When a new image arrives meanwhile, it could be rejected (since isRecognizing is still true).

Looking forward to test it!

---

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [18 February 2020 23:01 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/5 "2020-02-18T23:01:54Z")

</div>

Are the Stream and buffer same? While reading the code on ALPR I see a

```auto
fs.createReadStream(image_path)

```

personally I just want the following javascript code working as a self node-red node

So image as input and json as output.

```auto
const fetch = require('node-fetch');
const FormData = require('form-data');
const fs = require('fs');

let image_path = '/path/to/car.jpg'
let body = new FormData();
body.append('upload', fs.createReadStream(image_path));
// Or body.append('upload', base64Image);
body.append('regions', 'gb');
fetch("https://api.platerecognizer.com/v1/plate-reader/", {
        method: 'POST',
        headers: {
            "Authorization": "Token API_TOKEN"
        },
        body: body
    }).then(res => res.json())
    .then(json => console.log(json))
    .catch((err) => {
        console.log(err);
    });

```

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [18 February 2020 23:19 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/6 "2020-02-18T23:19:30Z")

</div>

Personally I wouldn't do it like that. Now you have to write all your images to disc and read them from there again (via the read stream).  
Normally previous nodes in your flow will read an image from an ip camera and send the image to your node via messages (e.g. in the `msg.payload`). So just get the images from the input messages:

```auto
node.on("input", function(msg) {
   // payload should contain an image as buffer or base64 encoded string
   var image = msg.payload;

   // make sure all images are base64 encoded
   if (Buffer.isBuffer(image)) {
       image = image.toString("base64");
   }
   
   var authorizationHeader = "Authorization": "Basic " + new Buffer("Token:" + node.credentials.token, "utf8").toString("base64")

   // Pass the base64 encoded image to the cloud service 
   ...
}

```

You should _ **keep the images in memory** _, and avoid any disc io!!! And for use cases where the images are stored on disc, you can add a File-In node just before your plate-recognizer node (to read the images from disc).

Caution: your **private token** really should be stored in the [node credentials](https://nodered.org/docs/creating-nodes/credentials)!!! Don't use a plain text input field! Otherwise all other nodes can read it, and when somebody export his flow (to share with others) you will also export his token as plain text, and make it visible to everybody.

It would also be nice if you could add an **URL field** on your node's config screen (which would be default filled with `https://api.platerecognizer.com/v1/plate-reader/`). Because they also offer a Docker [container](https://app.platerecognizer.com/sdk/) to run the whole recognition offline on a local server. In that case you should be able to enter the local url into your config screen, to send the images to your own local recognition service ...

My time is up for today. Good luck !!

---

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [19 February 2020 19:18 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/7 "2020-02-19T19:18:31Z")

</div>

> [@BartButenaers](#):
>
> var authorizationHeader

Visual studio code gives me an error that an comma is needed after "Authorization": should i worry about it ?

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [19 February 2020 19:24 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/8 "2020-02-19T19:24:24Z")

</div>

Ah perhaps it should be` "Authorization: Basic "`.  
Have not tested that code. Just quick typing on my smartphone...

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [19 February 2020 19:58 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/9 "2020-02-19T19:58:32Z")

</div>

And I see now that you got your code snippet from [here](http://docs.platerecognizer.com/?javascript#introduction), where you can also find:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/f/6fec27a981af4cd7de3de8fe15e2e1d46f12cd59.png)

So to me it seems that you don't even need to base64 encode the token, i.e. something like this:

```auto
node.on("input", function(msg) {
   // payload should contain an image as buffer or base64 encoded string
   var image = msg.payload;

   // make sure all images are base64 encoded
   if (Buffer.isBuffer(image)) {
       image = image.toString("base64");
   }
   
   var body = new FormData();
   body.append('upload', image);

   // Pass the base64 encoded image to the cloud (or docker) service 
   fetch(node.url, {
        method: 'POST',
        headers: {
            "Authorization": "Token " + node.credentials.token
        },
        body: body
    }).then(res => res.json())
    .then(json => {
         // Don't override the original msg.payload, which contains the input image
         msg.recognition = json;
         node.send(msg);
    })
    .catch((err) => {
        console.log(err);
    });
}

```

P.S. None of my code is tested, it is just to give you a quick idea!!!!

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [19 April 2020 19:58 UTC](https://discourse.nodered.org/t/creating-a-node-for-license-plate-recognition/21946/10 "2020-04-19T19:58:35Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
