eragonruan / eragonruan.github.io

1 stars 3 forks source link

论文阅读与实现--CTPN - 阮少辉的博客 | Slade Blog #2

Open eragonruan opened 6 years ago

eragonruan commented 6 years ago

http://slade-ruan.me/2017/10/22/text-detection-ctpn/

strand2013 commented 6 years ago

您好,我对您的这篇文章很感兴趣,我下载了你的代码。但是我在编译utils的时候遇到了问题,我的环境是Mac的没有gpu,希望大神解答~

eragonruan commented 6 years ago

你可以先修改setup.py, 注掉和cuda nms相关的内容,使用cython版本的bbox和nms即可

strand2013 commented 6 years ago

我现在编译通过了,但是test的时候出现了问题,我在cfg文件中已经指定了,checkpoint的位置,但是还是在restore的时候报错了,内容是 'Check your pretrained ckpt.model_checkpoint_path'。然后还有一个问题就是我在pycharm里面打开项目无法运行demo.py 而在命令行可以。原因是’ 没有/envs/py35’这个貌似是你的环境,我在哪里改呢。多谢啦~

eragonruan commented 6 years ago

我提供的模型是python3.5+tf1.3训练的,如果你的版本不一样,可能没法restore edit configuration修改你自己的python interpreter。

strand2013 commented 6 years ago

多谢了

Ruochen0715 commented 6 years ago

大神好,我在训练自己的数据时报错,能否请教一下您呢? 我自己准备了一批数据,执行split_label.py,ToVoc.py,ln -s TEXTVOC VOCdevkit2007均已无问题 但是在运行训练程序train_net.py时,会有一系列错误。

如直接运行,会报错 File "/home/wangruochen/TFworkspace/ctpn/lib/roi_data_layer/roidb.py", line 18, in prepare_roidb roidb[i]['image'] = imdb.image_path_at(i) IndexError: list index out of range 我用以训练的数据集仅有3个样本 在这里,我发现len(imdb.image_index)为6,似乎是扩展了我的数据集两倍。但len(imdb.roidb)仅为4,进而造成越界。进一步检查发现,在train_net.py的一开始,get_imdb('voc_2007_trainval')后,len(imdb.roidb)与len(imdb.image_index)分别为1和3。似乎imdb.roidb是错误的 事实上,即便使用你提供的VOC数据集,在get_imdb('voc_2007_trainval')后,imdb.roidb与imdb.image_index长度分别为1和6000。前者似乎是错误的,进而导致训练失败

而后,我修改程序,改为get_imdb('voc_2007_train')。此时imdb.roidb长度为6000,进而可以训练VOC数据集。但是当我训练自己的数据集时,imdb.roidb依旧为6000,导致报错 File "/home/wangruochen/TFworkspace/ctpn/lib/roi_data_layer/roidb.py", line 52, in add_bbox_regression_targets max_overlaps = roidb[im_i]['max_overlaps'] KeyError: 'max_overlaps' 看起来,imdb.roidb并没有随着数据集大小的变化而变化。这是怎么回事呢?希望能得到点拨

eragonruan commented 6 years ago

@ABigPing 在我本地,使用那6000张图片的话roidb和image_index都是6000,使用train或者trainval是一样的,因为用的都是这6000张图片。你可以检查一下VOCdevkit2007/VOC2007/ImageSets/Main下面的train.txt和trainval.txt是否正确,是否是6000张图片。你在用自己数据训练的时候也要特别注意一点,数据的标注格式是不是和mlt这个数据集一致,因为split_label这个函数是针对mlt的标注格式来写的,所以如果你原始数据标注格式如果和它不同,转换之后可能会是错的,那么得到的用来训练的数据集可能也不对。至于你提到的扩展2倍这件事,这是因为做了简单的data augment,也就是水平翻转了图片,所以数量会是2倍。

Ruochen0715 commented 6 years ago

大腿,在我这里,即便训练你提供的数据集,依旧出错。我检查了VOC的trainval.txt,是6000图片没错。image_index也是6000。但是roidb始终是1。实际上,即便我修改trainval.txt,增加点图片。image_index会跟着增加,但是roidb始终是1。这可能是什么错误呢? 再一个,我昨晚使用你提供的train.txt训练VOC,没有改动你的参数。由于image_index和roidb均为6000,所以可以训练。但是训练不收敛,loss始终在震荡。于是最后也不能检测文本行。。。。很茫然T^T

Ruochen0715 commented 6 years ago

好的,我发现roidb来源于ctpn/data/cache内生成的文件。在调整数据集并重新训练的过程中,ctpn/data/cache内的数据并不会覆盖。也就是说,生成了一次,就不再变了,即便我更换数据集。。。删除这个文件夹后,运行trainval模式就正常了,他会重新生成正常的cache内容。。。我跑一天你提供的VOC数据集看看哈~有情况再来抱你大腿

eragonruan commented 6 years ago

对的,cache是为了加速数据读取,所以不会每次重新生成,更换了数据集需要手动清理

Ruochen0715 commented 6 years ago

