Search code examples
javascriptpythonflaskvision-api

Unable to read object BoundingPoly sent from flask to javascript. Want to use this bounds in html and draw this bounds on image


These bounds are returned from the doctext.py DocText.py:

def draw_boxes(image, bounds, color):

    draw = ImageDraw.Draw(image)
    for bound in bounds:
    draw.polygon([
        bound.vertices[0].x, bound.vertices[0].y,
        bound.vertices[1].x, bound.vertices[1].y,
        bound.vertices[2].x, bound.vertices[2].y,
        bound.vertices[3].x, bound.vertices[3].y], None, color)
return image


def get_document_bounds(image_file, feature):

client = vision.ImageAnnotatorClient()

bounds = []

with io.open(image_file, 'rb') as image_file:
    content = image_file.read()

image = types.Image(content=content)

response = client.document_text_detection(image=image)
document = response.full_text_annotation

# Collect specified feature bounds by enumerating all document features
for page in document.pages:
    for block in page.blocks:
        for paragraph in block.paragraphs:
            for word in paragraph.words:
                for symbol in word.symbols:
                    if (feature == FeatureType.SYMBOL):
                        bounds.append(symbol.bounding_box)

                if (feature == FeatureType.WORD):
                    bounds.append(word.bounding_box)

            if (feature == FeatureType.PARA):
                bounds.append(paragraph.bounding_box)

        if (feature == FeatureType.BLOCK):
            bounds.append(block.bounding_box)

    if (feature == FeatureType.PAGE):
        bounds.append(block.bounding_box)

# The list `bounds` contains the coordinates of the bounding boxes.
return bounds


def render_doc_text(filein, fileout):
    image = Image.open(filein)
    bounds = get_document_bounds(filein, FeatureType.PAGE)
    draw_boxes(image, bounds, 'blue')
    bounds = get_document_bounds(filein, FeatureType.PARA)
    draw_boxes(image, bounds, 'red')
    bounds = get_document_bounds(filein, FeatureType.WORD)
    draw_boxes(image, bounds, 'yellow')

app.py using flask:

@app.route('/tagger')
def tagger():
    if (app.config["HEAD"] == len(app.config["FILES"])):
        return redirect(url_for('bye'))
    directory = app.config['IMAGES']
    image = app.config["FILES"][app.config["HEAD"]]
    labels = app.config["LABELS"]
    not_end = not(app.config["HEAD"] == len(app.config["FILES"]) - 1)
    opn = 'directory/'
    for f in os.listdir(opn):
        boundingpoly = doctext.render_doc_text(os.path.join(opn,f))
    print(boundingpoly)
    print(type(boundingpoly))
    print(not_end)
    return render_template('tagger.html', not_end=not_end, directory=directory, image=image, bounds=boundingpoly, labels=labels, head=app.config["HEAD"] + 1, len=len(app.config["FILES"]))

boundingpoly value

boundingpoly =
    [vertices {
      x: 15
      y: 5
    }
    vertices {
      x: 28
      y: 2
    }
    vertices {
      x: 37
      y: 49
    }
    vertices {
      x: 24
      y: 51
    }
    ]

when I pass bounds to html, I want to access this boundingpoly list in js for drawing rectangles using the canvas js in html

 <script>
    var bounds = {{bounds}}
    </script>

It is not working.

I want to read it as an object in js and access these object vertices and draw on canvas.

bounds.vertices.forEach(vertices => {
              ctx.beginPath();
              ctx.moveTo(vertices[0].x, vertices[0].y)
              for (var i = 1; i < vertices.length; i++) {
                ctx.lineTo(vertices[i].x, vertices[i].y);
              }
              ctx.closePath();
              ctx.fillStyle = "pink";
              ctx.strokeStyle = "pink";
              ctx.stroke();
              ctx.lineWidth="5";

when render template variable bounds it is passing as a list and is not able to read in javascript and even tried json dumps, it is displaying Object BoundingPoly is not Json serializable. How am I supposed to do it?


Solution

  • You have

    var bounds = [
        { x: 15 y: 5} { x: 28 y: 2} { x: 37 y: 49} { x: 24 y: 51},
        { x: 106 y: 5} { x: 252 y: 3} { x: 252 y: 36} { x: 106 y: 38},
        { x: 16 y: 40} { x: 296 y: 41} { x: 296 y: 100} { x: 16 y: 99},
    ]    
    

    but I think Javascript expects

    var bounds = {'vertices': [
        [{'x': 15, 'y': 5}, {'x': 28, 'y': 2}, {'x': 37, 'y': 49}, {'x': 24, 'y': 51}],
        [{'x': 106, 'y': 5}, {'x': 252, 'y': 3}, {'x': 252, 'y': 36}, {'x': 106, 'y': 38}],
        [{...}, {...}, {...}, {...}],
    ]}
    

    Using code from draw_boxes() it could be converted with

    result = {'vertices':[]}
    
    for bound in bounds:
        item = [
            {'x': bound.vertices[0].x, 'y': bound.vertices[0].y},
            {'x': bound.vertices[1].x, 'y': bound.vertices[1].y},
            {'x': bound.vertices[2].x, 'y': bound.vertices[2].y},
            {'x': bound.vertices[3].x, 'y': bound.vertices[3].y},
        ]
        result['vertices'].append(item)
    
    print(result)