2007年6月24日星期日

dodo:人脸识别方法个人见解(转载)

最近对人脸识别产生兴趣。其实一直觉得此方向比较有意思,不过没有时间仔细研究模式分类和机器学习方面的内容,
所以也只是了解个大概。
此处转载网友写的有脸识别方法的个人综述,方便参考。
最近Mr Mao推荐一篇比较好的人脸识别综述:Face Recognition-A Literature Survey,ACM 2005。正准备研读。


dodo:人脸识别方法个人见解

看到j.liu关于人脸识别的帖子,萌发写这个帖子的念头。没有别的意思,就是想抛砖引玉,把问题说的全面一点,希望j.liu和回其帖子的兄弟姐妹们不要介意。如有兴趣,欢迎继续讨论。在以下讨论中,

TPAMI = IEEE Transactions on PAMI 这个杂志
PAMI 是指 pattern analysis and machine intelligence这两个领域

1)PCA和LDA及其相关方法

Eigenfaces和Fisherfaces无疑是人脸识别中里程碑式的工作。就使用的方法而言,PCA和LDA都不是新方法,但是他们都是被第一次十分明确的用在人脸识别中的方法。之所以说"十分明确",是因为就发表的时间来看,这两个论文都不是首次把这两个方法用在PAMI相关的分类识别中。这给我们一个小小的启示:一个新的方法专注于解决一个具体的问题可能会带来更大的影响,虽然这个方法具有一般性。

在现在人脸识别的方法中,这两个方法也是follow的人最多的。究其原因,除了其有效性之外,简单是其最大的特点。纵观PAMI历史风云,能经受住时间考验而流传下来的方法,除了有效之外一般都有两个特点其一:1)简单 (PCA, LDA, K-Means, Normalized Cutsetc.);2)复杂 ,但是解决一个具有一般性而且很难被解决的问题 (在AAM、3d morphable model有深刻影响的Lucas-Kanade算法)。所以如果你的方法一般人都有能力做得到,那就尽量把你的方法做的简单明确。这就是外国人推崇备至的所谓的Ockham's Razor原理(就个人情感而言,我十分讨厌这个名词)。在这里我要强调一点是,这里说的简单并不是说原理简单,Normalized Cuts就方法本身来说简单,但是原理并不简单;微分几何中的Gauss-Bonnet定理形式非常简单,内涵何其丰富。

在此我想多提两句。由于国内有诸多发论文的方法论,其中一个流传下来的一句话就是:系统做的越简单越好,理论做的越复杂越好。不可否认,这句话有它有道理的地方,但是如果用这句话教育后人,误人子弟矣。

后来出现了许多新的与之类似的方法,就TPAMI上发表的来看,比较有代表性就是 HE Xiaofei 的LPP和 YAN Shuicheng 的MFA。关于这两个方法的评论大家可参看j.liu贴中knato的回帖。在这里我想谈谈我的个人见解。首先这两个方法的出现有它们的意义。LPP是流形学习中Laplacian Eigenmaps线性化,这样无疑会带动其它流形学习方法在识别问题中的尝试,一个为解决问题找到一个思路,二个为进入寒冬的流形学习找到新的用武之地,虽然这两个都不是上档次的思路,但是潜在影响还是有的。后来 YANG Jian 的UDP就是在LPP号召下在TPAMI上的产物。LPP是非监督方法,所以它的识别性能比LDA好的概率极其微弱。MFA是基于局部数据关系的监督鉴别方法。它有两个最近临近点数量的参数要调。这两个参数是这个方法双刃剑。参数调的好,MFA会比LDA效果好,调的不好则不行。这样MFA用起来比LDA复杂,这样如果MFA的性能比LDA好的有限,而用起来复杂得多的话,它终将被历史所抛弃。
另外就像j.Liu在他的帖子中说出的一样,这些方法有一定的投机性,比如这两篇文章的试验,他们都把Fisherfaces(PCA+LDA)设为c-1,虽然这是按照原始论文的取法,但是是做过这方面工作的人都知道PCA的主元数目如果取得太大,PCA+LDA的性能会显著降低,在WANGXiaogang的IJCV上的Random sampling LDA中清楚地给出了图形说明。所以他们论文中给出的实验比较不具可信性。

LPP, UDP, MFA都是我们中国人(至少这些方法发表时还都是)为第一作者发表的方法,个人认为其存在有一定的价值,但它们将是PAMI研究发展中的过眼烟云,无法与PCA,LDA相媲美。

