如何使用vue/javascripts在图像上绘制多边形

问题描述 投票:0回答:1

我有一张图像,每个痘痘上都有方框和代码。我将其发送到 Google Vision 并得到回复。 然后我显示每个“产品代码”的按钮列表。单击时,它应该使用“产品代码”从响应列表中查找其坐标,并在图像上绘制一个多边形以突出显示具有该“产品代码”的框。 我按照 mdn 文档了解如何绘制多边形,但它不起作用。请帮忙。

<script src="https://cdnjs.cloudflare.com/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.net/npm/[email protected]/dist/css/bootstrap.min.css">
    <script src="https://unpkg.com/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.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/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.net/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>

javascript canvas vuejs3 drawing
1个回答
0
投票

我知道问题是什么了!

  1. 当我上传图像时,它具有原始尺寸:图像宽度:4032 图片高度:3024
  2. 根据该大小,Google Vision 返回坐标。
  3. 但是在显示预览图像/画布时,根据屏幕尺寸较小: 预览图片:391 293
  4. 因此,当我尝试根据原始尺寸坐标绘制多边形时,它根本无法将这些坐标放入预览图像尺寸中。

结论:检查图像尺寸!

© www.soinside.com 2019 - 2024. All rights reserved.