xulihang's blog 2020-07-04T04:23:54+00:00 xulihanghai@163.com 找工作 2020-07-04T02:50:50+00:00 xulihang blog.xulihang.me/job-seeking 找工作不是件容易的事情,我去年夏天才开始了解社会提供的岗位,一直到现在也不能确定我到底适合什么岗位。

我在几个公司做翻译相关的实习的时候,因为能够发挥所学,与同事相处也比较愉快,其实还是挺开心的。但找正式的工作和实习还是有差别的。找实习是为了完成学业要求,寻找论文选题,钱多钱少也无所谓。但找正式工作,还是得考虑薪资、福利和城市等一系列因素。

在找工作时我会考虑以下因素:

  • 工作的价值和内容(与个人性格、身体条件、理想和技能的匹配度)
  • 长期的发展(个人成长、发大财的可能)
  • 部门氛围、同事和直属领导
  • 工作环境,公司是不是大公司
  • 上班时间、是否需要长期用眼
  • 薪酬(月薪年薪、五险一金、补贴、期权)
  • 城市(离家远近、家人和朋友、房价)

有人说工作主要是为了赚钱,我觉得发现赚钱的门道得对社会的方方面面有一定的认识。所以我会看一些社会制度、时代背景、相关行业的文章与新闻。找工作时,想找有发展前景的行业。但了解一个行业不是一件容易的事情,招聘网站上的工作这么多,涉及这么多行业,我每个都研究一下的话需要耗费相当多的时间,而且网上的资料都是二手资料,道听途说,很难做出正确的判断,而作为应届生,而且是在2020疫情年,也很难再通过实习去进行了解。

了解岗位信息,我主要通过以下方式:

  • 公司自己的招聘站点、宣讲会
  • 各大招聘网站,智联招聘、应届生、前程无忧、领英和BOSS直聘
  • 知乎、看准、牛客和学校BBS,用于了解网友对公司和行业的评价
  • 学校的就业信息网站
  • 地方的招聘网站

我找工作日子就是每天刷这些平台,然后投简历。

简历我是在超级简历网站上做的,生成了一份格式比较简明的简历,投递不同岗位时会做点修改,但其实我这方面做得比较随意,也没有按什么STAR方法去写工作内容。

以我的学校背景,通过简历还是不难的,但我秋招时投递的岗位不多,我对秋招的准备也不够,不知道有哪些岗位适合我,开始的晚也错过了很多招聘(九月底了,同时还要论文开题)。我投了银行总行、新华社、互联网公司和运营商的翻译岗、管培生岗,但从没想过做技术,没有相关的实习,也没有系统学习主流技术和刷题,所以也没有投技术相关的工作。我一心还是想做与翻译相关的工作。

秋招时我还嫌公司的考试题目无聊,行测类的题目和我的专业知识毫不相关,心理测试几百道题目,每个公司都要做一遍。还有现场考试,都是在北京的郊区,我从六道口过去都太远。

海康威视让我去杭州面试技术文档写作,我觉得文档写作是个辅助性质的岗位,而且他们都没有一对一通知我,就没有动力从北京跑去杭州面试了。

金山的管培生岗位,我跑到小米的新园区,第一次参加群面没啥经验,后来通知没过。

新华社参编部的外文编辑岗位,我看了新华社翻译编辑相关的书后还是挺感兴趣的。它的笔试是中英互译和写议论文,内容是弹劾特朗普、新疆暴恐以及快递,就像本科的英语考试一样,我的笔试成绩还是不错的,进了面试。但面试后也没有进一步通知了。

然后都说选调生好,我也报了浙江选调。公务员考试题目是行测和申论,我对这些题目不是很感冒,虽然研究了下觉得这类设置和日后工作是很有关联的,最后我报的岗位,30名里成绩排了15。公务员题目中的阅读材料还是挺有意思的,我了解了隐形冠军之类的概念。

我对出版行业还是比较感兴趣的,但出版公司的校招岗位不多。在北京的我嫌工资太低就没投,只投了浙江出版集团的,但没有后续通知,可能他们更倾向于有工作经验的编辑吧。