2)LDA奇异性问题

众所周知,LDA是基于求解广义特征值问题(Sb*u=Alpha*Sw*u),所以在实际应用时遇到奇异性的问题,就是Sw矩阵不可逆。在人脸识别中解决这一问题的论文“浩如烟海”。这也说明了LDA的影响力之大。在这一类方法中,也有风格之分。

o. PCA 降维
在Fisherfaces中采用的就是先用PCA降维,再用LDA,这也是现在处理这一问题的一般方法。这里有个比较讽刺的事情。Belhumeur在他的论文里说:PCA actually smears the classes together。那末既然smears the classes together,既然PCA破坏类的结构,那为什莫还要用PCA降维?而且事实证明,即使在Sw可逆的情况下,用PCA features也会增强LDA在人脸识别中的性能。这里只能说明,PCA的作用或是PCA features并不是Belhumeur和其以后follow这样说法的人叙述的那样。PCA虽然简单,但是人们应该对它有个正确的认识,这个以后如果有机会再谈。

a. RDA
至今影响最大最实用的还是基于regularization思想的RDA。其实这个问题不仅仅在人脸识别中才被注意到。很早在统计中就被解决过,RDA发表于1989的Journal of the AmericalStatistical Association杂志上,可见其久远。在Sw上加一个扰动项也是解决这一问题的最简单方法。

b.子空间投影
论文最多的也就在这一块。应用knato类似的排列组合方法,令image(Sw)和null(Sw)分别表示Sw的列(像)空间和零空间,则我们可很容易的就列出如下组合方法 (强调:这里却不是提供给大家发论文的方法论,而是以较形象的方式叙述!)把样本投影到aa. image(Sb), bb. null(Sw), cc. image(Sw), dd. image(Sw)+null(Sw), ee. image(Sb)+null(Sw) 可并列可串行, ff.image(St)+null(Sw)
以上每一种组合就代表不止一篇论文,在此就不详细列举了。另外,你还可以把random sampling技术加进来,这样就可以不止翻倍。还有,你还可以把同样的技术用到KPCA KLDA(kFA)上,这样又可翻倍。更进一步,你还可以把ICA,LBP, Gabor features等诸如此类的东西和以上子空间混合,...,子子孙孙无穷尽焉。把这个东西做到极致的是国内的 YANG Jian。另外香港中文大学的 TANG Xiaoou 和他以前的学生 WANG Xiaogang 也做这相关的工作,但是他们做一个idea就是一个,没有灌水之嫌。YANG Jian的工作可以用他在TPAMI上的 KPCA plus LDA 这篇文章来概括,虽然他灌水无数,但就子空间方法而言,他这篇文章还有他发表在国内自动化学报上的那篇长文还是有东西的。如果你想做这一块的工作,值得看一看,是个较为全面的总结。TANG Xiaoou在子空间方面的代表工作(开山之作)就是dual spaces LDA, random sampling (and bagging) LDA, unified subspaces。(在此之后他还有学生一直在做,就不详细列举了。)

我建议想做这一块工作的同学们,要把TANG and YANG的工作烂熟于心,取长补短,相互学习,取其精华,这样可以较为快速而全面地掌握。

c. QR分解
矩阵和数值功底比较好的人,能做得更像模像样。Cheong Hee Park 和 YE Jieping 无疑是这方面的高手。去看看他们在TPAMI,JMLR, 和SIAM的J. Matrix Anal. & Appl上发表的论文可知一二。

d. 相关性
如果Sw可逆,则Sb*u=Alpha*Sw*u可以转化为 inv(Sw)*Sb*u=Alpha*u。那末就可以考察Sw的子空间和Sb子空间的相关性。这方面的代表工作就是Aleix M. Martinez在TPAMI上长文的那个工作。

e. 变商为差变u'*Sb*u/(u'*Sw*u)为u'*(Sb-Sw)*u。

3)基于图像局部结构的方法