大腿,我再问一句啊。我现在在训练你提供的数据集,没有变更参数。现在iter到8000了,但是total loss始终在1左右震荡。这正常么?你训练这个数据集,total loss最后在多少左右?

eragonruan commented 6 years ago

我就是个学生,咱们正常交流就行。我训练了50k步之后,total loss大概能到0.6,cls 0.08, reg0.25。

chenmozxh commented 6 years ago

你好,我这边的centos上没有gpu,我修改了setup.py(注掉和cuda nms相关的内容),但编译依然报错,“error: each element of 'ext_modules' option must be an Extension instance or 2-tuple”。小白不懂,可能是我注释的有问题,我能把setup.py发给你,帮我看一下么?谢谢

eragonruan commented 6 years ago

@chenmozxh 跑一下python setup.py build, 然后把build文件夹下面生成的两个so文件拷贝到lib/utils就可以。setup.py 用下面的代码

from Cython.Build import cythonize
import numpy as np
from distutils.core import setup

try:
    numpy_include = np.get_include()
except AttributeError:
    numpy_include = np.get_numpy_include()

setup(
    ext_modules=cythonize(["bbox.pyx","cython_nms.pyx"],include_dirs=[numpy_include]),
)
Ruochen0715 commented 6 years ago

同学,我不得不继续请教你哦 我使用你提供的VOC数据集训练,loss永远处于震荡状态,无法收敛。 但是如果我把数据集缩小到仅有几张图,就可以收敛了。

接下来,我尝试使用100张图训练,total loss依旧震荡。并且非常有意思,即便我将学习率和WEIGHT_DECAY置零,total loss还是会在0.8-1.2这个范围内震荡。看起来震荡并不见得是网络的真实状态,也可能是total loss统计了不同的数据导致的。 我没用过TF,之前在用caffe,所以有些分析不清楚。这大概是什么情况?total loss是怎么统计的,统计了单张图的loss,还是一个batch内的loss,又或者是每个display间所有batch的平均loss?

然后,test.yml内的参数的意义,在哪里能看到呢?

chenmozxh commented 6 years ago

谢谢回复 我这边还是有点问题。对cython的版本有要求么?我这边cython是0.27.2

File "setup.py", line 11, in ext_modules=cythonize(["bbox.pyx","cython_nms.pyx"],include_dirs=[numpy_include]), File "/usr/lib64/python2.7/site-packages/Cython/Build/Dependencies.py", line 909, in cythonize c_options = CompilationOptions(**options) File "/usr/lib64/python2.7/site-packages/Cython/Compiler/Main.py", line 559, in init raise ValueError(message) ValueError: got unknown compilation option, please remove: include_dirs

eragonruan commented 6 years ago

@chenmozxh 我的版本是0.24.1,高版本的cython好像移除了include_dirs这个option,具体你可以查一下api

eragonruan commented 6 years ago

@ABigPing 这个loss是每一张图片的loss,而且目前没有加正则,所以有震荡是正常的,图与图之间的loss大小差别还是比较大的。你也可以修改lib/fast_rcnn/train.py, 去计算每个epoch的loss。具体参数的意义你可以去看faster rcnn和ctpn的论文和repo。或者有哪个具体参数不清楚也可以直接问我

chenmozxh commented 6 years ago

果然是cython版本的问题,换了台机器(cython是0.24),编译成功,能运行。 十分感谢

Ruochen0715 commented 6 years ago

谢谢,难得有这么热心的作者。。。我一边学tf一边看你的代码哈

Ruochen0715 commented 6 years ago

增加了一个mean_loss,感到0.0001学习率太高了,减小了10倍。训练结果正常了。感谢同学帮助

jinxin0924 commented 6 years ago

论文作者说大概是在0.14s/image,你这边tensorflow在gpu上的预测速度大概多少啊

eragonruan commented 6 years ago

没有仔细测试过,按照作者的做法,短边600的话在0.18左右吧

jinxin0924 commented 6 years ago

从论文看,是不是对倾斜图片的支持很差?需要自己先做旋转

eragonruan commented 6 years ago

对的,对倾斜文本支持是比较差的。算法本身是只能检测水平文本的,作者提供的caffe版本也只能检测水平文本。现在项目里检测倾斜文本也只是在后处理部分“强”加进去,效果不好说

kmustriver commented 6 years ago

同学,你好,请问训练数据的格式是什么样的,是不是需要准备图片,以及图片中的文字区域的坐标也需要手动给出才能训练

eragonruan commented 6 years ago

@kmustriver x1,y1,x2,y2,x3,y3,x4,y4 . 对的,可以直接用一些公开的数据集, 我用的是multi lingual scene texts dataset

OstNo1 commented 6 years ago

请问博主的原始gt文件是怎么样的呢,看split_label的时候就看不懂了。。。

OstNo1 commented 6 years ago

x1,y1,x2,y2,x3,y3,x4,y4 分别是什么?不是一个框对应4个坐标么

eragonruan commented 6 years ago

