MingtaoFu / gliding_vertex

The implementation of paper "Gliding vertex on the horizontal bounding box for multi-oriented object detection".
271 stars 63 forks source link

在自有数据上训练得到检测结果多数为棱形状 #21

Closed ygean closed 4 years ago

ygean commented 4 years ago

作者您好,我在研究过您的论文和代码后,在一个one-stage网络上尝试移植您提出的算法,在验证了数据集加载和可视化的编解码没有问题后,我对它进行了充分的训练,发现不少的结果出现了棱形状的检测检测,我想是滑动偏移没有回归到位,想听取您对这种情况的看法,谢谢! 正常的检测情况: image 不正常的: image

ygean commented 4 years ago

作者您好,我在进一步分析数据和对滑动系数这一块的编解码计算时,发现了一个问题,当出现原四边形中的某个角点,它的x,y均是最大或最小的时候,其他的点刚好组成如下图的分布时,您代码中的计算滑动距离是存在问题。 image 红色框是水平框,蓝色是根据滑动系数解码出来的四边形,显然这里解码失败了。对于这种情况,您是如何考虑解决的,我在代码中没有看到相应的解决,如果是我的疏忽,还请您指正,因为我想您这篇论文对四边形检测来说也是一个方案,相比DMP那篇解决了点排序带来的模型学习紊乱的问题。谢谢

ygean commented 4 years ago

@MingtaoFu

lijianfengtian commented 4 years ago

@zhouyuangan 请问下你那个问题都是由x,y均是最大或最小的时候引起的?你可视化了几张图?能分享下你解决那块的方法?

ygean commented 4 years ago

@lijianfengtian 您好,我在自有数据上发现了不少于1/10的解码失败的例子,作者的源码没有问题,我的看法是,这种没问题要加一个条件,一个四边形的四个点要分别对应外接矩形的一条边。当出现四个点中有且仅有一个点的坐标既是有xmax,ymax,那么会存在一个点不在外接矩形上或者刚好在两个点在同一条边上。这是我的看法。我得解决是,在文本上可以用作者的四边形表征算法来做,不过自己标注的文本四边形坐标最好用cv2.minAreaRect处理成旋转矩形,否则会出现我上图的情况。对于大的物体,用minAreaRect不太合适,会增加很多背景,检测文本没有问题。我觉得作者提出的算法很好,简单有效,可能应用场景对于我得文档检测(角度,透视变换)不太适合。对作者开源表示感谢。

lijain commented 4 years ago

@zhouyuangan 你好,我想问下你那部分的应该是作者代码中的maskrcnn_benchmark/box_code.py中class BoxCoder(object)部分? 可以给下你可视化你自己数据那检测正常和检测不正常的代码?我也想可视化下自己的数据看看

MingtaoFu commented 4 years ago

您好,我一段时间没看了,抱歉。 为了能取得及时的联系,请联系我的邮箱: mingtaofu@hust.edu.cn(优先) / madebyrag@gmail.com 请考虑两个问题:

  1. 您所展示的例子是接近于水平的情况,根据我们的论文,该方法应该会被我们的选择机制选定使用水平框代替。可能您只移植了一部分,而没有移植选择机制。
  2. 确实存在一部分四边形是无法使用我们的方法表示的,如下图。您可以考虑先进行预处理再用于训练,例如您提到的minAreaRec。 IMG_1604
ygean commented 4 years ago

谢谢您的回复,这让我对自己的疑问有了解答,非常感谢。我确实忘记移植选择机制😁,我去完善一下我的程序😀

ygean commented 4 years ago

@zhouyuangan 你好,我想问下你那部分的应该是作者代码中的maskrcnn_benchmark/box_code.py中class BoxCoder(object)部分? 可以给下你可视化你自己数据那检测正常和检测不正常的代码?我也想可视化下自己的数据看看

您好,我用的是作者提供的box_code.py中class BoxCoder(object)部分代码,稍微做了一些修改。出于谨慎的态度,我这部分的修改代码不能保证正确,我需要移植算法性能满足要求后,再分享。

import torch
import numpy as np
from lib.datasets.dataset_factory import get_dataset
from matplotlib import pyplot as plt
import cv2
from PIL import Image
from lib.models.box_coder import QuadCoder