这一类获得广泛认可的方法有Gabor和LBP,另外还有可能有用的SIFT和differential features。
Gabor应用比较早有影响力的代表作就是EBGM。Gabor也是提取用来识别的visual feature的最常用手段。
有无数人因为LBP的极其简单而怀疑它的性能,但是有趣的是最近Ahonen在TPAMI上的短文,就是把LBP应用在人脸识别上,没有任何新的改进,这也说明Reviewer们和editor对这类方法的肯定和鼓励。在非监督feature extraction中,LBP有明显的优势,但是绝对没有达到作者在论文显示的那个水平。在他的论文中,LBP特别weighted LBP效果非常好,这和他们应用的FERET人脸库的人脸crop形式有关。他们应用CSU的椭圆模板来crop人脸,如果应用正方形的模板weighted LBP提高很有限。特别在FRGC Version 2上测试,LBP绝对没有一般监督性的识别方法好。另外这也给我们一个小小启示,就是加个weight其识别性能就能大大提高,这说明什莫问题呢?

另外我不敢苟同j.liu在他文章说的LBP对image blocks大小不敏感是个美丽谎言的说法。首先,有一定的敏感性,这个是要承认的。但是LBP有一个性能稳定的image blocks,并不是人们认为的histogram要符合一定的统计性等等。这个block size的选取比最优的PCA主元数目的选取要容易得多。当然这些都是小问题。

国内有人做Gabor和LBP的结合。当然是值得探索的,但是我个人认为不应该在这两种方法结合上花费太多精力。完全可以用类似形式考虑别的思路。

4) Sparse representation

NMF和NTF都属于sparse representation的方法,都曾被应用在人脸识别中,但效果都非常有限。特别是NTF,属于数学理论上非常优美,但是实际效果很勉强的典型。

另外,Sparse representation (coding) 是一个很有趣也是很有前途的方法,Sparse representation 有很多方式,关键要看你怎莫用、解决怎样的问题。过段时间我们还有机会再谈。

5)Tensor方法

Tensor在人脸识别中至少到现在为止,还非常得不成功。最典型的就是M. Alex O.Vasilescu在ECCV'02上的tensorfaces。他们对于问题的分析和tensor的对应天衣无缝,非常有道理,数学实现上也同样简单,但是自从那个方法发表出来以后基本无人follow。究其原因,个人认为就是把本来简单的问题复杂化,最重要的就是复杂化以后并没有带来该有的益处。

Alex对tensor的应用是flattening high-way tensor。这是一种常见的处理tensor的方法,这样做的好处就是使tensor好处理易于计算。two-way tensorfaces就是我们理解的Eigenfaces。但是同样是tensor,这种tensor和Amnon Shashua的NTF有着本质的区别。NTF是纯正的tensor思想。但是它实现起来过于复杂,又加上原理比Alex的tensor更复杂,所以无人问津。但是不可否认,它们都是数学上十分优美的方法。如果你想学习tensor而又不想枯燥,我推荐你去看这三篇论文(Shashua两篇)。

6)参数模型
参数模型的应用也多种多样,比如HMM, GMM等。这两个都是一般性的建模方法,所以应用也很庞杂,而且在人脸识别中的应用大多是从speech recognition中的方法转化而来,在此就不多谈。有兴趣的同学们可以参看H. Othman在PAMI上的论文和Conrad Sanderson在PR上的论文。

但是在此其中,最简单的是Baback Moghaddam在TPAMI上那个Probabilistic Subspaces的文章,这个文章也是WANG Xiaogang的unified spaces的参考原本。

7) 3D 模型

代表作是Volker Blanz在TPAMI上的那个文章。不过个人十分不看好。

8)Personal Perspectives

a. 基于子空间的方法很难在实际应用中有所用处

b. 基于找图像局部结构的方法更有希望。像EBGM, LBP, SIFT之类可以给我们很多有益的启示。这点和j.liu的观点一致。

c. 把人脸识别中的方法推广开来,应用到一般的分类和统计问题中,这也是人脸识别衍生出来的一大作用。

d. 由于我们国内的特殊研究环境,大家一般都喜欢做简易快的工作,所以人脸识别这一领域出现有华人名字的论文为数可观。其实在某些压力之下这也无可厚非,但是还是希望我们国人在有条件的情况下,不要以发论文为主,多关注于解决问题本身、尽量向推动理论发展的方向努力。我们绝对有这个能力。君不见,NIPS‘06两篇Best student paper被在国外留学的中国人获得,CVPR'07更是又传来喜讯:Best student paper由清华学生获得,这些都是迹象。我们正处于一个意气风发、大有可为的时代。就本人学术水平和资历来说,绝没有资格来说这些话,这只不过是个人的一点心愿和号召而已,同时更是勉励自己。


