【问题标题】:Do anyone know how to extract Image coordinate from Marmot dataset?有谁知道如何从 Marmot 数据集中提取图像坐标?
【发布时间】:2018-10-15 20:50:15
【问题描述】:

Marmot 是一个文档图像数据集 (http://www.icst.pku.edu.cn/cpdp/data/marmot_data.htm),其中标记了文档正文、图像区域、表格区域、表格标题等多个内容。该数据集专门用于文档图像分析研究目的。他们提到了 16 位十六进制小端格式的所有坐标。有没有人如何使用这个数据集以及如何将 16 位 XY 坐标转换为人类可以理解的格式?

【问题讨论】:

    标签: python hex endianness


    【解决方案1】:

    最后我在分析后得到了线索,如果有人需要调查这个数据集,我会在这里发布。但是,他们提到了将给定坐标转换为像素值的单位值,但很难追踪,因为他们在手册/指南中没有提及。他们提到了另一个地方作为注释。

    1. 首先,您必须使用 IEEE 754 little endian 格式转换它们的 16 个字符的十六进制值。例如,标签的给定坐标是,

      BBox=['4074145c00000005', '4074dd95999999a9', '4080921e74bc6a80', '406fb9999999999a']

    2. 使用python转换,

      conv_pound = struct.unpack('!d', str(t).decode('hex'))[0]) for t in BBox]

    3. 您将获得以“磅”为单位的价值,即 1/72 英寸。我们通常以像素为单位使用坐标,我们知道 1 英寸是 96 像素。所以,

      conv_pound = [321.2724609375003, 333.8490234375009, 530.2648710937501, 253.8]

    然后,将每个值除以 72,再乘以 96,最终得到对应的像素值,即,

    in_pixel = [428.36328, 445.13203, 707.01983, 338.40000]
    
    1. 他们开始从文档图像的左下角开始计算像素位置。如果从左上角考虑(通常我们以这种方式考虑),则必须从图像高度中减去第二个和第四个值。如果我们认为图像 [height, width] 是 [1123, 793] 那么我们可以将上述坐标用整数值表示为,

      label_boundary = [428, 678, 707, 785]

    【讨论】:

    • 第 4 步似乎仅适用于数据集中的极少数图像,并且在使用 matplotlib 绘图和查看时,大多数情况下边界框似乎与表格不匹配。从 xml 解码数据的信息来源是什么
    • 作为@pv。提到,这种方法适用于大多数数据集。在少数情况下,坐标要么有点偏离,要么非常偏离。我认为这些图像的 dpi 不是 96。它们没有 dpi 信息,因此很难解释这些坐标。
    【解决方案2】:

    盯着xmls看了一个小时后,我在@MMReza的答案中找到了最后一个缺失的部分:

    您无需依赖(第 3 步)中的度量单位。根元素“Page”有一个名为“CropBox”的属性。使用那个来缩放坐标。 我有以下几点(这里也是逆 y 轴):

    px0, py1, px1, py0 = list(map(hex_to_double, page.get("CropBox").split()))
    pw = abs(px1 - px0)
    ph = abs(py1 - py0)
    
    for table in page.findall(".//Composite[@Label='TableBody']"):
        x0p, y1m, x1p, y0m = list(map(hex_to_double, table.get("BBox").split()))
        x0 = round(imgw*(x0p - px0)/pw)
        x1 = round(imgw*(x1p - px0)/pw)
        y0 = round(imgh*(py1 - y0m)/ph)
        y1 = round(imgh*(py1 - y1m)/ph)
    

    【讨论】:

      【解决方案3】:

      如果有人像我一样尝试在 Python 3 中执行此操作,您只需像这样更改其他答案的第 2 步:

      conv_pound = [struct.unpack('!d', bytes.fromhex(t))[0] for t in BBox]
      

      【讨论】:

        【解决方案4】:

        我想转换坐标并验证我的转换是否确实有效。因此,我制作了这个脚本来读取标签文件和相应的图像文件,然后提取表格主体的坐标(例如)并在图像上可视化它们。它可以用于以类似的方式提取其他字段。评论说明一切

        import glob
        import struct
        import cv2
        import binascii
        import re
        
        xml_files = glob.glob("path_to_labeled_files/*.xml")
        
        for i in xml_files:
            # Open the current file and read everything
            cur_file = open(i,"r") 
            content = cur_file.read()
        
            # Find index of all occurrences of only needed portions (eg TableBody this case)
            residxs = [l.start() for l in re.finditer('Label="TableBody"', content)]
        
            # Read the image
            img = cv2.imread("path_to_images_folder/"+i.split('/')[-1][:-3]+"jpg")
        
            # Traverse over all occurences
            for r in residxs[:-1]:
                # List to store output points
                coords = []
        
                # Start index of an occurence
                sidx = r
        
                # Substring from whole file content
                substr = content[sidx:sidx+400]
        
                # Now find start index and end index of coordinates in this substring  
                sidx = substr.find('BBox="')
                eidx = substr.find('" CLIDs')
        
                # String containing only points
                points = substr[sidx+6:eidx]
        
                # Make the conversion (also take care of little and big endian in unpack)
                bins = ''
                for j in points.split(' '):
                    if(j == ''):
                        continue
                    coords.append(struct.unpack('>d', binascii.unhexlify(j))[0])
        
                if len(coords) != 4:
                    continue
        
                # As suggested by MMReza
                for k in range(4):
                    coords[k] = (coords[k]/72)*96
                coords[1] = img.shape[0] - coords[1]
                coords[3] = img.shape[0] - coords[3] 
        
                # Print the extracted coordinates
                print(coords)
        
                # Visualize it on the image
                cv2.rectangle(img, (int(coords[0]),int(coords[1]))  , (int(coords[2]),int(coords[3])), (255, 0, 0), 2) 
                cv2.imshow("frame",img)
                cv2.waitKey(0)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-04
          • 2021-12-19
          • 1970-01-01
          • 2021-05-19
          • 1970-01-01
          • 2019-02-19
          相关资源
          最近更新 更多