def main():
    from lib.config import CertiPageConfig as cfg
    # print(cfg.debug)
    torch.manual_seed(cfg.seed)
    torch.backends.cudnn.benchmark = cfg.cudnn_benchmark
    Dataset = get_dataset(cfg.dataset)
    val_loader = torch.utils.data.DataLoader(
        Dataset(cfg, 'train'),
        batch_size=1,
        shuffle=False,
        num_workers=1,
        pin_memory=True)
    quad_coder = QuadCoder()

    for data in val_loader:
        # print("keys:\t", data.keys())
        # print("meta:\t", data["meta"])
        # print("reg:\t", data["reg"])
        # print("reg_mask:\t", data["reg_mask"])
        # print("ind:\t", data["ind"])
        # print("wh:\t", data["wh"])
        heatmap = data["hm"]
        input_images = data["input"]
        print("input_images shape:\t", input_images.shape)
        gt_bboxes = data["meta"]["bboxes"].numpy()
        gt_bboxes = gt_bboxes[:, :, :4]

        poly_xy = data["poly_xy"].numpy()

        batch = heatmap.shape[0]
        for b in range(batch):
            _heatmap = heatmap[b]
            # chw->hwc
            images = input_images[b].permute(1, 2, 0).detach().numpy()
            # channels = _heatmap.shape[0]
            images *= np.array([0.28863828, 0.27408164, 0.27809835], dtype=np.float32).reshape(1, 1, 3)
            images += np.array([0.40789654, 0.44719302, 0.47026115], dtype=np.float32).reshape(1, 1, 3)
            images *= 255
            images = images.astype(np.uint8)
            img = Image.fromarray(images)
            image = np.array(img)

            print("image shape:\t", image.shape)
            for item in range(gt_bboxes[b].shape[0]):
                # print(item, gt_bboxes.shape[0])
                points = gt_bboxes[b, item].tolist()
                x1, y1, x2, y2 = points
                ct = [(x1 + x2) / 2, (y1 + y2) / 2]
                bbox_4pt = np.array([x1, y1, x2, y1, x2, y2, x1, y2]).reshape((1, 4, 2)).astype(np.int) * cfg.down_ratio
                poly_xy_item = poly_xy[b, item]
                if np.sum(poly_xy_item) == 0:
                    continue
                print("poly_xy[b, item]:\t", poly_xy_item)
                real_quad = quad_coder.decode(poly_xy_item, ct)
                real_quad = real_quad.astype(np.int).reshape((1, 4, 2)) * cfg.down_ratio
                # import pdb; pdb.set_trace()
                # cv2.rectangle(images, (points[0], points[1]), (points[2], points[3]), 255, 2, cv2.LINE_AA)
                cv2.polylines(image, bbox_4pt, True, (0, 0, 255), 2, cv2.LINE_AA)
                cv2.polylines(image, real_quad, True, (255, 0, 0), 1, cv2.LINE_AA)
                cv2.imshow("vis", image)
                cv2.waitKey(0)

if __name__ == "__main__":
    # 执行命令
    # python .\dataset_test.py ctdet --dataset certi_text
    main()

这是我的可视化代码。

Calen-J commented 4 years ago

谢谢您的回复,这让我对自己的疑问有了解答,非常感谢。我确实忘记移植选择机制😁,我去完善一下我的程序😀

请问选择机制对应哪一部分代码

lijain commented 2 years ago

@lijianfengtian 您好,我在自有数据上发现了不少于1/10的解码失败的例子,作者的源码没有问题,我的看法是,这种没问题要加一个条件,一个四边形的四个点要分别对应外接矩形的一条边。当出现四个点中有且仅有一个点的坐标既是有xmax,ymax,那么会存在一个点不在外接矩形上或者刚好在两个点在同一条边上。这是我的看法。我得解决是,在文本上可以用作者的四边形表征算法来做,不过自己标注的文本四边形坐标最好用cv2.minAreaRect处理成旋转矩形,否则会出现我上图的情况。对于大的物体,用minAreaRect不太合适,会增加很多背景,检测文本没有问题。我觉得作者提出的算法很好,简单有效,可能应用场景对于我得文档检测(角度,透视变换)不太适合。对作者开源表示感谢。

I haven't seen much these days. My idea is whether the target drawn by the author can be projected on the corresponding edge to calculate the similar quadrilateral. Is it better than a rectangle?