以上均是dodo个人拙见,囿于本人才疏学浅,难免出现挂一漏万和观点偏颇的情况,还请大家及时批评指正,以免曲彼误人。谢谢


dodo: 人脸识别 II

这篇文章是接着《dodo:人脸识别方法个人见解》,之所以没有用《dodo:人脸识别方法个人见解 II》,仅仅是因为prfans显示的标题较短,为了使大家便与区别,就用了一个醒目的短标题。

这个帖子主要是谈谈在上一篇中没有谈到或是一带而过的问题。和上一篇一样,还是就方法论方法。


1,kernel methods

a. KPCA及其相关

kernel席卷PAMI领域的趋势还在加强。原因很简单,绝大多数的问题都能和kernel挂上钩。在人脸识别里,KPCA和KFA的影响力远不及PCA和LDA。就应用领域来说,KPCA也远没有PCA应用的广泛。YANG Jian在PAMI上的那个KPCA plus LDA就是子空间和kernel结合的典型论文。如果用作一般性的降维KPCA确实会比PCA效果好,特别是你用的feature空间不是一般的欧式空间的时候更为明显。所以,把LDA用在KPCA变换的空间里自然会比用在PCA变换的空间里效果好。但是就降维来说,KPCA有一个严重的缺点,就是由它不能得到一个可表示的子空间,比如PCA也可以得到一组正交基作为表示基。当然,这也是kernel方法的本质属性导致的。这样就会限制kernel方法的应该范围。举个简单的例子,有人做过用PCA来给SIFT特征降维的方法,也就是那个SIFT+PCA,但他们没有用KPCA+SIFT。就原理上来说,KPCA更适合给SIFT降维,但是在实际应用中,对于SIFT来说,如果需要降维的话,用来降维的东西必须事先学好,PCA就可以事先通过大量的自然图片来学习一个子空间。但是,KPCA做不到。虽然有out-of-sample的方法,但是这种方法有明显的缺点:如果训练样本过大,KPCA的kernel矩阵就很大,这样就很不方便应用,如果过小,效果又不好。其实这也是这类kernel方法的通病(不是一般)。

b. regression

regression也是分类常用的一种方法。CVPR'07就有一篇Kernel ridge regression。regression用来分类的原理很简单,但是他和传统的LDA等类似的方法有着明显的区别。就ridge regression来说,它就是要找一个变换,使样本在变换后的空间里和他们本身的label尽量接近,那末这个学到的变换就在最小二乘意义下尽量好的刻画了样本空间的类结构。一般的,对变换函数(离散就是向量或是矩阵)做一个l2范数上的限制,美其名曰保证函数的smooth(这个下面还会再谈)。这样就可以得到一个形式上较为美的闭解。其实根本不用kernelizaton,regression本身就可以和kernel直接挂上钩,因为求出来变换矩阵在一定限制下就可以看成kernel矩阵(YE Jieping CVPR‘07的metric learning中就用到了类似的思想)。这个和用graph Laplacian做ranking的方法非常相似。Laplacian(或是其简单变形)的逆矩阵如果是正定的,那末就把这个逆看作kernel矩阵。那末和kernel直接相关的方法和思路就用上来了,特别是learning中,种类繁杂。

把ridge regression核化的全部技术含量就在计算的trick上。由于把样本映射到Hilbert空间中只是一个虚的表示,在出现内积的情况下才能写成现实的表达式,所以对于kernel方法来说,计算上的trick要求就比较高。但是,往往这类trick都是在统计和矩阵早已被解决的问题,所以大部分工作就是怎样用好而已。

像这样“借壳还魂”的做法,在很多理论的研究上都非常重要。我们要达到我们的目的,但是这个东西又不是直接可表达的,那末就可以把它放到一定的空间中,按照这个空间中的基本原理来计算,最后到达一个可以表达的形式,而且是按照你的idea来推导的。这种东西一旦做出来,质量还不低。

2,regularization

虽然名字叫regularization,其实就想谈谈优化目标和优化约束问题。如果你看了ICML'07,CVPR'07和即将出炉的ICCV'07,你就会发现07年是个不平凡的一年,降维领域有点混乱。或者说自从97年以来一直就没有平静过,都是Fisherfaces惹的祸:)

还记得knato回帖中斗胆列出的排列组合吗?如果不记得暂且去温习一下,因为我要用一把。把knato列出的不同排列组合加上如下regression一个的一个优化||Y-W'X||^2,就可以概括所有今年的和这类相关论文的思想。然后,如果你愿意,你还可以衍生出很多。优化目标确定以后,所不同的就是求解方法。你可以带着这个观点再去看一下今年的论文,了然于胸。