我的专业是个交叉学科,的确不好找工作,英语没有继续专门学英语的同学好,计算机也没有科班同学好。我写的软件让我积累了工程实践经验,但用的技术不是主流的,而且编写翻译软件主要是熟悉了专门的业务,在技术上没有特别的钻研。

时间一晃都要年底了,我又在前程无忧上投了老家银行管培和一些北京事业单位的岗位。

回家后去银行面试,先是群面,然后是单面。群面讨论如何设计一款老年人专用水杯,感觉就像小学时和同学一起做手工。最后通过了。

小米的内容办招本地化工程师,部门的人联系了我。华为也通知我面试技术翻译工程师。我发现这两个岗位的招聘者对我以后要做的工作不能给出确切的说明。招聘者问我自己对以后日常工作的设想,可能是他自己也不知道。

小米和华为这样的公司,其实内部的翻译部门不会直接做翻译,主要是承接内部其它部门的翻译需求,找供应商去做,自己只要做好管理就行了。我觉得我其实更喜欢翻译实践,在甲方也没什么成长,就拒绝了。

华为后来还通知我面试行销产品经理,这是个售前岗位,其实挺锻炼人的,但我当时一心在论文修改上面,也拒绝了。

6月答辩通过后,校招的岗位不多了,我在前程无忧、应届生和BOSS直聘上继续找工作。

拿到了商飞上航的软件开发岗位,hr说以后会做翻译相关的工作。

关于找工作相关的文章,比如根据MBTI性格找工作、根据专业找工作还有个人发展的文章,可以参考,但不能一直看这类文章。个人发展的文章说人有想象的能力,可以通过想象来避免走弯路,但工作还是需要实践了才能知道好不好。

其实人类社会虽然复杂,但本质需求就是吃穿住行,满足这些是简单的,人的意义也是自己定义的,不必被社会所局限住。

]]>
写论文 2020-07-01T08:51:50+00:00 xulihang blog.xulihang.me/thesis-writing 本文主要基于我完成北大计算机辅助翻译毕业所需的工程硕士论文的经历展开。

好的开始是成功的一半,选题是论文写作中比较重要的一步。论文的选题来源一般有两种:一种是学生跟着老师做课题、做项目,一种是学生通过实习或者研究发现值得研究的题目。

像北大软微的专业硕士,第一年上课,第二年实习,第三年写论文,论文的选题来源主要是实习。论文可以集中体现硕士阶段的学习成果以及学生的研究能力,学校据此来决定是否授予学位。

我在公司实习的时候接触了漫画翻译项目,编写了辅助翻译工具,自然而然地,我的论文题目就是漫画翻译辅助工具的设计与实现了。

但要写论文,有实际的应用需求是一方面,同时也要考虑学术价值和过往的研究。老师一般要求学生在开题之前做好文献综述工作,确定题目可行。有的老师会要求开题前阅读数百篇文献,并写出选题表。

我认为,在刚开始的时候,学生可能只是给论文确定了一个大方向,对自己要做的事、创新点还存在模糊不清的地方,而随着研究的深入,会有拨开迷雾见青天的感觉。当然结果也可能是发现研究无法进展下去,比如一些假设性的需要实验的研究,实验结果表明假设错误,又或者论文提出的方法的结果没有突破性的进步,那可能就要重新换题目了。

我的论文是一篇工程设计类的文章,紧接着开题进行的工作是论文写作中最有意思的地方,阅读有关文献,编写程序,收集数据,不断实验,不断完善。

程序运行良好后,则进入较为枯燥的论文写作过程。软件工程的文章一般有固定的章节安排,即绪论-文献综述或者相关技术介绍-需求分析-系统设计-系统实现-系统测试-结论。把论文的问题、前人工作、自己的工作和结果用文字和图片讲述清楚。

硕士论文的字数一般有3万,篇幅较长,需要注重前后的逻辑关联。说实话,其实一段话的组织,要符合逻辑(文字表达、文字顺序等等能体现逻辑)都不是一件容易的事情,饶是我这样平时经常写博客的,写起来也会有很多问题。毕竟写博客是比较随意的事情,论文要求科学严密,同时也不能太具有文学性。

