整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

从《拳皇》案看游戏规则设计侵权

从《拳皇》案看游戏规则设计侵权

乐法内参导读:近日,上海知识产权法院(以下简称上海知产法院)审结了围绕两款动作卡牌手游——《拳皇98终极之战OL》(以下简称《拳皇》)与《数码大冒险》产生的著作权侵权与不正当竞争纠纷上诉案。该案的争议焦点之一是有关游戏规则性质的认定。内参叔将以本案为起点,引入网络游戏的规则引发的纠纷问题。

一、案件引入

《拳皇》是由日本SNK官方正版授权,国内游戏公司联合开发的一款以拳皇为题材的手游;《数码大冒险》是由上海羽盟网络科技有限公司(以下简称羽盟公司)开发的一款手游,以幻想的数码世界为背景展开游戏情节。上海知产法院维持一审判决,判令羽盟公司立即停止对《拳皇》游戏的侵权和不正当竞争的行为,并赔偿《拳皇》游戏软件的著作权人――天津益趣科技有限公司(以下简称益趣公司)160万元。

益趣公司参照现行《中华人民共和国著作权法(2010修正)》第3条中关于作品类型的规定,主张《拳皇》属于类电影作品,应当受到《著作权法》的保护。但是,一审和终审法院均未认同这一主张。法院认为《拳皇》游戏整体不能构成连续画面,缺乏电影情节的表达方式,因此不构成类电作品。而对于游戏规则设计、规则界面结构设计、人物属性技能设置等游戏玩法的性质,法院也未认定其受著作权法保护。其中,一审法院认为,《拳皇》游戏的界面、规则说明等内容不构成独创性表达;二审法院进一步说明,益趣公司主张的游戏玩法是基础规则,属于思想范畴,而构成作品的游戏设计应当为具体规则且构成独创性表达。最终,两审法院均认定羽盟公司在游戏规则设计上存在明显抄袭行为,有损益趣公司的智力劳动成果,违背了商业道德和诚实信用原则,构成不正当竞争。

在网络游戏侵权案例中,最为普遍的便是上文所述案例中蕴含的争议焦点——对游戏规则玩法的抄袭。由于此类侵权行为较为隐蔽,业界俗称为“换皮”抄袭,且证明玩法规则的独创性具有一定难度,导致在实际案例中主张著作权侵权的诉讼请求很难得到法院支持。在此情形下,一部分案例通过反不正当竞争的诉求获得了法院的支持。在本文中,内参叔将梳理有关游戏玩法规则的侵权类型和法院认定,并总结目前此类维权面临的困难。

二、获得著作权法保护的游戏玩法规则

与前文《拳皇》诉《数码大冒险》游戏侵权一案(下文简称《拳皇》案)仅判定不正当竞争的判决不同的是,在《太极熊猫》诉《花千骨》游戏案(下文简称《花千骨》案)中,法院认定《太极熊猫》游戏整体画面中游戏玩法规则的特定呈现方式构成了著作权法保护的客体。

太极熊猫是一款大型角色扮演类手机游戏(下文简称RPG)。游戏设定在虚构的伊瓦兰斯大陆上,由于大陆遭到黑暗的侵袭,玩家需要同游戏内置的NPC主人公一同维护和平。玩家可通过收集装备套装、符文合成、炼星等系统来提升角色实力,还可参加实时战场和多人组队副本等日常活动。在玩法本身富有剧情的设定下,游戏玩家可获得沉浸式的视听体验,这与观看电影等视听作品的欣赏体验类似。事实上,在2020年最新修正的《著作权法》中,已用“视听作品”替代了原第3条第6项的“电影作品和以类似摄制电影的方法创作的作品”。这一改动符合当下视听艺术发展多元化的趋势。尽管游戏整体被认定为受著作权法保护的作品,但关于游戏规则是否作为具有独创性的表达而属于著作权法的保护范畴,还需具体分析规则的内容。对此,该案判决提供了详细的判定思路。

