最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

canvas - how to draw polygons on image with vuejavascripts - Stack Overflow

matteradmin4PV0评论

I have an image with boxes and codes on each pox. I send it to Google Vision and get a response. Then I display the list of buttons for each "product code". On click, it should use "product code" to find its coordinates from the response list and draw a polygon on the image to highlight the box with that "product code". I follow mdn documentation on how to draw polygons but it does not work. Please help.

<script src=".5.4/vue.global.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="/[email protected]/dist/css/bootstrap.min.css">
    <script src="@3/dist/vue.global.js"></script>
    <title>Scan</title>
    <style>
        .form-group {
            margin-bottom: 1rem;
        }

        .code-button {
            margin: 5px;
        }
    </style>
</head>
<body>
    <div id="scan" class="container">
        <div class="row">
            <div class="col-md-12">
                <h1>Scan</h1>
                <div class="form-group">
                    <label for="image">Image</label>
                    <input type="file" accept="image/*" class="form-control" id="image" name="image" @change="handleFileUpload">
                </div>
                <div class="form-group">
                    <button v-if="isImageSelected" class="btn btn-warning" @click="restartImage">Restart Image</button>
                    <button class="btn btn-success" @click="sendImage">Submit</button>
                </div>
                <div style="position: relative; width: 640px; height: 480px;">
                    <canvas id="canvas" width="640" height="480" style="position: absolute; top: 0; left: 0; z-index: 1;"></canvas>
                    <img id="preview" src="" alt="Preview" class="img-fluid" style="position: absolute; top: 0; left: 0; z-index: 0;">
                </div>
                <div id="results"></div>
                <div id="code-buttons">
                    <button v-for="code in codeList" :key="code" class="code-button" @click="highlightBox(code)">
                        [[ code ]]
                    </button>
                </div>
            </div>
        </div>
    </div>

    <script src="/[email protected]/dist/js/bootstrap.min.js"></script>
    <script src="/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
    <script src="/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script>

    <script>
        const response = {
            "product_codes": [
                {
                    "code": "697902",
                    "bounding_poly": [
                        [574, 1250],
                        [766, 1256],
                        [765, 1282],
                        [573, 1276]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [762, 1390],
                        [960, 1384],
                        [961, 1413],
                        [763, 1419]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [673, 1570],
                        [880, 1579],
                        [878, 1612],
                        [672, 1603]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [364, 1792],
                        [573, 1796],
                        [572, 1825],
                        [364, 1821]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [640, 1796],
                        [848, 1779],
                        [851, 1811],
                        [643, 1828]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [1066, 1390],
                        [1248, 1388],
                        [1248, 1412],
                        [1066, 1414]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [942, 1784],
                        [1150, 1770],
                        [1152, 1800],
                        [944, 1814]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [631, 2039],
                        [848, 2024],
                        [850, 2053],
                        [633, 2068]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [1231, 1807],
                        [1445, 1809],
                        [1445, 1840],
                        [1231, 1838]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [1221, 2047],
                        [1439, 2032],
                        [1442, 2069],
                        [1224, 2084]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [591, 2295],
                        [811, 2275],
                        [814, 2309],
                        [594, 2329]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [904, 2296],
                        [1126, 2294],
                        [1126, 2327],
                        [904, 2329]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [216, 2572],
                        [444, 2543],
                        [449, 2581],
                        [221, 2611]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [561, 2558],
                        [788, 2546],
                        [790, 2582],
                        [563, 2594]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [897, 2559],
                        [1119, 2547],
                        [1121, 2586],
                        [899, 2598]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [2159, 2223],
                        [2384, 2237],
                        [2381, 2271],
                        [2157, 2257]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3293, 2021],
                        [3513, 2024],
                        [3513, 2056],
                        [3293, 2053]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3411, 2289],
                        [3641, 2289],
                        [3641, 2321],
                        [3411, 2321]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [2133, 2490],
                        [2361, 2509],
                        [2358, 2543],
                        [2130, 2525]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3801, 2508],
                        [4030, 2503],
                        [4031, 2537],
                        [3802, 2542]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3464, 2534],
                        [3698, 2541],
                        [3697, 2577],
                        [3463, 2570]
                    ]
                }
            ]
        };

        const { createApp } = Vue;

        createApp({
            delimiters: ['[[', ']]'],
            data() {
                return {
                    canvas: null,
                    context: null,
                    isImageSelected: false,
                    capturedImage: null,
                    response: response,
                    codeList: [...new Set(response.product_codes.map(item => item.code))]
                }
            },
            methods: {
                handleFileUpload(event) {
                    const file = event.target.files[0];
                    const reader = new FileReader();
                    reader.onload = (e) => {
                        this.capturedImage = e.target.result;
                        document.getElementById('preview').src = this.capturedImage;
                        document.getElementById('preview').style.display = 'block';
                        this.isImageSelected = true;
                    };
                    reader.readAsDataURL(file);
                },
                sendImage() {
                    this.drawPolygons();
                },
                restartImage() {
                    // Clear states
                    this.isImageSelected = false;
                    document.getElementById('preview').src = '';
                    document.getElementById('preview').style.display = 'none';
                    document.getElementById('results').innerHTML = '';
                    this.capturedImage = null;
                },
                drawPolygons() {
                    const canvas = document.getElementById('canvas');
                    const ctx = canvas.getContext('2d');
                    if (!ctx) {
                        console.error('Failed to get canvas context');
                        return;
                    }
                    const preview = document.getElementById('preview');
                    canvas.width = preview.width;
                    canvas.height = preview.height;
                    canvas.style.display = 'block'; // Ensure canvas is visible

                    this.response.product_codes.forEach(item => {
                        this.drawPolygon(item.bounding_poly, 'rgba(0, 255, 0, 0.5)');
                    });
                },
                drawPolygon(points, color) {
                    const canvas = document.getElementById('canvas');
                    const ctx = canvas.getContext('2d');
                    if (!ctx) {
                        console.error('Failed to get canvas context');
                        return;
                    }
                    ctx.fillStyle = color;
                    ctx.beginPath();
                    ctx.moveTo(points[0][0], points[0][1]);
                    points.slice(1).forEach(point => {
                        ctx.lineTo(point[0], point[1]);
                    });
                    ctx.closePath();
                    ctx.fill();
                },
                highlightBox(code) {
                    console.log('Highlighting box for code:', code);
                    const canvas = document.getElementById('canvas');
                    const ctx = canvas.getContext('2d');
                    if (!ctx) {
                        console.error('Failed to get canvas context');
                        return;
                    }
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    this.drawPolygons();

                    const pointsArray = this.response.product_codes
                        .filter(item => item.code === code)
                        .map(item => item.bounding_poly);
                    console.log('Points array:', pointsArray);
                    pointsArray.forEach(points => {
                        this.drawPolygon(points, 'rgba(255, 0, 0, 0.5)');
                    });
                }
            }
        }).mount('#scan');
    </script>