@OstNo1 一个框的四个角点的x,y坐标。这是因为我用的mlt训练的,他的数据就是这么标注的,如果你要用一些水平文本的数据集,标注是x,y,w,h的,也是可以的,修改一下split_label的代码,或者写个小脚本把x,y,w,h转换成x1,y1,x2,y2,x3,y3,x4,y4就行

kmustriver commented 6 years ago

非常感谢您之前的回复,对我非常有帮助,我还想问下,我现在想把这个改写为keras的实现方式,所以我想咨询下您改写为tensorflow的时候流程是怎么样的,或者您怎么知道这其中具体的网络结构的呢

wanhaipeng commented 6 years ago

你好请问,proposal layer是在CPU上跑的还是GPU呢

eragonruan commented 6 years ago

@kmustriver 可以去看他们的论文,论文讲的还是比较清楚的,整体的网络结构以及很多细节都有说到。我实现的时候基本照着论文来的,除了text connector这部分用了作者的代码,作者的caffe版本中的prototxt中也有网络的结构

eragonruan commented 6 years ago

@wanhaipeng cpu上,这部分是纯python代码,想移植到gpu还是比较复杂的

OstNo1 commented 6 years ago

谢谢之前回答,请问博主,我训练的时候,在CPU上可以训练,但到了GPU上训练就出现训练RPN的断言错误,:AssertionError: Single batch only,查看发现len(im_scales)=2,请问这是怎么回事呢?我训练样本每张图只有一个框的。。。

eragonruan commented 6 years ago

@OstNo1 这里是指每一次训练只用一张图片,和图片内有多少bbox没有关系

OstNo1 commented 6 years ago

博主,我又来了,请问你的数据是直接塞到模型训练还是还有一些预训练的?我训练简单自己生成的文字图片,模型对新图片预测出来的框全部是相同位置的54个框,请问博主有什么训练的方法么?

eragonruan commented 6 years ago

@OstNo1 直接训练,你这种情况模型应该还没有收敛

fanlu commented 6 years ago

请问博主,滑动窗口之后,W应该不是固定的,lstm之后是怎么进行FC的,是每一个滑动窗口都进行一次FC吗?另外论文里面是BLSTM,你的实现是LSTM?

eragonruan commented 6 years ago

@fanlu 对,滑动窗口之后w不固定,但是经过lstm之后就是固定的了,lstm的teamstep就是这个w,所以出来的特征维度可以固定

fanlu commented 6 years ago

@eragonruan 就是用了最后一个timestep的HT是吗?但是用一个timestep怎么预测所有的W*k个anchor呢?我看论文里面写的是,The internal state in Ht is mapped to the following FC layer, and output layer for computing the predictions of the t-th proposal.这不应该每个t都要计算FC吗? lstm_cell = tf.contrib.rnn.BasicLSTMCell(d_h, forget_bias=1.0, state_is_tuple=False) _istate = lstm_cell.zero_state(batch_size, dtype='float32') _LSTM_O, _LSTM_S = tf.contrib.rnn.static_rnn(lstm_cell, _Hsplit, initial_state=_istate) return tf.reshape(_LSTM_O[-1],[input_shape[0],input_shape[1],input_shape[2],int(d_h)]) 而你实现的这个是最后一个_LSTM_O[-1]?

eragonruan commented 6 years ago

@fanlu 这句话我倒没注意过,但是以我个人理解,应该还是用的最后一个HT,最后一个HT是包含之前的全部信息的。而中间的HT信息是不完备的,他只能预测他之前的anchor,后面的没法预测

wanhaipeng commented 6 years ago

请问,论文里面有个228*228是怎么算出来的?

wanhaipeng commented 6 years ago

receptive field的228怎么算出来的?

eragonruan commented 6 years ago

@wanhaipeng see section 3.1 in Faster-RCNN.

fanlu commented 6 years ago

@eragonruan 跟了一下代码,假如一个图片是NHWC为(1,800,600,3)经过rpn_conv/3*3得到的结果shape是(1,50,37,512),这个再经过input = tf.reshape(input, [-1, d_i]),变为(1850,512),然后经过_H = tf.matmul(input, kernel) + biases变为(1850,128),再_Hsplit = tf.split(_H, 1,0)变为[(1850,128)]然后再输入到LSTM里面,这时的rnn的循环长度就是1?得到的结果len(_LSTM_O)==1,然后_LSTM_O[-1]就是输出的唯一的一个结果。

eragonruan commented 6 years ago

@fanlu 抱歉这个项目是半年多前弄的,我需要review一下,现在看来好像确实有点奇怪

jinxin0924 commented 6 years ago

@fanlu, @eragonruan 我理解是每个window得到33C,然后全连接,得到2k个score和位置,然后用nms过滤多余box,这样得到每个位置的竖直框。(类似Faster-RCNN,每个anchor box都要由一个rpn算一个5维的值)

fanlu commented 6 years ago

@jinxin0924 w*h个全连接,那参数呢?而且每个window得到的是个长度为c的向量而不是33c

jinxin0924 commented 6 years ago

@fanlu 我的3×3×c,用了*号,结果成变成斜体了。全连接参数应该是共享的,3×3×C×5k