首先,判定游戏规则属于思想还是表达的关键是看其对规则的描述是否足够具体。若仅是一般性的、概括性的描述,则此种游戏规则属于著作权法保护范围之外的思想领域。在《拳皇》案中,《拳皇》游戏的著作权人益趣公司提供的证据显示,被诉侵权游戏在游戏规则的文字说明部分和游戏规则的界面部分均与《拳皇》存在多处实质性相似。比如,“拳皇争霸”对应“王者之战”、“终极试炼”对应“数码试炼”;此外,两游戏的“公会”“竞技场”“挑战系统”等界面包括的细节设计也十分相似。对此,二审法院认定,涉案游戏的规则属于同类格斗类游戏通用的基础规则。至于上诉人主张其游戏中的20个系统设计体现了人物形象、性格、技能等具体的表达,法院则认为具体设计的独创性不能代表整个游戏设计具有独创性,建议上诉人根据具体设计的性质,将其纳入相应的作品类型提出诉讼请求。

那么什么样的规则属于具体规则?在《拳皇》案,二审法院给出的定义为:具体规则系在基础规则的基础上指引玩家行为的一系列机制及机制的组合,使得整个游戏的玩法与其他游戏相比具有个性或特质。《太极熊猫》案中法院则对具体游戏规则给出了更为直观的描述,即游戏规则具体到了一定程度足以使玩家产生感知特定作品来源的特有玩赏体验。此时,游戏规则越过思想与表达的临界点,构成表达。由于《太极熊猫》游戏的设计师通过游戏连续动态图像中的游戏界面,将单个游戏系统的具体玩法规则或通过界面内直白的文字形式或通过连续游戏操作界面对外叙述表达,使玩家在操作游戏过程中清晰感知并据此开展交互操作,因而这样的游戏规则具有表达性。法院还进一步解释,此类叙事性的游戏规则类似于详细的电影剧情,具有传达剧情的效果。

其次,在确认游戏规则属于表达的范围内后,下一步需认定其是否具有独创性。由于无论是网游还是手游,经过多年的发展后逐渐呈现类型化趋势,即一款已有类型游戏的整体玩法系统不大可能从零开始,而是在已有各类游戏玩法系统的基础上,进行模块的选择、组合、以及部分创新。所以游戏中一些部分即使相同,也并不构成侵权,例如公共部分、功能性部分和有限表达部分。这些已经固定类型的玩法规定不能被任何游戏公司垄断,但可以对此类规则的特定呈现方式进行独创性认定,确认其是否产生著作权。

三、游戏规则维权难点和解决途径

结合其他游戏内容侵权案件,内参叔将在本部分探讨游戏规则侵权纠纷中权利人方可能面临的几点困难和解决途径。

首先,根据上一部分的分析可知,和美术作品、故事情节抄袭相比,对挪用游戏规则的抄袭认定不那么容易,因为大多数游戏规则为同类游戏的通用玩法,不能由一家游戏开发公司独占垄断。此时,法院会依据《反不正当竞争法》支持涉案游戏方提出的不正当竞争的诉讼请求。正如在《拳皇》案中,在认定涉案游戏规则是格斗类游戏通用的基础玩法而不构成作品的背景下,法院同时表示,《数码大冒险》就游戏设计具象化后呈现的图形、数字、文字、视觉特效等内容的美术设计的全面替换行为,尽管未构成著作权法意义上的实质性相似,但实质保留了《拳皇》但核心游戏规则,在这点上看,羽盟公司存在明显抄袭行为。二者同为游戏开发公司具有竞争关系,抄袭游戏规则的行为不仅降低了羽盟公司的开发成本,相似的规则还将导致部分《拳皇》玩家流失,导致益趣公司的相关市场受损,属于“不劳而获”型的搭便车行为,构成不正当竞争。

其次,被侵权者维权周期长,司法保护具有明显的滞后性。著作权侵权案件的审判周期普遍在1年以上,这是因为认定侵权行为需对涉案作品进行具体比对,这一环节往往工作量大、细节多。而对于游戏侵权案件,由于涉及软件设计等更具技术性的知识,在确定涉案作品性质、认定涉案作品与被诉作品是否具有实质性相似时,可能还需咨询相关产业的从业人员以提供辅助判断。在大多数手游黄金期只有3个月的背景下,待案件审理完毕,被诉侵权的游戏已完成了利润的积累,停止侵权行为等判决内容无法对开发者产生明显的威慑力。

针对上述维权过程中的两大难处,权利人方可以考虑申请诉前禁令。根据我国《民事诉讼法》第101条的规定,申请保全的利害关系人需满足3个条件:其一,情况紧急;其二,不及时制止将会使申请人的合法权益受到难以弥补的损害;其三,申请人应当提供担保。对于本文涉及的情况,可通过《最高人民法院关于审查知识产权纠纷行为保全案件适用法律若干问题的规定》(以下简称《规定》)第6条中的兜底条款,即“其他需要立即采取行为保全措施的情况”来保护。而对于“难以弥补的损害”的认定,《规定》第10条列举了4种情形,其中第2项“被申请人的行为将会导致侵权行为难以控制且显著增加申请人损害”和第3项“被申请人的侵害行为将会导致申请人的相关市场份额明显减少”可用于游戏规则侵权案例中。