由此,线性降维的混乱过程经历了一个小小的转折————从子空间组合到优化目标和优化约束的组合。子空间主要集中在1998--2005(当然还不会消失),后一种在今年可以说是达到一个小小的高潮。如果再加上应用算法的策略,就形成了乱世中的三足鼎立局面。特别是后一种,往往穿插出现,而且有待加强。这其中的代表人物 TANG Xiaoou, YANG Jian, YE Jieping, HE Xiaofei,YAN Shuicheng。导致这一变更的主要因素来源于非线性方法的应用,特别kernel和manifold learning的线性化应用。这其中LPP起了很大的刺激作用,个人认为,这也是这个方法的最大意义所在。

如果你能站在一个高度(一定范围内)看待这些东西,那末当你面临毕业出国压力时,你就可以“察若水三千,得一瓢饮”来缓解压力。而且还可以尽量饮得好水。(再次郑重声明:这不是发这个帖子的原意。)

3,子空间方法中常用的计算技巧
a.
关于这一块的东西,Stan Z. Li编辑过一个小书挺好的,可以通过下面的网站找到。http://www.face-rec.org/
不过,我想谈谈规律性的东西。这其中涉及到的东西就是 column (range) space, nullspace, generalized inverse。这些东西都和QR分解,SVD或是GSVD相关。遇到这些东西,就想起他们准没错。如果你有兴趣,可以看看YE Jieping和Haesun Park关于子空间的论文,都是一个模式。

b. 正交化
从发表的论文来看,对于广义特征值问题,如果求解一组相互正交的基,比B-orthogonal效果要好很多。代表作就是CAI Deng的orthogonal LPP和YE Jieping的 orthogonal LDA。

CAI Deng做了一个orthogonal LPP发在TIP上。他用的就是88年发在TPAMI上的方法,原理一模一样。YE Jieping用的是同时对角化三个矩阵。风格不同,各有长短。个人还是倾向于CAI Deng用的那个方法。


4,Tensor revisited

在上一篇中,我谈了tensor的方法,主要说了tensorfaces和NTF。这里再多说几句。

最近在tensor方面功夫最多的是YAN Shuicheng,最近的TPAMI, TIP, 和 CVPR'07都有他与此相关的文章。个人认为,这对发文章有帮助,对于解决问题帮助不大。不过,这对于发扬和推广tensor的思想和方法确实是个好事情,我是赞同探讨的。
另外,HE Xiaofei和CAI Deng也做过tensor subspace。准确地说,他们只是借用了tensor的概念,并不是正宗的tensor方法。他们的方法可以和2D PCA, 2D LDA归为一类。

