记如何利用myscript笔迹文件实现在图片上打标记

背景

使用到的数据

接到一个需求,利用myscript笔迹文件的信息,在对应图片右下角打上标记。
作答图片如下
在这里插入图片描述

而书写这图片所生成的myscript解析后的笔迹文件的内容数据结构如下

{
    "type": "Text",
    "bounding-box": {
        "x": 28.9970188,
        "y": 86.0071945,
        "width": 77.0569305,
        "height": 12.1241608
    },
    "label": "核酸, DNA, RNA",
    "words": [
   			{
            "label": "核酸",
            "candidates": [
                "核酸",
                "核䘒"
            ],
            "first-char": 0,
            "last-char": 1,
            "bounding-box": {
                "x": 28.9970188,
                "y": 86.2018967,
                "width": 20.7964153,
                "height": 11.92
                },
                },
                ...
     "chars": [
        {
            "label": "核",
            "word": 0,
            "grid": [
                {
                    "x": 29.4614334,
                    "y": 86.8824234
                },
                {
                    "x": 38.2922058,
                    "y": 86.8824234
                },
                {
                    "x": 38.2922058,
                    "y": 100.476776
                },
                {
                    "x": 29.4614334,
                    "y": 100.476776
                }
            ],
            "bounding-box": {
                "x": 28.9970188,
                "y": 86.2018967,
                "width": 9.08084297,
                "height": 11.9294586
            },
            },
            ...

而标记的图片如下
在这里插入图片描述

补充的背景信息

  1. 作答图片的大小是自适应生成的,也就是会随着使用者的书写而调整
  2. 作答图片的四边在生成时会填充上宽度为60pixel的白边
  3. 笔迹文件的坐标并不是在图片上的绝对坐标,只是一个相对坐标,但这个坐标是使用笛卡尔坐标系

初步思路

  1. 由于笔迹文件的坐标只是相对坐标,如果想在作答图片上进行正确标记的话,必须将笔迹文件坐标转化为作答图片上的坐标。
  2. 根据bounding-box字段求得整个作答区域的长宽与作答图片的长宽,求得比例系数
  3. 利用比例系数,求得在作答图片的坐标
  4. 对求得的新作答图片坐标上的长与宽进行60pixel的平移

逻辑实现

   def _convert_bounding_boxes(self, original_boxes, writing_area_coords, image_size):
        """
        严格矩形书写区域的坐标转换(等比例缩放 + 边框)
        """
        # 1. 计算可用内容区域(减去 120px 边框)
        border_padding = 60
        content_width = image_size[0] - 2 * border_padding
        content_height = image_size[1] - 2 * border_padding

        # 2. 提取书写区域坐标
        tl = writing_area_coords['top_left']
        tr = writing_area_coords['top_right']
        bl = writing_area_coords['bottom_left']

        # 3. 计算原始书写区域的宽度和高度
        original_width = tr[0] - tl[0]
        original_height = bl[1] - tl[1]

        # 4. 计算统一缩放比例(取宽高比例的最小值,避免溢出)
        width_ratio = content_width / original_width
        height_ratio = content_height / original_height
        uniform_ratio = min(width_ratio, height_ratio) 

        # 5. 计算居中偏移量(让内容在可用区域内居中)
        scaled_width = original_width * uniform_ratio
        scaled_height = original_height * uniform_ratio
        offset_x = (content_width - scaled_width) / 2 + border_padding  # 水平居中
        offset_y = (content_height - scaled_height) / 2 + border_padding  # 垂直居中

        converted_boxes = []
        for box in original_boxes:
            if  box["bounding-box"] is not None:
                bbox = box['bounding-box']
                # 6. 计算偏移量(相对于书写区域左上角)
                original_x = bbox['x'] - tl[0]
                original_y = bbox['y'] - tl[1]

                # 7. 应用统一缩放
                new_x = original_x * uniform_ratio + offset_x
                new_y = original_y * uniform_ratio + offset_y
                new_width = bbox['width'] * uniform_ratio
                new_height = bbox['height'] * uniform_ratio

                # 8. 四舍五入到整数像素(减少浮点误差)
                converted_box = box.copy()
                converted_box['bounding-box'] = {
                    'x': new_x,
                    'y': new_y,
                    'width': new_width,
                    'height': new_height
                }
                converted_boxes.append(converted_box)
            else:
                converted_box = box.copy()
                converted_box['bounding-box'] = {
                    'x': 0,
                    'y': 0,
                    'width': 0,
                    'height': 0
                }
                converted_boxes.append(converted_box)

        return converted_boxes

补充

  1. 使用居中会令效果更好
    # 5. 计算居中偏移量(让内容在可用区域内居中)
        scaled_width = original_width * uniform_ratio
        scaled_height = original_height * uniform_ratio
        offset_x = (content_width - scaled_width) / 2 + border_padding  # 水平居中
        offset_y = (content_height - scaled_height) / 2 + border_padding  # 垂直居中
  1. 是否使用统一比例,要根据实际情况来调,在这里使用统一比例效果会好一丢丢
        # 4. 计算统一缩放比例(取宽高比例的最小值,避免溢出)
        width_ratio = content_width / original_width
        height_ratio = content_height / original_height
        uniform_ratio = min(width_ratio, height_ratio) 

测试效果

在这里插入图片描述
可以看到可以成功框选出每个词语的最后一个字,这就可以利用坐标进行标记了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值