You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中获取图片点击事件坐标以实现边界框标注功能

解决方案思路

首先明确:坐标捕获是前端JavaScript的职责,Django作为后端框架只负责接收前端传递的坐标数据、做校验后存入数据库。你之前的思路混淆了前后端的分工,才会找不到对应的Django侧实现。

第一步:前端捕获点击/绘制坐标

你可以用原生JS或者轻量标注库实现坐标采集,以原生JS为例,核心逻辑如下:

  • 给展示图片的<img>标签绑定click、mousedown、mouseup事件,计算相对图片的坐标(要排除图片外边距、滚动偏移量,避免坐标错位)
  • 绘制bounding box时记录两个点的坐标:框选起始点(x1,y1)、结束点(x2,y2)
  • 把最终得到的坐标、选中的对象类别写到隐藏的<input>标签里,或者直接用AJAX请求发送给Django后端

最简JS捕获坐标示例:

const img = document.getElementById('标注图片的ID');
// 框选起始点记录
let startX, startY;
img.addEventListener('mousedown', function(e) {
    const rect = img.getBoundingClientRect();
    const scaleX = img.naturalWidth / rect.width;
    const scaleY = img.naturalHeight / rect.height;
    startX = Math.round((e.clientX - rect.left) * scaleX);
    startY = Math.round((e.clientY - rect.top) * scaleY);
});
// 框选结束点记录
img.addEventListener('mouseup', function(e) {
    const rect = img.getBoundingClientRect();
    const scaleX = img.naturalWidth / rect.width;
    const scaleY = img.naturalHeight / rect.height;
    const endX = Math.round((e.clientX - rect.left) * scaleX);
    const endY = Math.round((e.clientY - rect.top) * scaleY);
    // 坐标赋值给隐藏input,方便表单提交
    document.getElementById('x1').value = Math.min(startX, endX);
    document.getElementById('y1').value = Math.min(startY, endY);
    document.getElementById('x2').value = Math.max(startX, endX);
    document.getElementById('y2').value = Math.max(startY, endY);
});

对应的前端模板里要加对应的隐藏input:

<input type="hidden" name="x1" id="x1">
<input type="hidden" name="y1" id="y1">
<input type="hidden" name="x2" id="x2">
<input type="hidden" name="y2" id="y2">
<!-- 保留你已有的对象类别选择控件、提交按钮等元素 -->

第二步:Django后端接收存储坐标

后端部分和普通表单提交处理逻辑一致:

  • 先定义存储标注坐标的模型,字段至少包含图片外键、对象类别、x1/y1/x2/y2四个坐标、标注用户、标注时间等
  • 写对应的视图函数,接收POST请求里的坐标参数,做合法性校验(比如坐标不超过原图宽高、类别是预设可选值等),校验通过后存入数据库即可
  • 如果用AJAX提交的话,返回JsonResponse给前端提示提交结果即可

示例模型定义:

from django.db import models
from django.contrib.auth.models import User

# 替换为你自己的图片存储模型
class UploadedImage(models.Model):
    img_file = models.ImageField(upload_to='images/')
    width = models.IntegerField()
    height = models.IntegerField()
    upload_time = models.DateTimeField(auto_now_add=True)

class Annotation(models.Model):
    image = models.ForeignKey(UploadedImage, on_delete=models.CASCADE, related_name='annotations')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    category = models.CharField(max_length=50)  # 对应你选的对象类型
    x1 = models.IntegerField()
    y1 = models.IntegerField()
    x2 = models.IntegerField()
    y2 = models.IntegerField()
    create_time = models.DateTimeField(auto_now_add=True)

示例视图处理逻辑:

from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from .models import Annotation, UploadedImage

def save_annotation(request):
    if request.method != 'POST':
        return JsonResponse({'status': 'error', 'msg': '请求方法错误'})
    # 提取提交参数
    image_id = request.POST.get('image_id')
    category = request.POST.get('category')
    x1 = int(request.POST.get('x1', 0))
    y1 = int(request.POST.get('y1', 0))
    x2 = int(request.POST.get('x2', 0))
    y2 = int(request.POST.get('y2', 0))
    # 校验参数合法性
    image = get_object_or_404(UploadedImage, id=image_id)
    if x1 <0 or y1 <0 or x2 > image.width or y2 > image.height:
        return JsonResponse({'status': 'error', 'msg': '坐标超出图片范围'})
    # 写入数据库
    Annotation.objects.create(
        image=image,
        user=request.user,
        category=category,
        x1=x1, y1=y1, x2=x2, y2=y2
    )
    return JsonResponse({'status': 'success'})

参考项目的坐标存储逻辑

该项目的坐标提交逻辑在前端JS文件中实现,收集完标注数据后通过POST请求发送到后端的标注保存接口,后端对应的视图完成存储操作,你可以重点看项目静态资源里的JS标注逻辑,以及views.py中处理标注提交的视图函数即可。

内容的提问来源于stack exchange,提问作者yuki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 20:45:02