于是论文写出来后,还要不断修改完善,并纠正所有存在错别字和排版错误的地方。

此外,论文写作过程中,需要多和导师以及同学沟通,及时发现自己存在的不足。

论文写好后,光自己觉得好还不行,最终能不能通过还得由老师来做评定。其实对自己的成果有信心是不用担心的,但毕竟论文通过与否掌握在别人手中,会因为不确定性而担心。

评审通过后,根据老师的意见进行修改,之后再进行答辩,答辩通过后提交进一步修改的论文,差不多论文环节就可以结束了。

悄悄说:致谢是论文中可以自由发挥,也是非专业人士都能看懂的一部分,我看别人论文一般会看看致谢

我的时间节点:

  • 6-9月 论文选题
  • 9-10月 论文开题
  • 6-2月 读文献、做实验、写程序、写初稿
  • 3-4月 和老师同学沟通,修改和完善论文,提交终稿
  • 5-6月 根据论文评审意见修改论文、答辩

相关链接:

]]>
论文评审 2020-06-30T13:06:50+00:00 xulihang blog.xulihang.me/thesis-review 硕士论文写好后需要交由评审老师进行评审,一般会按写作内容、排版等分项进行打分,并给出修改建议。结果可以分为直接进入答辩、修改后进入答辩和拒绝进入答辩等等。

硕士研究生们花了1年时间写的论文,当然希望能够通过评审进入答辩,但送到评审老师手上时,感觉命运掌握在了别人的手理,不免惴惴不安。自我评价是容易的,而且一般评价会较好。而他人评价存在不确定性,像硕士论文,可能评审老师对自己的研究内容和价值并没有深刻的了解。

得知通过评审后,发现评审老师还给出了十几条修改意见。仔细阅读时,发现有几条建议是恰当的,有几条则不恰当。研究生自己是最熟悉自己的论文的,而且论文数易其稿后,对自己的论文也会有迷之自信的地方,所以一时间可能会觉得他人的建议无法接受。但大多数时候,仔细研究老师的建议,的确能发现论文的不足之处。只是到了论文的后期,学生就像强弩之末,修改的动力并不强烈了。

]]>
写作与发言的危险性 2020-05-04T12:57:50+00:00 xulihang blog.xulihang.me/writing-and-speaking-are-dangerous 本文的写作主要指较长的书面文本的写作,发言主要指现场的发言和互联网上的帖子等内容。

看了标题,你可能会问,写作和发言有什么危险的,又不像开车、乘飞机,可能出现事故,而且现在都用电脑来编辑文字了,可以不断更新。

首先,人们的生产和生活往往需要根据前人编写的文字来进行。比如汽车、飞机的操纵,需要有技术文档;药物的服用,需要遵循说明书中写的剂量和疗程。操作步骤或者药物的剂量写错了,可能就会危及到人的性命。

然后,人们的日常交流依赖文字,但能用好文字的人不多。首先写作和发言很难表达内心的所有想法,信息的接受者和发出者可能存在信息不对称的问题。然后,人也可能受到背景知识的影响形成主观臆断。此外,人也会比较注意对方说话的礼貌程度。这些都会导致信息被误解。小事还好,顶多争论一番,但也有人会为此搏命。而如果是被认为隐射政权这样的情况,就会出现类似文字狱、批斗这样的事件。

文字的组织通常是会存在漏洞的。我在编写论文的过程中对这一问题有了更深刻的了解。在论文主体完成后,我在词语的选择、段与段的衔接等方面做了很大的改进,同时因为自己对所写内容有了更深入的了解,看到了很多先前表达不正确的地方。而新闻和社交媒体上的文本,因为写作周期短,出错的概率要大很多。

有一个成语叫言多必失,也反应了写作与发言的危险性。但我们不能惧怕犯错或者被人攻击而保持沉默,在合适的时候,我们还是要发出自己的声音。

]]>
使用Git管理Word格式的论文 2020-04-08T12:58:50+00:00 xulihang blog.xulihang.me/use-git-with-thesis-in-word-format 论文是用Word来写的,而且格式是doc,我一直只用备份文件的方法做版本控制。我习惯了使用Git做版本控制,可以查看每次做了哪些修改,但它对二进制格式文件的支持不佳,不能显示修改。另外我一个doc格式论文文档有十几MB大,这样经常提交commit的话git仓库的大小会变得很大。

