如何使用TensorFlow对象检测API播放Quidditch

by Bharath Raj

巴拉斯·拉吉(Bharath Raj)

如何使用TensorFlow对象检测API播放Quidditch (How to play Quidditch using the TensorFlow Object Detection API)

Deep Learning never ceases to amaze me. It has had a profound impact on several domains, beating benchmarks left and right.

深度学习永远不会令我惊讶。 它对多个领域产生了深远的影响,超越了左右基准。

Image classification using convolutional neural networks (CNNs) is fairly easy today, especially with the advent of powerful front-end wrappers such as Keras with a TensorFlow back-end. But what if you want to identify more than one object in an image?

如今,使用卷积神经网络(CNN)进行图像分类非常容易,尤其是随着功能强大的前端包装程序(例如带有TensorFlow后端的Keras)的出现。 但是,如果您想在一个图像中识别多个对象怎么办?

This problem is called “object localization and detection.” It is much more difficult than simple classification. In fact, until 2015, image localization using CNNs was very slow and inefficient. Check out this blog post by Dhruv to read about the history of object detection in Deep Learning, if you’re interested.

此问题称为“对象定位和检测”。 这比简单分类困难得多。 实际上,直到2015年,使用CNN进行图像定位都非常缓慢且效率低下。 如果您有兴趣,请查看Dhruv的这篇博客文章 ,以了解有关深度学习中对象检测的历史记录。

Sounds cool. But is it hard to code?

听起来不错。 但是很难编码吗?

Worry not, TensorFlow’s Object Detection API comes to the rescue! They have done most of the heavy lifting for you. All you need to do is to prepare the dataset and set some configurations. You can train your model and use then it for inference.

不用担心, TensorFlow的对象检测API可以助您一臂之力 ! 他们为您完成了大部分繁重的工作。 您需要做的只是准备数据集并设置一些配置。 您可以训练模型,然后将其用于推理。

TensorFlow also provides pre-trained models, trained on the MS COCO, Kitti, or the Open Images datasets. You could use them as such, if you just want to use it for standard object detection. The drawback is that, they are pre-defined. It can only predict the classes defined by the datasets.

TensorFlow还提供预先训练的模型,这些模型在MS COCO,Kitti或Open Images数据集上进行训练。 如果您只想将其用于标准对象检测,则可以按原样使用它们。 缺点是它们是预定义的。 它只能预测数据集定义的类。

But, what if you wanted to detect something that’s not on the possible list of classes? That’s the purpose of this blog post. I will guide you through creating your own custom object detection program, using a fun example of Quidditch from the Harry Potter universe! (For all you Star Wars fans, here’s a similar blog post that you might like).

但是,如果您想检测出可能不在类列表中的东西怎么办? 这就是这篇博客的目的。 我将通过一个有趣的哈利波特宇宙中的魁地奇示例,指导您创建自己的自定义对象检测程序! (对于您所有的《星球大战》粉丝,这里可能都是您喜欢的类似博客 )。

入门 (Getting started)

Start by cloning my GitHub repository, found here. This will be your base directory. All the files referenced in this blog post are available in the repository.

通过克隆我的GitHub库,发现开始在这里 。 这将是您的基本目录。 该博客文章中引用的所有文件都可以在资源库中找到。

Alternatively, you can clone the TensorFlow models repo. If you choose the latter, you only need the folders named “slim” and “object_detection,” so feel free to remove the rest. Don’t rename anything inside these folders (unless you’re sure it won’t mess with the code).

另外,您可以克隆TensorFlow 模型库 。 如果选择后者,则只需要名为“ slim”和“ object_detection”的文件夹,因此可以随意删除其余的文件夹。 不要重命名这些文件夹中的任何内容(除非您确定它不会与代码混淆)。

依存关系 (Dependencies)

Assuming you have TensorFlow installed, you may need to install a few more dependencies, which you can do by executing the following in the base directory:

假设您已安装TensorFlow,则可能需要安装更多依赖关系,可以通过在基本目录中执行以下操作来完成此依赖关系:

pip install -r requirements.txt

The API uses Protobufs to configure and train model parameters. We need to compile the Protobuf libraries before using them. First, you have to install the Protobuf Compiler using the below command:

该API使用Protobufs来配置和训练模型参数。 在使用它们之前,我们需要先编译Protobuf库。 首先,您必须使用以下命令安装Protobuf编译器:

sudo apt-get install protobuf-compiler

Now, you can compile the Protobuf libraries using the following command:

现在,您可以使用以下命令编译Protobuf库:

protoc object_detection/protos/*.proto --python_out=.

You need to append the path of your base directory, as well as your slim directory to your Python path variable. Note that you have to complete this step every time you open a new terminal. You can do so by executing the below command. Alternatively, you can add it to your ~/.bashrc file to automate the process.

您需要将基本目录的路径以及苗条目录附加到Python路径变量中。 请注意,每次打开新终端时必须完成此步骤。 您可以通过执行以下命令来实现。 或者,您可以将其添加到〜/ .bashrc中 文件以自动执行该过程。

export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

准备输入 (Preparing the inputs)

My motive was pretty straightforward. I wanted to build a Quidditch Seeker using TensorFlow. Specifically, I wanted to write a program to locate the snitch at every frame.

我的动机很简单。 我想使用TensorFlow构建Quidditch Seeker。 具体来说,我想编写一个程序来定位每帧的小节。

But then, I decided to up the stakes. How about trying to identify all the moving pieces of equipment used in Quidditch?

但是后来,我决定举足轻重。 如何尝试识别魁地奇中使用的所有移动设备?

We start by preparing the label_map.pbtxt file. This would contain all the target label names as well as an ID number for each label. Note that the label ID should start from 1. Here’s the content of the file that I used for my project.

我们首先准备label_map.pbtxt文件。 这将包含所有目标标签名称以及每个标签的ID号。 请注意,标签ID应该从1开始。这是我用于项目的文件的内容。

item { id: 1 name: ‘snitch’}
item { id: 2 name: ‘quaffle’}
item { id: 3 name: ‘bludger’}

Now, its time to collect the dataset.

现在,该收集数据集了。

Fun! Or boring, depending on your taste, but it’s a mundane task all the same.

好玩! 还是无聊,取决于您的口味,但这都是一个平凡的任务。

I collected the dataset by sampling all the frames from a Harry Potter video clip, using a small code snippet I wrote, using the OpenCV framework. Once that was done, I used another code snippet to randomly sample 300 images from the dataset. The code snippets are available in utils.py in my GitHub repo if you would like to do the same.

我使用OpenCV框架,使用我编写的一个小代码段,通过对Harry Potter视频剪辑中的所有帧进行采样来收集数据集。 完成此操作后,我使用了另一个代码段从数据集中随机采样了300张图像 。 如果您想这样做,可以在我的GitHub存储库中的utils.py中找到这些代码片段。

You heard me right. Only 300 images. Yeah, my dataset wasn’t huge. That’s mainly because I can’t afford to annotate a lot of images. If you want, you can opt for paid services like Amazon Mechanical Turk to annotate your images.

你没听错 仅300张图像。 是的,我的数据集并不庞大。 这主要是因为我无法注释很多图像。 如果需要,您可以选择Amazon Mechanical Turk之类的付费服务来注释图像。

注解 (Annotations)

Every image localization task requires ground truth annotations. The annotations used here are XML files with 4 coordinates representing the location of the bounding box surrounding an object, and its label. We use the Pascal VOC format. A sample annotation would look like this:

每个图像本地化任务都需要地面真相注释。 此处使用的注释是XML文件,具有4个坐标,分别表示围绕对象的边框及其标签的位置。 我们使用Pascal VOC格式。 注释示例如下所示:

<annotation>  <filename>182.jpg</filename>  <size>    <width>1280</width>    <height>586</height>    <depth>3</depth>  </size>  <segmented>0</segmented>  <object>    <name>bludger</name>    <bndbox>      <xmin>581</xmin>      <ymin>106</ymin>      <xmax>618</xmax>      <ymax>142</ymax>    </bndbox>  </object>  <object>    <name>quaffle</name>    <bndbox>      <xmin>127</xmin>      <ymin>406</ymin>      <xmax>239</xmax>      <ymax>526</ymax>    </bndbox>  </object></annotation>

You might be thinking, “Do I really need to go through the pain of manually typing in annotations in XML files?” Absolutely not! There are tools which let you use a GUI to draw boxes over objects and annotate them. Fun! LabelImg is an excellent tool for Linux/Windows users. Alternatively, RectLabel is a good choice for Mac users.

您可能会想:“我真的需要经历手动输入XML文件中注释的痛苦吗?” 绝对不! 有一些工具可让您使用GUI在对象上绘制框并进行注释。 好玩! LabelImg是Linux / Windows用户的绝佳工具。 另外,对于Mac用户, RectLabel是一个不错的选择。

A few footnotes before you start collecting your dataset:

开始收集数据集之前的一些脚注:

  • Do not rename you image files after you annotate them. The code tries to look up an image using the file name specified inside your XML file (Which LabelImg automatically fills in with the image file name). Also, make sure your image and XML files have the same name.

    对图像文件进行注释后,请勿重命名它们。 该代码尝试使用XML文件中指定的文件名查找图像(其中LabelImg自动填充图像文件名)。 另外,请确保您的图片XML文件具有相同的名称

  • Make sure you resize the images to the desired size before you start annotating them. If you do so later on, the annotations will not make sense, and you will have to scale the annotation values inside the XMLs.

    开始注释图像之前,请确保将图像调整为所需的尺寸。 如果以后再这样做,注释将没有意义,并且您将不得不在XML内部缩放注释值。

  • LabelImg may output some extra elements to the XML file (Such as <pose>, <truncated>, <path>). You do not need to remove those as they won’t interfere with the code.

    LabelImg可能会将一些额外的元素输出到XML文件(例如<pose>,<truncated>,<path>)。 您无需删除它们,因为它们不会干扰代码。

In case you messed up anything, the utils.py file has some utility functions that can help you out. If you just want to give Quidditch a shot, you could download my annotated dataset instead. Both are available in my GitHub repository.

万一您搞砸了一切, utils.py文件具有一些实用程序功能可以为您提供帮助。 如果您只想给Quidditch一炮而红,则可以下载我带注释的数据集。 两者都可以在我的GitHub 存储库中找到。

Lastly, create a text file named trainval. It should contain the names of all your image/XML files. For instance, if you have img1.jpg, img2.jpg and img1.xml, img2.xml in your dataset, you trainval.txt file should look like this:

最后,创建一个名为trainval的文本文件。 它应该包含所有图像/ XML文件的名称。 例如,如果数据集中有img1.jpg,img2.jpg和img1.xml,img2.xml,则trainval.txt文件应如下所示:

img1img2

Separate your dataset into two folders, namely images and annotations. Place the label_map.pbtxt and trainval.txt inside your annotations folder. Create a folder named xmls inside the annotations folder and place all your XMLs inside that. Your directory hierarchy should look something like this:

将数据集分成两个文件夹,即imagesnotes 。 将label_map.pbtxttrainval.txt放在注释文件夹中。 在注解文件夹中创建一个名为xmls的文件夹,并将所有XML放入其中。 您的目录层次结构应如下所示:

-base_directory|-images|-annotations||-xmls||-label_map.pbtxt||-trainval.txt

The API accepts inputs in the TFRecords file format. Worry not, you can easily convert your current dataset into the required format with the help of a small utility function. Use the create_tf_record.py file provided in my repo to convert your dataset into TFRecords. You should execute the following command in your base directory:

该API接受TFRecords文件格式的输入。 不用担心,您可以借助一个小的实用程序功能轻松地将当前数据集转换为所需格式。 使用我的仓库中提供的create_tf_record.py文件将您的数据集转换为TFRecords。 您应该在基本目录中执行以下命令:

python create_tf_record.py \    --data_dir=`pwd` \    --output_dir=`pwd`

You will find two files, train.record and val.record, after the program finishes its execution. The standard dataset split is 70% for training and 30% for validation. You can change the split fraction in the main() function of the file if needed.

程序完成执行后,您将找到两个文件train.recordval.record 。 标准数据集拆分为训练的70%和验证的30%。 如果需要,可以在文件的main()函数中更改拆分分数。

训练模型 (Training the model)

Whew, that was a rather long process to get things ready. The end is almost near. We need to select a localization model to train. Problem is, there are so many options to choose from. Each vary in performance in terms of speed or accuracy. You have to choose the right model for the right job. If you wish to learn more about the trade-off, this paper is a good read.

ew,这是一个漫长的准备过程。 末日快到了。 我们需要选择一种本地化模型进行训练。 问题是,有太多选项可供选择。 每个方面在速度或准确性方面都有差异。 您必须为正确的工作选择正确的模型。 如果您想了解更多有关权衡的知识,可以阅读这篇文章 。

In short, SSDs are fast but may fail to detect smaller objects with decent accuracy, whereas Faster RCNNs are relatively slower and larger, but have better accuracy.

简而言之,SSD速度很快,但可能无法以适当的精度检测较小的对象,而Faster RCNN相对较慢且较大,但具有更好的精度。

The TensorFlow Object Detection API has provided us with a bunch of pre-trained models. It is highly recommended to initialize training using a pre-trained model. It can heavily reduce the training time.

TensorFlow对象检测API为我们提供了一堆预训练的模型 。 强烈建议使用预训练模型初始化训练。 它可以大大减少培训时间。

Download one of these models, and extract the contents into your base directory. Since I was more focused on the accuracy, but also wanted a reasonable execution time, I chose the ResNet-50 version of the Faster RCNN model. After extraction, you will receive the model checkpoints, a frozen inference graph, and a pipeline.config file.

下载这些模型之一,然后将内容提取到您的基本目录中。 由于我更加关注精度,而且还希望有合理的执行时间,因此我选择了Faster RCNN模型的ResNet-50版本。 提取后,您将收到模型检查点,冻结的推理图和pipeline.config文件。

One last thing remains! You have to define the “training job” in the pipeline.config file. Place the file in the base directory. What really matters is the last few lines of the file — you only need to set the highlighted values to your respective file locations.

最后一件事仍然存在! 您必须在pipeline.config文件中定义“培训工作”。 将文件放在基本目录中。 真正重要的是文件的最后几行-您只需将突出显示的值设置为您各自的文件位置。

gradient_clipping_by_norm: 10.0  fine_tune_checkpoint: "model.ckpt"  from_detection_checkpoint: true  num_steps: 200000}train_input_reader {  label_map_path: "annotations/label_map.pbtxt"  tf_record_input_reader {    input_path: "train.record"  }}eval_config {  num_examples: 8000  max_evals: 10  use_moving_averages: false}eval_input_reader {  label_map_path: "annotations/label_map.pbtxt"  shuffle: false  num_epochs: 1  num_readers: 1  tf_record_input_reader {    input_path: "val.record"  }}

If you have experience in setting the best hyper parameters for your model, you may do so. The creators have given some rather brief guidelines here.

如果您有为模型设置最佳超级参数的经验,则可以这样做。 创作者在这里给出了一些相当简短的指导。

You’re all set to train your model now! Execute the below command to start the training job.

您现在就可以训练模型了! 执行以下命令以开始培训工作。

python object_detection/train.py \--logtostderr \--pipeline_config_path=pipeline.config \--train_dir=train

My Laptop GPU couldn’t handle the model size (Nvidia 950M, 2GB) so I had to run it on the CPU instead. It took around 7–13 seconds per step on my device. After about 10,000 excruciating steps, the model achieved a pretty good accuracy. I stopped training after it reached 20,000 steps, solely because it had taken two days already.

我的笔记本电脑GPU无法处理模型尺寸(Nvidia 950M,2GB),因此我不得不在CPU上运行它。 我的设备每步花费了大约7-13秒的时间。 经过大约10,000个步骤,该模型达到了相当好的精度。 达到20,000步后,我停止了训练,这完全是因为已经花了两天时间。

You can resume training from a checkpoint by modifying the “fine_tune_checkpoint” attribute from model.ckpt to model.ckpt-xxxx, where xxxx represents the global step number of the saved checkpoint.

您可以通过将model.ckpt的“ fine_tune_checkpoint”属性从model.ckpt修改为model.ckpt-xxxx来从训练点恢复训练,其中xxxx代表已保存检查点的全局步骤号。

导出模型以进行推断 (Exporting the model for inference)

What’s the point of training the model if you can’t use it for object detection? API to the rescue again! But there’s a catch. Their inference module requires a frozen graph model as an input. Not to worry though: using the following command, you can export your trained model to a frozen graph model.

如果不能将其用于对象检测,训练模型有什么意义? API再次解救! 但是有一个陷阱。 他们的推理模块需要一个冻结的图模型作为输入。 不过不用担心:使用以下命令,您可以将训练后的模型导出为冻结的图形模型。

python object_detection/export_inference_graph.py \--input_type=image_tensor \--pipeline_config_path=pipeline.config \--trained_checkpoint_prefix=train/model.ckpt-xxxxx \--output_directory=output

Neat! You will obtain a file named frozen_inference_graph.pb, along with a bunch of checkpoint files.

整齐! 您将获得一个名为Frozen_inference_graph.pb的文件,以及一堆检查点文件。

You can find a file named inference.py in my GitHub repo. You can use it to test or run your object detection module. The code is pretty self explanatory, and is similar to the Object Detection Demo, presented by the creators. You can execute it by typing in the following command:

您可以在我的GitHub存储库中找到一个名为inference.py的文件。 您可以使用它来测试或运行对象检测模块。 该代码很容易解释,并且类似于创建者提供的“对象检测演示”。 您可以通过键入以下命令来执行它:

python object_detection/inference.py \--input_dir={PATH} \--output_dir={PATH} \--label_map={PATH} \--frozen_graph={PATH} \--num_output_classes={NUM}

Replace the highlighted characters {PATH} with the filename or path of the respective file/directory. Replace {NUM} with the number of objects you have defined for your model to detect (In my case, 3).

将突出显示的字符{PATH}替换为相应文件/目录的文件名或路径。 将{NUM}替换为为模型定义的要检测的对象数(在我的情况下为3)。

结果 (Results)

Check out these videos to see its performance for yourself! The first video demonstrates the model’s capability to distinguish all three objects, whereas the second video flaunts its prowess as a seeker.

观看这些视频,亲自体验一下! 第一个视频演示了模型区分所有三个对象的能力,而第二个视频则彰显了其作为搜寻者的能力。

Pretty impressive I would say! It does have an issue with distinguishing heads from Quidditch objects. But considering the size of our dataset, the performance is pretty good.

我会说非常令人印象深刻! 将头部与魁地奇对象区分开来确实存在问题。 但是考虑到数据集的大小,性能相当不错。

Training it for too long led to massive over-fitting (it was no longer size invariant), even though it reduced some mistakes. You can overcome this by having a larger dataset.

训练时间过长会导致严重的过度拟合(不再大小不变),即使它减少了一些错误。 您可以通过拥有更大的数据集来克服这一问题。

Thank you for reading this article! Hit that clap button if you did! Hope it helped you create your own Object Detection program. If you have any questions, you can hit me up on LinkedIn or send me an email (bharathrajn98@gmail.com).

感谢您阅读本文! 如果您按下了拍手按钮! 希望它可以帮助您创建自己的对象检测程序。 如有任何疑问,您可以在LinkedIn上打我,或给我发送电子邮件(bharathrajn98@gmail.com)。

翻译自: https://www.freecodecamp.org/news/how-to-play-quidditch-using-the-tensorflow-object-detection-api-b0742b99065d/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/394643.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

删除目录软链接注意事项

2019独角兽企业重金招聘Python工程师标准>>> 实验环境&#xff1a; 在root 目录下创建一个目录 1 ,并在该目录下创建一个2.txt 的文件&#xff0c;写入内容 1.txt: [rootserver ~]# mkdir 1 [rootserver ~]# echo 1.txt > 1/2.txt [rootserver ~]# tree 1 1 └─…

html如何模拟点击,Javascript 模拟点击事件(点击链接与html点击) 兼容IE/Firefox

一把情况下模拟点击一般两个方面&#xff0c;模拟点击超级连接事件firefox的兼容的函数为对HTMLAnchorElement 加入onclick事件try {// create a element so that HTMLAnchorElement is accessibledocument.createElement(a);HTMLElement.prototype.click function () {if (ty…

mvn编写主代码与测试代码

maven编写主代码与测试代码 3.2 编写主代码 项目主代码和测试代码不同&#xff0c;项目的主代码会被打包到最终的构件中&#xff08;比如jar&#xff09;&#xff0c;而测试代码只在运行测试时用到&#xff0c;不会被打包。默认情况下&#xff0c;Maven假设项目主代码位于src/…

打印速度快点的打印机_SLM推出了功能强大的新型金属3D打印机,速度快20倍

德国金属3D打印机制造商SLM Solutions在Formnext Connect贸易展览会上推出了功能强大的新系统NXG XII 600。SLM的大幅面机器配备了十二个可同时运行的1 KW激光器&#xff0c;使其速度比该公司自己的单激光SLM 280快20倍。NXG XII 600经过定制设计&#xff0c;可大量生产大型零件…

把转变为json_如何使用7行JSON将您的网站转变为移动应用程序

把转变为jsonby Ethan通过伊桑 将Web引擎融合到本机应用程序的新方法 (A New Approach for Blending Web Engine into Native Apps) What if I told you the 7 lines of JSON above, colored in orange is all you need to turn a website into a mobile app? No need to rew…

1.7Oob 继承关系中构造方法的使用

1&#xff1a;父类中最好要有一个空参数的构造方法&#xff0c;因为默认的构造方法在自定义了构造方法后就不存在了&#xff0c;需要显示的写出来。 若父类中没有空参数的构造方法&#xff0c;则子类必须有自定义的构造方法&#xff0c;且用super&#xff08;&#xff09;调用父…

JavaScript浮点运算0.2+0.1 !== 0.3

浮点运算JavaScript 本文主要讨论JavaScript的浮点运算&#xff0c;主要包括 JavaScript number基本类型二进制表示十进制浮点数的精度number 数字类型 在JavaScript中&#xff0c;数字只有number这一种类型; var intS 2,floatA 0.1; typeof intS; // number typeof floatA…

html获取data-*值,html5 获取和设置data-*属性值的四种方法讲解

1、获取id的对象2、需要获取的就是data-id 和 dtat-vice-id的值一&#xff1a;getAttribute()方法const getId document.getElementById(getId);// //getAttribute()取值属性console.log(getId.getAttribute("data-id"));//console.log(getId.getAttribute("da…

三菱模拟量输入与输出程序_初学PLC是学习西门子还是三菱?

PLC的种类繁多&#xff0c;品牌大多分为欧系、日系、美系。德系PLC以西门子为主&#xff0c;日系有三菱、欧姆龙、松下……&#xff0c;美系有罗克韦尔(A-B)通用电气(GE)公司、莫迪(MODICON)公司等。美国和欧洲的PLC技术是在相互隔离情况下独立研究开发的&#xff0c;因此美国和…

性能测试十四:Xshell链接linux虚拟机

一、先装一个linux虚拟机 VBoxcentos1、先下载Linux镜像文件的ovf或者OVA文件2、打开vbox&#xff0c;点击菜单栏“管理”-“导入虚拟电脑3、选择解压路径中的ovf或者OVA文件&#xff0c;点击下一步 4、点击“导入”&#xff0c;等待完成5、导入成功后&#xff0c;选择新导入的…

代码编写工具_我希望在开始编写代码时就已经知道的工具:已复习

代码编写工具by Mario Hoyos通过马里奥霍约斯(Mario Hoyos) 我希望在开始编写代码时就已经知道的工具&#xff1a;已复习 (Tools I wish I had known about when I started coding: Revisited) A few days ago, I wrote this article for freeCodeCamp which has since gone o…

Hydra扫描姿势

参数详解&#xff1a; -R 根据上一次进度继续破解 -S 使用SSL协议连接 -s 指定端口 -l 指定用户名 -L 指定用户名字典(文件) -p 指定密码破解 -P 指定密码字典(文件) -e 空密码探测和指定用户密码探测(ns) -C 用户名可以用:分割(username:password)可以代替-l username -p pass…

html5进度条插件 传递参数,Html5进度条插件(自写)

(function () {window.H5ProgressBar function (obj) {this.height obj.height;this.width obj.width;this.speed obj.speed;};//在界面上布局元素H5ProgressBar.prototype.drawLayout function () {document.write("开始下载")document.write(" ")do…

python合并txt文本_Python实现将目录中TXT合并成一个大TXT文件的方法

本文实例讲述了Python实现将目录中TXT合并成一个大TXT文件的方法。分享给大家供大家参考。具体如下&#xff1a; 在网上下了一个dota的英雄攻略,TXT格式,每个英雄一个文件,看得疼,就写了一个小东西,合并一下. #codinggbk import os import sys import glob def dirTxtToLargeTx…

读取字符串中的数字和小数

package com.jm.label.tools;import java.util.Map;import java.util.TreeMap;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 读取字符串中的数字和小数 * author JM.H * */public class DigitUtil { public static String getNumber(String str){ …

html网页设计要点,网站交互设计的8个要点

一、力求一致性例如网站首页需要和每一个下级页面保持一致的风格&#xff0c;导航都要放在屏幕的左上角&#xff0c;具有高度一致性的界面能给人清晰整洁的感觉。二、允许频繁使用快捷键快捷键表示产品使用的灵活性和有效性&#xff0c;想想每次我们使用搜索引擎的时候是鼠标点…

行为扩展以及插件机制

在thinkPHP中的行为扩展和插件机制。 首先行为扩展这个概念是TP框架的核心组成之一&#xff0c;关于行为的解释我就粗略的概括一下吧&#xff1a; TP在从接受到HTTP请求到最终将试图输出&#xff0c;期间经历的很多步骤&#xff0c;这些步骤大家可以在http://document.thinkphp…

python android 库_Python库

Gevent Gevent是一个基于greenlet的Python的并发框架&#xff0c;以微线程greenlet为核心&#xff0c;使用了epoll事件监听机制以及诸多其他优化而变得高效。 于greenlet、eventlet相比&#xff0c;性能略低&#xff0c;但是它封装的API非常完善&#xff0c;最赞的是提供了一个…

ios 应用商店_如何在预算范围内制作值得应用商店使用的iOS应用预览

ios 应用商店Back in 2014, Apple made it possible to add an app preview to the the App Store. App previews are the best way to show potential users what your app has to offer before they download the app. In fact, users are 3x more likely to install an app …

搭建nfs共享存储服务之二nfs服务端配置

1.1.NFS服务端配置文件路径为&#xff1a; /etc/exports&#xff0c;并且默认为空&#xff0c;需要用户自行配置。/etc/exports文件配置格式为&#xff1a;NFS共享的目录 NFS客户端地址1&#xff08;参数1&#xff0c;参数2...&#xff09;客户端地址2&#xff08;参数1&#x…