内参叔曰

近20年来,网络游戏逐渐成为主流娱乐方式,为了吸引更多玩家入局,网游开发公司不断创新、为玩家带来新颖有趣的游戏,但其中也不乏试图走捷径、不劳而获的商家,绞尽脑汁“借鉴”已经过市场检验大获成功的游戏模式,通过窃取他人的智力成果来获利。对此,一方面,法律应当提供更为完备的保护,让投机分子无机可乘。另一方面,游戏开发商也应当意识到,拥有自己的智力成果才是提升企业核心竞争力的关键,否则,即便短期内收益不菲,也终将受到法律的制裁,不仅要归还不法收益,“抄袭者”的名头也将为业内人员熟知,实在是得不偿失。

参考文献:

[1](2020)沪73民终33号。

[2](2015)苏中知民初字第00201号案例。

[3]蔡辉:“游戏玩法侵权难界定,四成诉讼流程超一年”,载《南方都市报》,2018年12月20日,转载于GameRes游资网,https://www.gameres.com/832103.html,最后访问日期:2021年3月1日。

来源学会官方公众号:娱乐法内参 yulefaneican 作者:张羽霄

拳皇97OL》是SNK正版IP授权,并拥有《拳皇97》的移动平台游戏改编权。3月12日,也就是今日上午11点,拳皇97OL已经热血首测了,成千上万的玩家都在期待这一佳作,不过结果最终却是好多玩家并不能即时体验到这款游戏,现在测试阶段游戏需要激活码才可以进入,具体游戏要怎么获得激活码呢?不清楚的玩家,跟小编一起来看看拳皇97OL怎么获得激活码?激活码获取途径一览。

拳皇97激活码获得途径:

1、官网直接领取:

进入官网:http://kof.wanmei.com/main.html,点击“快速领号”,填写设备类型和设备系统,最后填写手机号就有一定的概率获得激活码,官方一般都会短信通知;

2、微信领取:

方式一:打开微信--通讯录--添加朋友--输入【拳皇97OL】查找官方公众号--点击关注【拳皇97OL】官方公众号,点击【发号】领取激活码;

方式二:打开微信--发现--扫一扫--扫描下方【二维码图片】--点击关注【拳皇97OL】官方公众号,选择【发号】领取激活码。

好了,以上就是拳皇97OL怎么获得激活码?激活码获取途径一览的全部内容了,希望对大家能有帮助。

更多关于拳皇97OL的其他最新活动资讯,实用攻略技巧,还请玩家持续关注超好玩拳皇97OL攻略<<<<点击!

查 编译整理

量子位 出品 | 公众号 QbitAI

小时候的你在游戏中搓着手柄,在现实中是否也会模仿这《拳皇》的动作?用身体控制游戏角色的体感游戏很早就已出现,但需要体感手柄(Wii)或体感摄像头(微软Kinect)配合。而现在,笔记本就能帮你做到这一切!

最近,有一位名叫Minko Gechev的软件工程师实现了在笔记本上玩《真人快打》(Mortal Kombat),只需要一颗前置摄像头即可。



早在5年前,他就曾展示过体感玩格斗游戏的项目成果:



当时实现方案很简单,也没有利用时下流行的AI技术。但是这套算法离完美还相去甚远,因为需要单色画面背景作为参照,使用条件苛刻。

5年间,无论是网络浏览器的API,还是WebGL都有了长足的发展。于是这名工程师决定用TensorFlow.js来改进他的游戏程序,并在他个人Blog上放出了完整教程。

量子位对文章做了编译整理,主要内容是训练模型识别《真人快打》这款游戏主要有拳击、踢腿两种动作,并通过模型输出结果控制游戏人物做出对应动作。

以下就是他Blog的主要内容:

简介

我将分享用TensorFlow.js和MobileNet创建动作分类算法的一些经验,全文将分为以下几部分:

  • 为图片分类收集数据
  • 使用imgaug进行数据增强
  • 使用MobileNet迁移学习
  • 二元分类和N元分类
  • 在浏览器中使用TensorFlow.js模型训练图片分类