于是写了个小工具,根据文件修改日期排序文件,然后利用Apache Tika导出文本后提交commit,commit的信息是修改日期。

本来还想导出成HTML或者markdown格式,并对图片进行管理的,觉得比较麻烦就没做。我的目的主要是查看文字变动,如果多了代码看起变动来就比较麻烦。

doc转markdown的相关文章其实我之前也写过:

本项目是用B4J编写的:https://github.com/xulihang/ThesisTrack

网上还搜索到修改.gitattributes和.gitconfig的方法,也是用到了pandoc来转换doc到markdown:git 对 Microsoft Word 进行版本控制

但我不想把二进制文件直接放到仓库里,我考虑用github的release存放重要的论文版本。

好久不更博了,最近写作的时间都花在了硕士论文上面。难得更新的这篇文章也是关于论文写作的。

]]>
图像处理学习——基于OpenCV实例 2020-03-11T13:32:50+00:00 xulihang blog.xulihang.me/learn-image-processing-with-opencv-examples 打算用B4J编写一系列OpenCV示例,用于更好地了解常见的图像处理算法和OpenCV的使用,主要包含ImageTrans用到的操作,会持续更新。

OpenCV函数的具体用法见前文:OpenCV使用笔记

  1. 二值化

    二值化是在灰度图像的基础上进行操作,用一定的阈值对每个像素的灰度进行判断,如果该灰度小于阈值则是黑色,大于阈值则是白色。

    灰度图像可以由RGB图像转换得来,数值在0-255之间,数值越大,亮度越大。

    下面是一个RGB转灰度的公式:

    Gray=(R*299 + G*587 + B*114 + 500) / 1000

    在OpenCV中使用threshold函数进行操作,该函数还支持OTSU和Triangle算法自动计算阈值。

    用PS打开灰度图像,像素的灰度会用K值来表示,这是反映黑色程度的百分值,计算方式:1-灰度值/255。

    B4J项目:threshold

  2. 轮廓检测

    OpenCV使用1提出的改进版边界跟踪(border following)算法进行轮廓检测。

    轮廓检测需要在二值化的图像上进行。什么是轮廓,可以看下面的示例。

    原图:

    轮廓:

    轮廓可以分为两类,一种是外轮廓(outer border),一种是孔洞(hole)。因为OpenCV检测时处理的是白色的像素,所以这里孔洞和外轮廓是倒过来的。

    孔洞:

    外轮廓:

    下面是OpenCV中的用法:

    findContours(img As cvMat,contours As List,hierarchy As cvMat,mode As Int,method As Int)

    mode有四种模式:

    • RETR_EXTERNAL,提取所有外轮廓
    • RETR_LIST,单纯列举出所有轮廓
    • RETR_CCOMP,将轮廓分为外轮廓和孔洞轮廓两种,最内部的轮廓会和最外面轮廓归到一级。
    • RETR_TREE,计算完整的轮廓层级

    hiearchy,包含四种层级信息,分别是:

    1. 同一层级的下一轮廓
    2. 同一层级的前一轮廓
    3. 第一个子轮廓
    4. 父轮廓

    我觉得比较有用的是父轮廓信息,可以据此对轮廓进行分类。

    B4J项目:findContours

    示例程序可以单独查看某个层级的轮廓,便于试验。

  3. 图像修复

    图像修复原理是给出需要修复的图片区域,然后根据区域周边像素对该区域进行复原。一个用途是结合轮廓检测生成文字掩膜,抹除图片中的文字。

    OpenCV中对应inpaint方法。该方法包含在轮廓检测项目中。

  4. 形态学操作

    这里主要指腐蚀和膨胀操作。

    首先取一个核(kernel),也叫形态元素(Structuring Element),进行卷积操作。核的中心点的取值是所在核的所有像素值中最大或最小的那个值,如果取最大则为膨胀操作,最小则为腐蚀操作。

  5. 边缘检测

    边缘和轮廓这两个概念比较接近。我理解轮廓提取的精度更高,边缘则是近似的,表示灰度变化明显的区域。边缘检测能处理彩色图片,可以保留更完整的边缘信息。具体可以看下面的例子,不过边缘检测的结果和阈值的设定有关。

    原图:

    轮廓:

    边缘:

    使用Canny算子检测物体的边缘,该操作有以下步骤:

    1. 高斯平滑用于去除噪点
    2. 计算梯度强度和方向
    3. 非极大值抑制去除非边缘像素
    4. hysteresis阈值处理,输出二值化的轮廓图像,该步骤需要两个阈值,如果像素的梯度高于较大的阈值,则判定为边缘。如果像素的梯度小于较小的阈值则去除。如果在两个阈值之间,那么需要存在相邻的梯度高于较大的阈值的像素。
  6. 连通区域标记

    如果一个像素和它周围的8个像素或者上下左右4个像素的颜色一致或相近,那这些像素就是彼此连通的。

    连通区域标记就是给每个区域的像素进行标记(赋值一个数字),从而知道图中有哪几个连通区域,每个区域对应哪些像素。

    连通区域和轮廓的区别在于,轮廓仅仅是图像的边缘部分。 连通区域标记的算法很多,比较简单的是递归的方法。具体见相关链接。

    连通区域标记和区域生长十分相似,区别在于前者用于检测对象,而后者用于分割图像。

    项目:connectedcomponents