</body>
</html>

I have an image with boxes and codes on each pox. I send it to Google Vision and get a response. Then I display the list of buttons for each "product code". On click, it should use "product code" to find its coordinates from the response list and draw a polygon on the image to highlight the box with that "product code". I follow mdn documentation on how to draw polygons but it does not work. Please help.

<script src="https://cdnjs.cloudflare/ajax/libs/vue/3.5.4/vue.global.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr/npm/[email protected]/dist/css/bootstrap.min.css">
    <script src="https://unpkg/vue@3/dist/vue.global.js"></script>
    <title>Scan</title>
    <style>
        .form-group {
            margin-bottom: 1rem;
        }

        .code-button {
            margin: 5px;
        }
    </style>
</head>
<body>
    <div id="scan" class="container">
        <div class="row">
            <div class="col-md-12">
                <h1>Scan</h1>
                <div class="form-group">
                    <label for="image">Image</label>
                    <input type="file" accept="image/*" class="form-control" id="image" name="image" @change="handleFileUpload">
                </div>
                <div class="form-group">
                    <button v-if="isImageSelected" class="btn btn-warning" @click="restartImage">Restart Image</button>
                    <button class="btn btn-success" @click="sendImage">Submit</button>
                </div>
                <div style="position: relative; width: 640px; height: 480px;">
                    <canvas id="canvas" width="640" height="480" style="position: absolute; top: 0; left: 0; z-index: 1;"></canvas>
                    <img id="preview" src="" alt="Preview" class="img-fluid" style="position: absolute; top: 0; left: 0; z-index: 0;">
                </div>
                <div id="results"></div>
                <div id="code-buttons">
                    <button v-for="code in codeList" :key="code" class="code-button" @click="highlightBox(code)">
                        [[ code ]]
                    </button>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr/npm/[email protected]/dist/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script>

    <script>
        const response = {
            "product_codes": [
                {
                    "code": "697902",
                    "bounding_poly": [
                        [574, 1250],
                        [766, 1256],
                        [765, 1282],
                        [573, 1276]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [762, 1390],
                        [960, 1384],
                        [961, 1413],
                        [763, 1419]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [673, 1570],
                        [880, 1579],
                        [878, 1612],
                        [672, 1603]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [364, 1792],
                        [573, 1796],
                        [572, 1825],
                        [364, 1821]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [640, 1796],
                        [848, 1779],
                        [851, 1811],
                        [643, 1828]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [1066, 1390],
                        [1248, 1388],
                        [1248, 1412],
                        [1066, 1414]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [942, 1784],
                        [1150, 1770],
                        [1152, 1800],
                        [944, 1814]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [631, 2039],
                        [848, 2024],
                        [850, 2053],
                        [633, 2068]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [1231, 1807],
                        [1445, 1809],
                        [1445, 1840],
                        [1231, 1838]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [1221, 2047],
                        [1439, 2032],
                        [1442, 2069],
                        [1224, 2084]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [591, 2295],
                        [811, 2275],
                        [814, 2309],
                        [594, 2329]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [904, 2296],
                        [1126, 2294],
                        [1126, 2327],
                        [904, 2329]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [216, 2572],
                        [444, 2543],
                        [449, 2581],
                        [221, 2611]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [561, 2558],
                        [788, 2546],
                        [790, 2582],
                        [563, 2594]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [897, 2559],
                        [1119, 2547],
                        [1121, 2586],
                        [899, 2598]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [2159, 2223],
                        [2384, 2237],
                        [2381, 2271],
                        [2157, 2257]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3293, 2021],
                        [3513, 2024],
                        [3513, 2056],
                        [3293, 2053]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3411, 2289],
                        [3641, 2289],
                        [3641, 2321],
                        [3411, 2321]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [2133, 2490],
                        [2361, 2509],
                        [2358, 2543],
                        [2130, 2525]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3801, 2508],
                        [4030, 2503],
                        [4031, 2537],
                        [3802, 2542]
                    ]
                },
                {
                    "code": "697902",
                    "bounding_poly": [
                        [3464, 2534],
                        [3698, 2541],
                        [3697, 2577],
                        [3463, 2570]
                    ]
                }
            ]
        };

        const { createApp } = Vue;

        createApp({
            delimiters: ['[[', ']]'],
            data() {
                return {
                    canvas: null,
                    context: null,
                    isImageSelected: false,
                    capturedImage: null,
                    response: response,
                    codeList: [...new Set(response.product_codes.map(item => item.code))]
                }
            },
            methods: {
                handleFileUpload(event) {
                    const file = event.target.files[0];
                    const reader = new FileReader();
                    reader.onload = (e) => {
                        this.capturedImage = e.target.result;
                        document.getElementById('preview').src = this.capturedImage;
                        document.getElementById('preview').style.display = 'block';
                        this.isImageSelected = true;
                    };
                    reader.readAsDataURL(file);
                },
                sendImage() {
                    this.drawPolygons();
                },
                restartImage() {
                    // Clear states
                    this.isImageSelected = false;
                    document.getElementById('preview').src = '';
                    document.getElementById('preview').style.display = 'none';
                    document.getElementById('results').innerHTML = '';
                    this.capturedImage = null;
                },
                drawPolygons() {
                    const canvas = document.getElementById('canvas');
                    const ctx = canvas.getContext('2d');
                    if (!ctx) {
                        console.error('Failed to get canvas context');
                        return;
                    }
                    const preview = document.getElementById('preview');
                    canvas.width = preview.width;
                    canvas.height = preview.height;
                    canvas.style.display = 'block'; // Ensure canvas is visible

                    this.response.product_codes.forEach(item => {
                        this.drawPolygon(item.bounding_poly, 'rgba(0, 255, 0, 0.5)');
                    });
                },
                drawPolygon(points, color) {
                    const canvas = document.getElementById('canvas');
                    const ctx = canvas.getContext('2d');
                    if (!ctx) {
                        console.error('Failed to get canvas context');
                        return;
                    }
                    ctx.fillStyle = color;
                    ctx.beginPath();
                    ctx.moveTo(points[0][0], points[0][1]);
                    points.slice(1).forEach(point => {
                        ctx.lineTo(point[0], point[1]);
                    });
                    ctx.closePath();
                    ctx.fill();
                },
                highlightBox(code) {
                    console.log('Highlighting box for code:', code);
                    const canvas = document.getElementById('canvas');
                    const ctx = canvas.getContext('2d');
                    if (!ctx) {
                        console.error('Failed to get canvas context');
                        return;
                    }
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    this.drawPolygons();

                    const pointsArray = this.response.product_codes
                        .filter(item => item.code === code)
                        .map(item => item.bounding_poly);
                    console.log('Points array:', pointsArray);
                    pointsArray.forEach(points => {
                        this.drawPolygon(points, 'rgba(255, 0, 0, 0.5)');
                    });
                }
            }
        }).mount('#scan');
    </script>
</body>
</html>

Share Improve this question asked Nov 16, 2024 at 2:55 Azamat UzbekovAzamat Uzbekov 1501 silver badge14 bronze badges 1
  • Your question is too vague and the snippet you posted is not useful. Consider providing an example with the image you're trying to draw on already loaded and specify what exactly works other than you expect it to. – tao Commented Nov 16, 2024 at 10:59
Add a comment  | 

1 Answer 1

Reset to default 0

I got what the problem was!

  1. When I upload an image it has the original size: Image Width: 4032 Image Height: 3024
  2. Based on that size Google Vision returns coordinates.
  3. But on display Preview image/canvas has a smaller size based on the screen: Preview Image: 391 293
  4. So when I tried to draw a polygon based on Original size coordinates it simply could not fit those coordinates into the Preview image size.

Conclusion: Check the image size!

Post a comment

comment list (0)

  1. No comments so far