简单讨论使用LSTM进行动作分类

我们将开发一种监督深度学习模型,利用笔记本摄像头获取的图像来分辨用户是在出拳、出腿或者没有任何动作。最终演示效果如下图:



理解本文内容需要有基本的软件工程和JavaScript知识。如果你有一些基本的深度学习知识会很有帮助,但非硬性要求。

收集数据

深度学习模型的准确性在很大程度上取决于训练数据的质量。因此,我们首要的目标是建立一个丰富的训练数据集。

我们的模型需要识别人物的拳击和踢腿,所以应当从以下三个分类中收集图像:

  • 拳击
  • 踢腿
  • 其他

为了这个实验,我找到两位志愿者帮我收集图像。我们总共录制了5段视频,每段都包含2-4个拳击动作和2-4个踢腿动作。由于收集到的是视频文件,我们还需要使用ffmpeg将之转化为一帧一帧的图片:

ffmpeg -i video.mov $filename%03d.jpg

最终,在每个目录下,我们都收集了大约200张图片,如下:



注:除了拳击和踢腿外,图片目录中最多的是“其他”部分,主要是走动、转身、开关视频录制的一些画面。如果这部分内容太多,会有风险导致训练后的模型产生偏见,把应该归于前两类的图片划分到“其他”中,因此我们减少了这部分图片的量。

如果只使用这600张相同环境、相同人物的图片,我们将无法获得很高的准确度。为了进一步提高识别的准确度,我们将使用数据增强对样本进行扩充。

数据增强

数据增强是一种通过已有数据集合成新样本的技术,可以帮助我们增加数据集的样本量和多样性。我们可以将原始图片处理一下转变成新图,但处理过程不能太过激烈,好让机器能够对新图片正确归类。

常见的处理图片的方式有旋转、反转颜色、模糊等等。网上已有现成软件,我将使用一款由Python编写的imgaug的工具(项目地址见附录),我的数据增强代码如下:

np.random.seed(44)
ia.seed(44)
def main():
 for i in range(1, 191):
 draw_single_sequential_images(str(i), "others", "others-aug")
 for i in range(1, 191):
 draw_single_sequential_images(str(i), "hits", "hits-aug")
 for i in range(1, 191):
 draw_single_sequential_images(str(i), "kicks", "kicks-aug")
def draw_single_sequential_images(filename, path, aug_path):
 image=misc.imresize(ndimage.imread(path + "/" + filename + ".jpg"), (56, 100))
 sometimes=lambda aug: iaa.Sometimes(0.5, aug)
 seq=iaa.Sequential(
 [
 iaa.Fliplr(0.5), # horizontally flip 50% of all images
 # crop images by -5% to 10% of their height/width
 sometimes(iaa.CropAndPad(
 percent=(-0.05, 0.1),
 pad_mode=ia.ALL,
 pad_cval=(0, 255)
 )),
 sometimes(iaa.Affine(
 scale={"x": (0.8, 1.2), "y": (0.8, 1.2)}, # scale images to 80-120% of their size, individually per axis
 translate_percent={"x": (-0.1, 0.1), "y": (-0.1, 0.1)}, # translate by -10 to +10 percent (per axis)
 rotate=(-5, 5),
 shear=(-5, 5), # shear by -5 to +5 degrees
 order=[0, 1], # use nearest neighbour or bilinear interpolation (fast)
 cval=(0, 255), # if mode is constant, use a cval between 0 and 255
 mode=ia.ALL # use any of scikit-image's warping modes (see 2nd image from the top for examples)
 )),
 iaa.Grayscale(alpha=(0.0, 1.0)),
 iaa.Invert(0.05, per_channel=False), # invert color channels
 # execute 0 to 5 of the following (less important) augmenters per image
 # don't execute all of them, as that would often be way too strong
 iaa.SomeOf((0, 5),
 [
 iaa.OneOf([
 iaa.GaussianBlur((0, 2.0)), # blur images with a sigma between 0 and 2.0
 iaa.AverageBlur(k=(2, 5)), # blur image using local means with kernel sizes between 2 and 5
 iaa.MedianBlur(k=(3, 5)), # blur image using local medians with kernel sizes between 3 and 5
 ]),
 iaa.Sharpen(alpha=(0, 1.0), lightness=(0.75, 1.5)), # sharpen images
 iaa.Emboss(alpha=(0, 1.0), strength=(0, 2.0)), # emboss images
 iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.01*255), per_channel=0.5), # add gaussian noise to images
 iaa.Add((-10, 10), per_channel=0.5), # change brightness of images (by -10 to 10 of original value)
 iaa.AddToHueAndSaturation((-20, 20)), # change hue and saturation
 # either change the brightness of the whole image (sometimes
 # per channel) or change the brightness of subareas
 iaa.OneOf([
 iaa.Multiply((0.9, 1.1), per_channel=0.5),
 iaa.FrequencyNoiseAlpha(
 exponent=(-2, 0),
 first=iaa.Multiply((0.9, 1.1), per_channel=True),
 second=iaa.ContrastNormalization((0.9, 1.1))
 )
 ]),
 iaa.ContrastNormalization((0.5, 2.0), per_channel=0.5), # improve or worsen the contrast
 ],
 random_order=True
 )
 ],
 random_order=True
 )
 im=np.zeros((16, 56, 100, 3), dtype=np.uint8)
 for c in range(0, 16):
 im[c]=image
 for im in range(len(grid)):
 misc.imsave(aug_path + "/" + filename + "_" + str(im) + ".jpg", grid[im])