相关链接:

  1. 【数字图像处理】边界跟踪算法
  2. Finding contours in your image
  3. Canny Edge Detector
  4. Eroding and Dilating
  5. 图像分析:二值图像连通域标记
  6. Connected Component Labelling

参考文献:

  1. Suzuki, S. and Abe, K., Topological Structural Analysis of Digitized Binary Images by Border Following. CVGIP 30 1, pp 32-46 (1985) 

]]>
关于视频教程 2020-02-23T01:55:50+00:00 xulihang blog.xulihang.me/on-video-tutorials 最近给ImageTrans写文档,觉得文档虽然可以做到细致的描述,但不如视频演示直观,我决定还是录一些演示视频。因为不单纯是讲操作,我还想把软件的原理讲清楚,所以还涉及一些理论性的内容。

这就带来一个挑战,写文字的时候,我的部分逻辑是跳跃的,期望读者看完文章后能自己琢磨明白我写的内容,发现我遗漏的细节。但视频演示的时候,一环一环都要衔接到位,如果存在模糊和跳跃的地方,会很容易被发现。不过,视频教程其实也不应该事无巨细,而应该挑关键的内容讲。把复杂的事情将清楚。

另外,因为要录五到六分钟的视频,说的时候难免会出错,要么是发音错了,要么是忘记接下来要讲什么,要么是每次录的时候都会临时起意,添加不同的内容,但这内容考虑得并不周全。

其实现实中老师上课就是如此,一点小磕绊、小意外是难免的,但也可能成为课堂的调味剂。而如果是因为备课不充分,就不能忍受,课堂的质量会比较糟糕。

我现在总结下来,操作的演示视频,因为是录制的视频,出现的错误应该比现场上课为少,因为有大量时间去完善。通过一次次的重新录制,最终的视频内容也会趋向完善。录制视频前也应该先写好稿子,并在录制过程中发现可以调整和补充的地方。

视频教程还有一个视频受众的问题,如果软件的适用群体比较广,较难针对群体的特点调整视频内容,所以只能把一般性的内容放上去。如果要做针对性的内容,就得再录过新的视频。

以上内容算是我最近录制视频教程的一点心得。

]]>
图像处理软件的互操作性 2020-02-16T02:30:50+00:00 xulihang blog.xulihang.me/interoperability-between-image-editors 此前的一篇文章提到了CAT工具的互操作性,今天再来说说图像软件的互操作性。

要实现图像软件的互操作性,首先一点是得有一个数据交换格式标准。