其实做这一块东西最早的是YANG Jian的一个大师兄,在90年代PR上的工作,后来YANG Jian把它发扬光大,最初的结果就是PR和TPAMI上各一篇短文(2DPCA)。
最早把这类东西以tensor形式呈现的是CV中的大牛Amnon Shashua在01年CVPR上的论文,有兴趣可以看看。不过,大牛终究是大牛,当他听说了NMF以后,NTF立马横空出世(ICML'05)。这个中间的变化是质的跨越,能做出前面那种方法的可以说非常之多,能做出后面那种方法的真是寥寥。这是值得我们好好学习的。
(B.T.W.,Amnon此人并不只是学术了得,其妻子是以色列小姐,again,也值得大家学习的榜样,特别是整天闷头做科研的我们)

在这里要强调的是,我们不能完全否定一些简单的东西,上轨道的或是正宗有深度的方法往往就是这样慢慢做出来的。所以,我们也不要轻易去否定HE Xiaofei和CAI Deng在这一块做的东西。


5,其它

关于kernel的方法我就是点到而止。在上一个帖子中有人提出说说SVM和Boosting,如果谁有兴趣,可以谈谈。

另外也有人说在上一个贴中我漏掉了Bayesianfaces,实际这个就是我在参数模型中提到的Probabilistic Subspaces方法。有兴趣可以看看。


结束语

纵观PAMI领域困扰纷争,虽然我们达不到“跳出三界外,不在五行中”的境界,但是至少我们可以更好的看清楚这个领域的情况。如果你能站在一个高度看待这些东西,你就有可能认清你自己认为有希望的方向在哪儿,从而更准确地找到自己的目标而少走弯路,或是更好地给自己定位。

写这些东西,就是想帮助了解这一领域的人能全面准确地了解这一块的东西,少走弯路。另外,对于已经谙熟于心的人,激发一个讨论的话题。在上一篇贴子中,看贴的人多,回帖的人少,这个现象可不好。欢迎大家踊跃发言,良性讨论,这样才会带来更多益处,千万不要担心自己是新手,越是新手越需要发言。

俗话说:“乱世出英雄”,当今在PAMI领域正是需要英雄的时机,就是我在I中说的“我们正处在一个大有可为的时代”,希望下次力挽狂澜的是华人的名字。

以上尽是一家之言,欢迎大家批评指正、主动参与讨论。

2007年6月19日星期二

Doubt about ETS

I think no body will doubt that ETS has wasted a lot of precious time of our Chinese students. Due to the limited number of seats for Tofel in the mainland of China, all the seats have been taken up in the first few days when ETS announced access to the web-based register. Then, of course, a lot of misfortunates who are eagle for exams have to take their chances to look up ETS's website for seats and information constantly. I am just one of them~
This noon, ETS again announced the additional seats for Tofel for the next half of year. It was a good news. However, we were too worry to miss the chance again, that all of us rushed to take the seats and nearly cracked down ETS's servers, which in consequence, made register rather a tough and boring issure, for we were frequently notified that "The server is disconnected".
Finally, after neary an hour of efforts, I've fortunately enough to finished the register and was rather tired of the whole thing. Behind me, many other students were still on the process. God bless them!
The whole thing seems to me just like a funny joke, and I strongly doubt the ability of ETS on this issue. I concede that someone played a bashful role(those took up some seats at first and sold them at high price later!). But, if ETS had foreseed this scenario and taken som measures, for example, adding more seats, then I think, it would save a lot of time and efforts of the our Chinese students!

2007年6月14日星期四

Rainy June

Rainy June, rainy in the sky, also rainy in my heart.

video format conversion

These two days, I developped a library to convert YUV format to RGB, and vice visa. The core algorithm is based on ccvt's codes. But I found the interfaces provided by ccvt are not sufficient, and also contain bugs. So I sat down to analyse the YUV formats(420p, 420i, yuyv), program and debug. Finally a satisfying library is avaliable which is quite easy for use.
The algorithm itself is very simple, but debugging is not so easy a thing. You have to design special routines to expose the errors. The problem is, programmer may always presumes some "facts" or "certainties" which are total error in essence. And sometimes, the code's behavior depends on the dataset fed to the program. All these add to the difficulty of code testing. I've spend neary 3/4 time on testing and debugging~~

2007年6月7日星期四

tips on efficient program

How to write elegent, efficient program is, nearly, all the programmers' desires and dreams. But how to make your program run faster or more efficiently, generally is beyond our ken. On some occasions, it's the very fact that an expert's hunch leads him to tune some codes which turns out to hit the point! But with the increasing complexity in modern compilers, it's much harder for us to "guess" the bottleneck of the program, without the help of profiling tools. Though we can rely on these profiling tools, however, they only tell us where the bottlenecks may lie by lots of datas, yet we have to figure out the reason in the background. If you can do so, then you must be satisfied with yourself, and say, "hei, look, I know the whole thing now!"

I'll give an interesting example below to test your ability on code optimization. The original code came from Mr Mao. Thanks him for the code !

#define NN 5000000

idata = new unsigned char [NN];
odata = new unsigned char [NN];

N1 = (int)(sqrtf( N ));
total = N1 * N1;
Table = new int [total];
for ( y = 0; y < N1; y++ )
for ( x = 0; x < N1; x++ )
{
x1 = ((a*b+1)*x+a*y)%N1;
y1 = (b*x+y)%N1;
Table[j++] = y1*N1+x1;
}

/* code one */
for ( j = 0; j < total; j++ )
{
tp = Table[j];
odata[tp] = idata[j];
}

for ( j = 0; j < total; j++ )
{
tp = Table[j];
idata[tp] = odata[N-1-j];
}

/*code two */
for ( j = 0; j < total; j++ )
{
tp = Table[j];
odata[j] = idata[tp];
}

for ( j = 0; j < total; j++ )
{
tp = Table[j];
idata[j] = odata[N-1-tp];
}

then can you tell me the difference between the two pieces of codes? which one is more efficient, and why?