每张图片最后都被扩展成16张照片,考虑到后面训练和评估时的运算量,我们减小了图片体积,每张图的分辨率都被压缩成100*56。



建立模型

现在,我们开始建立图片分类模型。处理图片使用的是CNN(卷积神经网络),CNN适合于图像识别、物体检测和分类领域。

迁移学习

迁移学习允许我们使用已被训练过网络。我们可以从任何一层获得输出,并把它作为新的神经网络的输入。这样,训练新创建的神经网络能达到更高的认知水平,并且能将源模型从未见过的图片进行正确地分类。

我们在文中将使用MobileNet神经网络(安装包地址见附录),它和VGG-16一样强大,但是体积更小,在浏览器中的载入时间更短。

在浏览器中运行模型

在这一部分,我们将训练一个二元分类模型。

首先,我们浏览器的游戏脚本MK.js中运行训练过的模型。代码如下:

const video=document.getElementById('cam');
const Layer='global_average_pooling2d_1';
const mobilenetInfer=m=> (p): tf.Tensor<tf.Rank>=> m.infer(p, Layer);
const canvas=document.getElementById('canvas');
const scale=document.getElementById('crop');
const ImageSize={
 Width: 100,
 Height: 56
};
navigator.mediaDevices
 .getUserMedia({
 video: true,
 audio: false
 })
 .then(stream=> {
 video.srcObject=stream;
 });

以上代码中一些变量和函数的注释:

  • video:页面中的HTML5视频元素
  • Layer:MobileNet层的名称,我们从中获得输出并把它作为我们模型的输入
  • mobilenetInfer:从MobileNet接受例子,并返回另一个函数。返回的函数接受输入,并从MobileNet特定层返回相关的输出
  • canvas:将取出的帧指向HTML5的画布
  • scale:压缩帧的画布

第二步,我们从摄像头获取视频流,作为视频元素的源。对获得的图像进行灰阶滤波,改变其内容:

const grayscale=(canvas: HTMLCanvasElement)=> {
 const imageData=canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
 const data=imageData.data;
 for (let i=0; i < data.length; i +=4) {
 const avg=(data[i] + data[i + 1] + data[i + 2]) / 3;
 data[i]=avg;
 data[i + 1]=avg;
 data[i + 2]=avg;
 }
 canvas.getContext('2d').putImageData(imageData, 0, 0);
};

第三步,把训练过的模型和游戏脚本MK.js连接起来。

let mobilenet: (p: any)=> tf.Tensor<tf.Rank>;
tf.loadModel('http://localhost:5000/model.json').then(model=> {
 mobileNet
 .load()
 .then((mn: any)=> mobilenet=mobilenetInfer(mn))
 .then(startInterval(mobilenet, model));
});

在以上代码中,我们将MobileNet的输出传递给mobilenetInfer方法,从而获得了从网络的隐藏层中获得输出的快捷方式。此外,我还引用了startInterval。