CAT工具中,Trados可以说是一家独大,但它仍然遵循XLIFF、TMX等数据交换标准,并且积极地兼容其它CAT软件的格式。而图像软件领域的老大自然是Adobe。提到图像编辑软件,大家会想到Photoshop,但很少知道其它软件。开源领域有不少多层图像编辑器,比如GIMP、Krita等等,但用的人相对少很多。这也使得多层图像的标准格式似乎只有PSD一种。

针对这一问题,Krita和KDE的作者与2006年提出了一种多层图像格式OpenRaster(拓展名ora)。

一个ora文件是一个zip文件,内部的文件结构如下:

example.ora
 ├ mimetype
 ├ stack.xml '描述图像信息的xml文件
 ├ data/
 │  ├ [png格式保存的图层,命名为layer*.png,其中星号是图层的序号]
 │  └ [其它数据文件]
 ├ Thumbnails/
 │  └ thumbnail.png '缩略图,宽和高不能超过256
 └ mergedimage.png '图层合并后的图像

stack.xml示例如下:

<?xml version='1.0' encoding='UTF-8'?>
<image version="0.0.3" w="300" h="177" xres="600" yres="600">
  <stack>
    <stack x="10">
      <stack>
        <layer name="OpenRaster Logo" src="data/hw.svg" x="5" y="5" />
        <text x="50" y="10">Use a Rich Text XML Specification to write cool text in your OpenRaster File</text>
      </stack>
    </stack>
    <!-- filters are syntactically permissible, but not valid for baseline -->
    <layer name="layer1" src="data/image1.png" />
  </stack>
</image>

目前Adobe Photoshop、Gimp和Krita均支持ora格式。但可惜的是,ora格式到现在也只是0.0.5版本的草稿阶段,很多内容都没有制定。比如文字图层就没有得到定义,文字图层都是导出为图像来进行处理的。因为不同软件有着不同的实现,对于图像处理这样的任务,很难制定统一的标准。想实现完全的互操作性是似乎是不太可能了。

在OpenRaster尚不完善的阶段,要想迁移一个软件中的图层到另一软件,可能只有使用脚本了。例如使用Photoshop的脚本将文字图层的坐标、字体设置等信息导出,然后再用Gimp的脚本导回,这个过程当然也需要制定数据交换格式。

相关链接:

  1. OpenRaster Specifications
]]>
纯前端全文检索 2020-02-14T05:25:50+00:00 xulihang blog.xulihang.me/frontend-full-text-search-for-ImageTrans-comics-translation-projects 使用ImageTrans翻译好漫画后需要进行后期的管理和展示。

我预想将其传到Github Pages上,再做几个页面用于浏览和检索。因为不涉及后端,是个纯前端项目,如果做全文检索的话得先在发布的时候创造索引文件供调用。

下面是大致的一个目录结构:

根目录
│  come_to_me_love.itp #ImageTrans项目文件
│  come_to_me_love.itp-images.json #生成的图片列表,排好序的
│  come_to_me_love.itp-doc.json #导出的文本部分
│  come_to_me_love.itp-geometry.json #导出的坐标部分
│  index.json #生成的索引
│  viewer.html #浏览页面
│  search.html #索引页面
│
└─come_to_me_love #图片目录
    │  2.jpg
    │  3.jpg
    │  4.jpg
    │  5.jpg
    │  6.jpg
    │  7.jpg
    │  8.jpg
    │
    └─out #译文图片目录
            2.jpg
            3.jpg
            4.jpg
            5.jpg
            6.jpg
            7.jpg
            8.jpg

我选择lunr.js提供全文检索的支持。lunr.js默认支持多个语种的索引,但并不支持中文,一位网友根据其多语言接口制作了中文支持的库:Add Chinese support,这个库使用nodejieba对中文进行分词。

下面是操作过程:

  1. 首先处理ImageTrans的项目文件,把每个文本框作为一个文档导出为json。有三个属性,名称、原文和译文。名称为用冒号分隔的项目名称、图片名称和文本框序号。

     [
         {
             "name": "come_to_me_love.itp:8.jpg:13",
             "source": "IT WAS THE FIRST TIME, BABy...I...I WANTED TO BUy THINGS FOR yOU! I WANTED TO BE ABLE TO OFFER YOU AS MUCH AS BART!",
             "target": "这是第一次,宝贝,我想给你买东西!我想给你像巴特给的一样多的东西!"
         }
     ]
    
  2. 使用node调用lunr.js生成索引。

    生成索引部分的js:

     var lunr = require("./lunr.js");
     var fs = require('fs');
     require("./lunr.stemmer.support.js")(lunr)
     require('./lunr.multi.js')(lunr)
     require("./lunr.zh.js")(lunr)
    
     var data = fs.readFileSync("./doc.json", "utf-8");
     var documents = JSON.parse(data);
    
     var idx = lunr(function () {
       this.use(lunr.zh)
       this.ref('name')
       this.field('source')
       this.field('target')
    
       documents.forEach(function (doc) {
         this.add(doc)
       }, this)
     })
    
     fs.writeFile('./index.json', JSON.stringify(idx))
    
  3. 检索测试

     var lunr = require('./lunr.js'),
         fs = require('fs');
     var idx = lunr.Index.load(JSON.parse(fs.readFileSync("./index.json")));
     idx.search("moon")
    

    结果:

     [	
         {
             "ref":"come_to_me_love.itp:6.jpg:38",
             "score":3.99,
             "matchData":{"metadata":{"moon":{"source":{}}}}},
         {
             "ref":"come_to_me_love.itp:6.jpg:9",
             "score":3.361,
             "matchData":{"metadata":{"moon":{"source":{}}}}
         }
     ]
    

因为索引文件不存储文本,检索的内容只包含ref信息,不显示匹配的文本。所以我又把文本按项目文件导出,供前端调用。同时,我还把坐标信息导出了,这样浏览图片时可以高亮检索到的文本对应的文本框。

我把上述代码封装为了一个检索页面:http://comics.xulihang.me/search.html

用户获得匹配后,可以点击链接跳转到漫画浏览页面,浏览页面根据name属性跳转到对应的图片。

JavaScript实现的纯前端全文检索还是有挺多的应用的,特别是做成静态页面的技术文档,比如Sphinx、mkdocs都提供全文检索功能。

相关链接:

mkdocs如何支持中文搜索

使用lunr.js为Wiki系统增加全文搜索支持

]]>
使用JavaScript编写Photoshop脚本 2020-02-08T06:56:50+00:00 xulihang blog.xulihang.me/Photoshop-scripting-javascript 之前的文章Photoshop文档本地化脚本已经介绍过如何编写Photoshop的脚本。我这里再针对JavaScript做点补充。

使用JavaScript的好处是跨平台,弊端是不如VBScript和AppleScript那样可以和系统更好地结合起来。

另外,我电脑上装的Photoshop CS3的精简版,没有办法用COM进行调用,装完整版PS的话磁盘空间不够,用JS来写的话,因为是打开PS后选择脚本进行调用,不用考虑COM是否能调用的问题。

首先来一波文档和工具链接:

  1. Adobe ExtendScript API documentation。用在Adobe中的JavaScript叫做ExtendScript,补充了很多API接口,比如本地文件读写的接口。
  2. Learn How to Script Adobe Photoshop CS2,较为全面的教程。
  3. JSON在线工具,查看导出的json时可以使用。

下面是我觉得可以写一下的注意事项:

  1. 默认不支持将JS对象转换为JSON字符串,可以把json2.js下下来include:#include json2.js
  2. 用上述方法调用JSON.stringify不能处理中文,需要将中文做encodeURI处理。
  3. 要注意单位问题,PS中可以以点(point)或者像素(pixel)为单位。

我编写了三个本地化PSD用的脚本(github):

psd2jpg.jsx,遍历某个目录及子目录下的所有PSD文档,另存为JPG
readTextLayers.jsx,遍历某个目录及子目录下的所有PSD文档,将所有文字图层的图层名、文字和坐标信息导出为一个json文件
addLayers.jsx,根据ImageTrans导出的数据文件,给图片添加文字层或者用译文替换PSD里文字图层的原文

JavaScript不是我的主力语言,所以折腾起来还是比较费劲。有一款漫画翻译标号工具叫LabelPlus,对PS脚本的利用比较充分。脚本项目地址:PS-Script

]]>