const startInterval=(mobilenet, model)=> ()=> {
 setInterval(()=> {
 canvas.getContext('2d').drawImage(video, 0, 0);
 grayscale(scale
 .getContext('2d')
 .drawImage(
 canvas, 0, 0, canvas.width,
 canvas.width / (ImageSize.Width / ImageSize.Height),
 0, 0, ImageSize.Width, ImageSize.Height
 ));
 const [punching]=Array.from((
 model.predict(mobilenet(tf.fromPixels(scale))) as tf.Tensor1D)
 .dataSync() as Float32Array);
 const detect=(window as any).Detect;
 if (punching >=0.4) detect && detect.onPunch();
 }, 100);
};

startInterval正是关键所在,它每间隔100ms引用一个匿名函数。在这个匿名函数中,我们把视频当前帧放入画布中,然后压缩成100*56的图片后,再用于灰阶滤波器。

在下一步中,我们把压缩后的帧传递给MobileNet,之后我们将输出传递给训练过的模型,通过dataSync方法返回一个一维张量punching。

最后,我们通过punching来确定拳击的概率是否高于0.4,如果是,将调用onPunch方法,现在我们可以控制一种动作了:



用N元分类识别拳击和踢腿

在这部分,我们将介绍一个更智能的模型:使用神经网络分辨三种动作:拳击、踢腿和站立。

const punches=require('fs')
 .readdirSync(Punches)
 .filter(f=> f.endsWith('.jpg'))
 .map(f=> `${Punches}/${f}`);
const kicks=require('fs')
 .readdirSync(Kicks)
 .filter(f=> f.endsWith('.jpg'))
 .map(f=> `${Kicks}/${f}`);
const others=require('fs')
 .readdirSync(Others)
 .filter(f=> f.endsWith('.jpg'))
 .map(f=> `${Others}/${f}`);
const ys=tf.tensor2d(
 new Array(punches.length)
 .fill([1, 0, 0])
 .concat(new Array(kicks.length).fill([0, 1, 0]))
 .concat(new Array(others.length).fill([0, 0, 1])),
 [punches.length + kicks.length + others.length, 3]
);
const xs: tf.Tensor2D=tf.stack(
 punches
 .map((path: string)=> mobileNet(readInput(path)))
 .concat(kicks.map((path: string)=> mobileNet(readInput(path))))
 .concat(others.map((path: string)=> mobileNet(readInput(path))))
) as tf.Tensor2D;

我们对压缩和灰阶化的图片调用MobileNet,之后将输出传递给训练过的模型。 该模型返回一维张量,我们用dataSync将其转换为一个数组。 下一步,通过使用Array.from我们将类型化数组转换为JavaScript数组,数组中包含我们提取帧中三种姿势的概率。

如果既不是踢腿也不是拳击的姿势的概率高于0.4,我们将返回站立不动。 否则,如果显示高于0.32的概率拳击,我们会向MK.js发出拳击指令。 如果踢腿的概率超过0.32,那么我们发出一个踢腿动作。

以下就是完整的演示效果:



动作识别

如果我们收集到更大的多样性数据集,那么我们搭建的模型就能更精确处理每一帧。但这样就够了吗?显然不是,请看以下两张图:



它们都是踢腿动作,但实际上在视频中有很大的不同,是两种不同的动作。



为了识别动作,我们还需要使用RNN(循环神经网络),RNN的优势在处理时间序列问题,比如

  • 自然语言处理,词语的意思需要联系上下文
  • 根据历史记录,预测用户将要访问的页面
  • 识别一系列帧中的动作

若要识别动作,我们还需要将数帧画面输入CNN,再将输出结果输入RNN。

总结

在本文中,我们开发了一个图像分类模型。为此,我们手动提取视频帧并收集数据集,将它们分成三个不同的类别,然后使用imgaug进行数据增强。

之后,我们通过MobileNet来解释什么是迁移学习,以及我们如何利用MobileNet。经过训练,我们的模型达到了90%以上的准确率!

为了在浏览器中使用我们开发的模型,我们将它与MobileNet一起加载,并从用户的相机中每100ms取出一帧,识别用户的动作,并使用模型的输出来控制《真人快打3》中的角色。

最后,我们简单讨论了如何通过RNN来进一步改进我们的模型。

我希望你们能够和我一样喜欢这个小项目。

附录:

原文地址:

https://blog.mgechev.com/2018/10/20/transfer-learning-tensorflow-js-data-augmentation-mobile-net/

原动作识别项目地址:

https://github.com/mgechev/movement.js

JS版《真人快打》项目地址:

https://github.com/mgechev/mk.js

imgaug:

https://github.com/aleju/imgaug

MobileNet神经网络:

https://www.npmjs.com/package/@tensorflow-models/mobilenet