<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[咚咚咚的小极客]]></title><description><![CDATA[Thoughts, stories and ideas.]]></description><link>https://blog.akkz.net/</link><image><url>https://blog.akkz.net/favicon.png</url><title>咚咚咚的小极客</title><link>https://blog.akkz.net/</link></image><generator>Ghost 3.2</generator><lastBuildDate>Mon, 06 Apr 2026 20:56:06 GMT</lastBuildDate><atom:link href="https://blog.akkz.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[centos7 mini 安装virtualbox]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>这篇文章主要针对linux纯命令行环境下安装windows的需求。</p>
<ol>
<li>安装Virtualbox</li>
</ol>
<ul>
<li>下载</li>
<li>rpm</li>
</ul>
<ol start="2">
<li>安装扩展工具包</li>
</ol>
<ul>
<li><code>vboxmanage extpack install Oracle_VM_VirtualBox_Extension_Pack-5.1.22-115126.vbox-extpack</code></li>
</ul>
<ol start="3">
<li>创建虚拟机</li>
</ol>
<ul>
<li><code>VBoxManage createvm --name &quot;Windows XP&quot; --ostype WindowsXP --register</code></li>
</ul>
<ol start="4">
<li>配置虚拟机，以下命令也可以合并到一行完成</li>
</ol>
<ul>
<li><code>vboxmanage modifyvm win2003 --ostype Windows10</code> 配置系统类型,如果不是win10 32位可以通过<code>vboxmanage list ostypes</code>查找下</li>
<li><code>vboxmanage modifyvm win10 --memory 2048</code> 配置内存2G</li>
<li><code>vboxmanage modifyvm win10</code></li></ul>]]></description><link>https://blog.akkz.net/centos7-mini-an-zhuang-virtualbox/</link><guid isPermaLink="false">601558c31e72900001b6ed27</guid><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Thu, 13 Jul 2017 05:28:21 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>这篇文章主要针对linux纯命令行环境下安装windows的需求。</p>
<ol>
<li>安装Virtualbox</li>
</ol>
<ul>
<li>下载</li>
<li>rpm</li>
</ul>
<ol start="2">
<li>安装扩展工具包</li>
</ol>
<ul>
<li><code>vboxmanage extpack install Oracle_VM_VirtualBox_Extension_Pack-5.1.22-115126.vbox-extpack</code></li>
</ul>
<ol start="3">
<li>创建虚拟机</li>
</ol>
<ul>
<li><code>VBoxManage createvm --name &quot;Windows XP&quot; --ostype WindowsXP --register</code></li>
</ul>
<ol start="4">
<li>配置虚拟机，以下命令也可以合并到一行完成</li>
</ol>
<ul>
<li><code>vboxmanage modifyvm win2003 --ostype Windows10</code> 配置系统类型,如果不是win10 32位可以通过<code>vboxmanage list ostypes</code>查找下</li>
<li><code>vboxmanage modifyvm win10 --memory 2048</code> 配置内存2G</li>
<li><code>vboxmanage modifyvm win10 --acpi on</code> 配置电源管理</li>
<li><code>vboxmanage modifyvm win10 --nic1 nat</code> 配置网卡工作模式</li>
<li><code>vboxmanage modifyvm win10 --cpus 2</code> 配置CPU数量</li>
</ul>
<ol start="5">
<li>创建虚拟硬盘</li>
</ol>
<ul>
<li><code>vboxmanage createhd --filename win10.vdi --size 102400</code> 新建一个100G的硬盘，注意这里会在当前目录下创建，如果需要管理的话记得换个目录。</li>
<li><code>vboxmanage storagectl win10 --name win10HDD --add ide --bootable on</code> 新建硬盘控制器</li>
<li><code>vboxmanage storageattach win10 --storagectl win10HDD --port 0 --device 0 --type hdd --medium win10.vdi</code> 绑定硬盘</li>
</ul>
<ol start="6">
<li>安装系统</li>
</ol>
<ul>
<li><code>vboxmanage storageattach win10--storagectl win10HDD --port 0 --device 1 --type dvddrive --medium win10.iso</code> 挂载镜像</li>
<li><code>VBoxManage modifyvm win10 --vrde on</code> 打开VirtualBox remote desktop extension（不然无法远程装系统）</li>
<li><code>VBoxHeadless --startvm win10</code> 打开虚拟机并开始安装程序</li>
</ul>
<ol start="7">
<li>后续工作(在刚才的远程桌面中配置并打开运行远程连接后)</li>
</ol>
<ul>
<li><code>vboxmanage modifyvm win10 --natpf1 &quot;remote desktop,tcp,,3390,,3389&quot;</code> 增加名称为“remote desktop”的端口转发，可以通过<code>VBoxManage modifyvm win10 --natpf1 delete &quot;remote desktop&quot;</code>删除</li>
<li><code>firewalld-cmd --add-port=3390/tcp --permanent</code> 打开防火墙3390端口（如用iptables自行修改）</li>
<li><code>VBoxManage modifyvm win10 --vrde off</code> 关掉virtualbox的远程桌面</li>
<li><code>vboxmanage startvm win2003 --type headless</code> 从后台启动虚拟机（不然命令行窗口关了虚拟机就停了）</li>
</ul>
<p>TIPS:</p>
<ol>
<li>备份虚拟机</li>
</ol>
<ul>
<li><code>vboxmanage clonevm win10-Base --name win10-Test --register</code></li>
</ul>
<ol start="2">
<li>取消注册虚拟机</li>
</ol>
<ul>
<li><code>vboxmanage unregistervm win10-Base</code></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[我的世界游戏插件开发总结]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>在开发一个游戏插件时，有些东西是可以共用的，有些东西则是每个游戏单独有的。如何将这些内容区别开来，将共用的抽象成库，有助于提高以后的开发速度</p>
<h1 id>可以共用的部分</h1>
<ol>
<li>一套更加完善的命令处理机制</li>
</ol>
<ul>
<li>bukkit自带的命令处理机制并不完美，需要写很多重复的代码，比如判断命令发送者的权限，是否是玩家等等，通过写一个代理来执行可以有效降低代码量。</li>
<li>在上一步的思路上，设计一套Annotation接口，把每个命令的要求通过Annotation配置，效率可以大大提升。</li>
</ul>
<ol start="2">
<li>游戏初始化的逻辑</li>
</ol>
<ul>
<li>玩家排队的相关逻辑，如按顺序进入游戏、延迟传送等</li>
<li>一些游戏启动，监听加载的逻辑</li>
</ul>
<ol start="3">
<li>游戏状态的控制</li>
</ol>
<ul>
<li>一个游戏从启动到结束的生命周期是类似的，由系统托管生命周期也有助于减少工作量</li>
</ul>
<h1 id>不可以共用的部分</h1>
<ol>
<li>每个游戏的逻辑</li>
</ol>
<ul>
<li>虽然很多游戏有相似之处，如：跑酷类型的游戏都是又一个点跑到另一个点，但是提取这种共用逻辑的价值不大，基本上没有重复使用的价值。除非是小游戏集合，有很多相似的游戏在一个包里面。</li>
<li>这个与游戏初始化的区别是，游戏初始化时每个小游戏必须要有的，但是这部分不一定。</li>
</ul>
<ol start="2">
<li>监听操作</li>
</ol>
<ul>
<li>虽然很多监听操作是可以共用的，但是这样无疑会导致监听代码的复杂度直线上升。每个小游戏单独有自己的监听逻辑，启动时开启监听，结束时关闭监听。不仅有助于使代码更简洁，也能有效提高程序效率。</li>
</ul>
<!--kg-card-end: markdown-->]]></description><link>https://blog.akkz.net/wo-de-shi-jie-you-xi-cha-jian-kai-fa-zong-jie/</link><guid isPermaLink="false">601558c31e72900001b6ed26</guid><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Sat, 06 May 2017 16:00:40 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>在开发一个游戏插件时，有些东西是可以共用的，有些东西则是每个游戏单独有的。如何将这些内容区别开来，将共用的抽象成库，有助于提高以后的开发速度</p>
<h1 id>可以共用的部分</h1>
<ol>
<li>一套更加完善的命令处理机制</li>
</ol>
<ul>
<li>bukkit自带的命令处理机制并不完美，需要写很多重复的代码，比如判断命令发送者的权限，是否是玩家等等，通过写一个代理来执行可以有效降低代码量。</li>
<li>在上一步的思路上，设计一套Annotation接口，把每个命令的要求通过Annotation配置，效率可以大大提升。</li>
</ul>
<ol start="2">
<li>游戏初始化的逻辑</li>
</ol>
<ul>
<li>玩家排队的相关逻辑，如按顺序进入游戏、延迟传送等</li>
<li>一些游戏启动，监听加载的逻辑</li>
</ul>
<ol start="3">
<li>游戏状态的控制</li>
</ol>
<ul>
<li>一个游戏从启动到结束的生命周期是类似的，由系统托管生命周期也有助于减少工作量</li>
</ul>
<h1 id>不可以共用的部分</h1>
<ol>
<li>每个游戏的逻辑</li>
</ol>
<ul>
<li>虽然很多游戏有相似之处，如：跑酷类型的游戏都是又一个点跑到另一个点，但是提取这种共用逻辑的价值不大，基本上没有重复使用的价值。除非是小游戏集合，有很多相似的游戏在一个包里面。</li>
<li>这个与游戏初始化的区别是，游戏初始化时每个小游戏必须要有的，但是这部分不一定。</li>
</ul>
<ol start="2">
<li>监听操作</li>
</ol>
<ul>
<li>虽然很多监听操作是可以共用的，但是这样无疑会导致监听代码的复杂度直线上升。每个小游戏单独有自己的监听逻辑，启动时开启监听，结束时关闭监听。不仅有助于使代码更简洁，也能有效提高程序效率。</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[IntelliJ IDEA 设置Maven代理]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>在下一些国外的库时，如果直接下的话会非常慢，这个时候就需要为Maven配置一下代理~</p>
<p>打开File-&gt;settting，然后搜索Maven，打开Maven下的Importing选项，在VM Options for importer一栏后面加上<code> -DproxySet=true -DproxyHost=localhost -DproxyPort=1080</code>。</p>
<p>这里面localhost就是代理服务器地址，1080就是端口。</p>
<!--kg-card-end: markdown-->]]></description><link>https://blog.akkz.net/intellij-idea-she-zhi-mavendai-li/</link><guid isPermaLink="false">601558c31e72900001b6ed25</guid><category><![CDATA[IDE]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Sun, 30 Apr 2017 03:00:55 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>在下一些国外的库时，如果直接下的话会非常慢，这个时候就需要为Maven配置一下代理~</p>
<p>打开File-&gt;settting，然后搜索Maven，打开Maven下的Importing选项，在VM Options for importer一栏后面加上<code> -DproxySet=true -DproxyHost=localhost -DproxyPort=1080</code>。</p>
<p>这里面localhost就是代理服务器地址，1080就是端口。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Spigot开发文档整理]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>由于Spigot插件在不断更新，很多已有的中文文档已经不再适用，因此编写这篇文档对Spigot的官方教程做整理和翻译。<br>
这份文档是为具备Java基础的开发者准备的，一些关于项目创建的过程直接略过了，只整理开发插件的核心内容。</p>
<h1 id>新建项目</h1>
<ol>
<li>新建一个Java或Maven项目</li>
<li>导入spigot-api和bukkit的jar包</li>
</ol>
<ul>
<li>这里可以在<a href="https://hub.spigotmc.org/nexus/#welcome">https://hub.spigotmc.org/nexus/#welcome</a>中搜索spigot-api和bukkit，下载自己所开发版本对应的包，下载并拖到项目依赖中。</li>
<li>如果不想手动下载，可建一个Maven项目，加入下面的repositories依赖，再把搜索结果右下方的信息复制到Maven的配置文件中，更新一下即可。</li>
</ul>
<pre><code>&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;spigot-repo&lt;/id&gt;
        &lt;url&gt;https://hub.spigotmc.org/nexus/content/repositories/snapshots/&lt;/url&</code></pre>]]></description><link>https://blog.akkz.net/spigotkai-fa-wen-dang-zheng-li/</link><guid isPermaLink="false">601558c31e72900001b6ed24</guid><category><![CDATA[spigot]]></category><category><![CDATA[minecraft]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Wed, 26 Apr 2017 06:06:20 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>由于Spigot插件在不断更新，很多已有的中文文档已经不再适用，因此编写这篇文档对Spigot的官方教程做整理和翻译。<br>
这份文档是为具备Java基础的开发者准备的，一些关于项目创建的过程直接略过了，只整理开发插件的核心内容。</p>
<h1 id>新建项目</h1>
<ol>
<li>新建一个Java或Maven项目</li>
<li>导入spigot-api和bukkit的jar包</li>
</ol>
<ul>
<li>这里可以在<a href="https://hub.spigotmc.org/nexus/#welcome">https://hub.spigotmc.org/nexus/#welcome</a>中搜索spigot-api和bukkit，下载自己所开发版本对应的包，下载并拖到项目依赖中。</li>
<li>如果不想手动下载，可建一个Maven项目，加入下面的repositories依赖，再把搜索结果右下方的信息复制到Maven的配置文件中，更新一下即可。</li>
</ul>
<pre><code>&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;spigot-repo&lt;/id&gt;
        &lt;url&gt;https://hub.spigotmc.org/nexus/content/repositories/snapshots/&lt;/url&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;
</code></pre>
<p><img src="https://blog.akkz.net/content/images/2017/04/QQ--20170426135201.png" alt></p>
<h1 id>创建插件</h1>
<ol>
<li>新建插件的主类</li>
</ol>
<ul>
<li>插件的主类需要继承JavaPlugin</li>
<li>JavaPlugin 提供了插件工作时所需要的各种方法和属性</li>
<li>每个插件只能有一个主类，其它需要JavaPlugin的地方可以在onEnable()中将属性的引用传递过去。</li>
</ul>
<ol start="2">
<li>重写onEnable()和onDisable()方法</li>
</ol>
<ul>
<li>这两个方法会在服务器启动和关闭插件时执行</li>
</ul>
<ol start="3">
<li>编写plugin.yml</li>
</ol>
<ul>
<li>这个文件描述了插件的相关信息，其详细格式可参考下面代码</li>
</ul>
<p><strong>Main.java</strong></p>
<pre><code>package org.spigotmc.tutorial;

import org.bukkit.plugin.java.JavaPlugin;

public class Main extends JavaPlugin {
       @Override
       public void onEnable() {

       }

      @Override
      public void onDisable(){

      }
}
</code></pre>
<p><strong>plugin.yml</strong></p>
<pre><code>name: //插件的名称
version: //插件的版本
author: //插件的作者
main: //插件的主类，记得带包名
depend: //插件的前置依赖
website: //作者网站，通过 /version &lt;pluginname&gt; 可以查看
commands: //插件的命令（没有可以不写）
      &lt;command&gt;:  //命令名称，不带'/'
               description: //命令描述，/help 时可以查看
               usage: //命令在控制台中的使用方式，带'/'
</code></pre>
<h1 id>创建一个命令</h1>
<ol>
<li>新建命令类</li>
</ol>
<ul>
<li>命令的主类需要引用CommandExecutor 接口</li>
</ul>
<ol start="2">
<li>重写<code>public boolean onCommand(CommandSender commandSender, Command command, String label, String[] args)</code>方法</li>
</ol>
<ul>
<li>commandSender - 命令的发送者，可以是玩家、控制台或命令方块</li>
<li>command - 发送命令的一些信息，其实就是plugin中配置的一些信息，感觉这个参数没啥作用呀</li>
<li>label - 玩家敲的命令，会自动去掉'/'，感觉这个参数也没啥用</li>
<li>args - 玩家敲的命令后面跟的参数</li>
</ul>
<ol start="3">
<li>在主类中注册命令类<code>this.getCommand(&quot;kit&quot;).setExecutor(new CommandKit());</code></li>
</ol>
<ul>
<li>getCommand中的值在plugin.yml中需要有对应，否则会返回null</li>
</ul>
<ol start="4">
<li>在plugin.yml中添加这个命令即可</li>
<li>补充：如果指令发送者为玩家，就可以通过<code>(Player) commandSender</code>强制转换获得玩家对象</li>
</ol>
<ul>
<li>记得先判断一下，防止代码出错<code>if (sender instanceof Player)</code></li>
</ul>
<p><strong>CommandKit .java</strong></p>
<pre><code>public class CommandKit implements CommandExecutor {
    // This method is called, when somebody uses our command
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        if (sender instanceof Player) {
            Player player = (Player) sender;

            // Create a new ItemStack (type: diamond)
            ItemStack diamond = new ItemStack(Material.DIAMOND);

            // Create a new ItemStack (type: brick)
            ItemStack bricks = new ItemStack(Material.BRICK);

            // Set the amount of the ItemStack
            bricks.setAmount(20);

            // Give the player our items (comma-seperated list of all ItemStack)
            player.getInventory().addItem(bricks, diamond);
        }

        // If the player (or console) uses our command correct, we can return true
        return true;
    }
}
</code></pre>
<p><strong>Main.java</strong></p>
<pre><code>@Override
public void onEnable() {
        // Register our command &quot;kit&quot; (set an instance of your command class as executor)
        this.getCommand(&quot;kit&quot;).setExecutor(new CommandKit());
    }
</code></pre>
<p><strong>plugin.yml</strong></p>
<pre><code># Replace &quot;kit&quot; with the name of your command.
commands:
  kit:
    description: Your description
    usage: /kit
</code></pre>
<h1 id>创建一个事件监听</h1>
<ol>
<li>新建监听类</li>
</ol>
<ul>
<li>监听类需要实现Listener接口</li>
</ul>
<ol start="2">
<li>添加需要监听的方法</li>
</ol>
<ul>
<li>方法名称为 <code>public void on+事件名称(事件名称 event)</code></li>
<li>事件名称可以在<a href="https://hub.spigotmc.org/javadocs/spigot/">javadoc</a>中<code>org.bukkit.event</code>包下面查找</li>
<li>比如有个玩家加入的事件PlayerJoinEvent，那么就写<code>public void onPlayerJoin(PlayerJoinEvent event)</code></li>
<li>记得加上@EventHandler注解</li>
<li>event的方法在javadoc里面也可以查得到</li>
</ul>
<ol start="3">
<li>在主类中注册监听类<code>getServer().getPluginManager().registerEvents(new MyListener(), this);</code></li>
</ol>
<p><strong>MyListener.java</strong></p>
<pre><code>import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

public class MyListener implements Listener
{
     @EventHandler
     public void onPlayerJoin(PlayerJoinEvent event)
     {
         event.setJoinMessage(&quot;Welcome, &quot; + event.getPlayer().getName() + &quot;!&quot;);
     }
}
</code></pre>
<p><strong>Main.java</strong></p>
<pre><code>@Override
public void onEnable()
{
    getServer().getPluginManager().registerEvents(new MyListener(), this);
}
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[行人识别位置过滤总结]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id>数据统计</h1>
<p>数据统计工作是为了获得行人位置的分布区间。统计方法为计算不同高度下的行人ROI上边界和下边界距离假设的水平线的距离。</p>
<p>通过在DetectModule输出结果的部分插入以下代码实现统计：</p>
<pre><code>if (roi-&gt;height &lt; 200)
{
	count[1][roi-&gt;height &gt;&gt; 2] += (240 - roi-&gt;y - DST_START_COL); //此处统计上边界距离水平线距离
	count[0][roi-&gt;height &gt;&gt; 2]++;

	for (int i = 0; i &lt; 50; i++)
	{
		printf(&quot;%.2f &quot;, count[0]</code></pre>]]></description><link>https://blog.akkz.net/xing-ren-shi-bie-wei-zhi-guo-lu-zong-jie/</link><guid isPermaLink="false">601558c31e72900001b6ed23</guid><category><![CDATA[嵌入式]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Sat, 15 Apr 2017 04:18:57 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id>数据统计</h1>
<p>数据统计工作是为了获得行人位置的分布区间。统计方法为计算不同高度下的行人ROI上边界和下边界距离假设的水平线的距离。</p>
<p>通过在DetectModule输出结果的部分插入以下代码实现统计：</p>
<pre><code>if (roi-&gt;height &lt; 200)
{
	count[1][roi-&gt;height &gt;&gt; 2] += (240 - roi-&gt;y - DST_START_COL); //此处统计上边界距离水平线距离
	count[0][roi-&gt;height &gt;&gt; 2]++;

	for (int i = 0; i &lt; 50; i++)
	{
		printf(&quot;%.2f &quot;, count[0][i] == 0 ? 0 : count[1][i] / count[0][i]);
	}

	printf(&quot;\r\n&quot;);
}
</code></pre>
<p>统计结果按高度每4个像素为一个阶梯，分布如下图。</p>
<p><img src="https://blog.akkz.net/content/images/2017/04/QQ--20170415121353-1.png" alt="下边界于水平线距离分布"></p>
<p><img src="https://blog.akkz.net/content/images/2017/04/QQ--20170415165137.png" alt="上边界于水平线距离分布"></p>
<p>接下来统计一下分布距离与ROI高度的关系</p>
<p><img src="https://blog.akkz.net/content/images/2017/04/QQ--20170415121406-2.png" alt="下边界于水平线距离与ROI高度比例"></p>
<p><img src="https://blog.akkz.net/content/images/2017/04/QQ--20170415165150.png" alt="上边界于水平线距离与ROI高度比例"></p>
<p>从统计结果可以看书，上下边界距离水平线的距离大约呈线性增加，平均比率分别为0.6和0.4。</p>
<p>接下来针对70米(30~50个像素高度)左右距离的ROI进行分析，判断在某个距离下的ROI分布:</p>
<pre><code>if (roi-&gt;height &gt; 30 &amp;&amp; roi-&gt;height &lt; 40)
{
	int t = (240 - roi-&gt;y - DST_START_COL + 10);
	if (t &gt; 0 &amp;&amp; t &lt; 50)
	{
		count[0][t]++;
	}
	
	for (int i = 0; i &lt; 50; i++)
	{
		printf(&quot;%d &quot;, count[0][i]);
	}

	printf(&quot;\r\n&quot;);

	//printf(&quot;%d - %d\r\n&quot;, roi-&gt;y + DST_START_COL, roi-&gt;height + roi-&gt;y + DST_START_COL - 240);
}
</code></pre>
<p>得到下图：</p>
<p><img src="https://blog.akkz.net/content/images/2017/04/QQ--20170415154520.png" alt></p>
<p>通过该图可以看出，70米左右距离的行人ROI距离水平线距离呈正太分布，平均值在13。最边界的ROI可能由于误检或车抖动造成漂移较大。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[红外行人识别系统标记方法]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>在行人识别的最后步骤，需要对识别出的行人进行标记。通常在实验阶段往往只是把ROI的框涂出来，但是在工程阶段，需要更加精细的标记方法以获得更好的用户体验。</p>
<p>经过总结，标记的ROI需要满足以下需求：</p>
<ul>
<li>只标记人的身体部分，不填或少填无关的部分；</li>
<li>标记部分显示黄色，颜色深浅随着roi的置信度变化；</li>
</ul>
<p>设计思路：</p>
<ul>
<li>一般人体的亮度均大于背景，因此可以设置一个阈值，只标记高于阈值的像素，实现只标记人体部分。</li>
<li>我们红外图像只有亮度信息，对应到RGB色域中，RGB的值就是亮度的值。因此我们可以调高R和G的值来提高黄色的色度，降低B的值来增加颜色的深度。只要R和G的值一样且大于B就能获得理想的效果。</li>
</ul>
<p>那么开始设计：</p>
<ol>
<li>去除背景部分</li>
</ol>
<ul>
<li>经过测试，行人身体的亮度大都大于192，因此只标记亮度大于192的像素。</li>
</ul>
<ol start="2">
<li>通过两个像素的均值确定需要填图的黄色色度</li>
</ol>
<ul>
<li><code>yy = (ptr[current + 1] + ptr[current + 3]) &gt;&gt; 1;</code></li>
</ul>
<ol start="3">
<li>根据当前亮度，调整黄色的明暗程度，这部分yb的值必须小于yy</li>
</ol>
<ul>
<li><code>yb = yy - (1 &lt;&lt; level);</code></li>
</ul>
<ol start="4">
<li>计算具体的亮度值</li>
</ol>
<ul>
<li>因为R和G固定，</li></ul>]]></description><link>https://blog.akkz.net/hong-wai-xing-ren-shi-bie-xi-tong-biao-ji-fang-fa/</link><guid isPermaLink="false">601558c31e72900001b6ed22</guid><category><![CDATA[嵌入式]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Wed, 29 Mar 2017 04:49:08 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>在行人识别的最后步骤，需要对识别出的行人进行标记。通常在实验阶段往往只是把ROI的框涂出来，但是在工程阶段，需要更加精细的标记方法以获得更好的用户体验。</p>
<p>经过总结，标记的ROI需要满足以下需求：</p>
<ul>
<li>只标记人的身体部分，不填或少填无关的部分；</li>
<li>标记部分显示黄色，颜色深浅随着roi的置信度变化；</li>
</ul>
<p>设计思路：</p>
<ul>
<li>一般人体的亮度均大于背景，因此可以设置一个阈值，只标记高于阈值的像素，实现只标记人体部分。</li>
<li>我们红外图像只有亮度信息，对应到RGB色域中，RGB的值就是亮度的值。因此我们可以调高R和G的值来提高黄色的色度，降低B的值来增加颜色的深度。只要R和G的值一样且大于B就能获得理想的效果。</li>
</ul>
<p>那么开始设计：</p>
<ol>
<li>去除背景部分</li>
</ol>
<ul>
<li>经过测试，行人身体的亮度大都大于192，因此只标记亮度大于192的像素。</li>
</ul>
<ol start="2">
<li>通过两个像素的均值确定需要填图的黄色色度</li>
</ol>
<ul>
<li><code>yy = (ptr[current + 1] + ptr[current + 3]) &gt;&gt; 1;</code></li>
</ul>
<ol start="3">
<li>根据当前亮度，调整黄色的明暗程度，这部分yb的值必须小于yy</li>
</ol>
<ul>
<li><code>yb = yy - (1 &lt;&lt; level);</code></li>
</ul>
<ol start="4">
<li>计算具体的亮度值</li>
</ol>
<ul>
<li>因为R和G固定，因此直接优化为0.886 * yy，再带入上一公式，化简</li>
<li><code>y = yy - 0.114 * (1 &lt;&lt; level);</code></li>
</ul>
<ol start="5">
<li>换算YCbCr</li>
</ol>
<ul>
<li><code>ptr[current + 1] = y;</code></li>
<li><code>ptr[current + 3] = y;</code></li>
<li><code>ptr[current] = (yb - y) * 0.564 + 128;</code></li>
<li><code>ptr[current + 2] = (yy - y) * 0.713 + 128;</code></li>
</ul>
<ol start="6">
<li>化简</li>
</ol>
<pre><code>y = ((ptr[current + 1] + ptr[current + 3]) &gt;&gt; 1) - 0.114 * (1 &lt;&lt; level);

ptr[current + 1] = y;
ptr[current + 3] = y;
ptr[current] = (0 - 0.886 * (1 &lt;&lt; level)) * 0.564 + 128;
ptr[current + 2] = (0.114 * (1 &lt;&lt; level)) * 0.713 + 128;
</code></pre>
<p>效果展示<br>
<img src="https://blog.akkz.net/content/images/2017/03/QQ--20170329113045.png" alt><br>
<img src="https://blog.akkz.net/content/images/2017/03/QQ--20170329113114.png" alt></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[行人识别算法的系统设计]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id>模块化设计</h1>
<p>行人识别算法的具有一定的复杂度，在设计系统框架时要处理好以下问题：</p>
<ul>
<li>单一职责原则</li>
<li>里氏替换原则</li>
<li>依赖倒置原则</li>
<li>接口隔离原则</li>
<li>迪米特法则</li>
<li>开闭原则</li>
</ul>
<h2 id>单一职责原则</h2>
<p>**定义：**不要存在多于一个导致类变更的原因。通俗的说，即一个类只负责一项职责。</p>
<p>**实现：**对系统功能模块化，每个模块只负责自己的功能。</p>
<h2 id>里氏替换原则</h2>
<p>**定义：**如果对每一个类型为 T1的对象 o1，都有类型为 T2 的对象o2，使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时，程序 P 的行为没有发生变化。</p>
<p>**实现：**定义存储函数接口的结构体，在结构体中定义函数接口。不同的模块提供一个构造函数，在构造函数中申明接口实现并返回该结构体。针对不同的实现只需要将结构体中的函数接口指向不同的实现，上层模块的调用不会有感知。</p>
<h2 id>依赖倒置原则</h2>
<p>**定义：**高层模块不应该依赖低层模块，且都应该依赖其抽象。</p>
<p>**实现：**高层模块定义接口，底层模块按照接口设计其实现。</p>]]></description><link>https://blog.akkz.net/xing-ren-shi-bie-suan-fa-de-xi-tong-she-ji/</link><guid isPermaLink="false">601558c31e72900001b6ed1f</guid><category><![CDATA[嵌入式]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Thu, 23 Mar 2017 06:55:05 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id>模块化设计</h1>
<p>行人识别算法的具有一定的复杂度，在设计系统框架时要处理好以下问题：</p>
<ul>
<li>单一职责原则</li>
<li>里氏替换原则</li>
<li>依赖倒置原则</li>
<li>接口隔离原则</li>
<li>迪米特法则</li>
<li>开闭原则</li>
</ul>
<h2 id>单一职责原则</h2>
<p>**定义：**不要存在多于一个导致类变更的原因。通俗的说，即一个类只负责一项职责。</p>
<p>**实现：**对系统功能模块化，每个模块只负责自己的功能。</p>
<h2 id>里氏替换原则</h2>
<p>**定义：**如果对每一个类型为 T1的对象 o1，都有类型为 T2 的对象o2，使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时，程序 P 的行为没有发生变化。</p>
<p>**实现：**定义存储函数接口的结构体，在结构体中定义函数接口。不同的模块提供一个构造函数，在构造函数中申明接口实现并返回该结构体。针对不同的实现只需要将结构体中的函数接口指向不同的实现，上层模块的调用不会有感知。</p>
<h2 id>依赖倒置原则</h2>
<p>**定义：**高层模块不应该依赖低层模块，且都应该依赖其抽象。</p>
<p>**实现：**高层模块定义接口，底层模块按照接口设计其实现。高层模块通过对象工厂拿到底层模块的实例，不需要依赖底层模块的头文件。</p>
<h2 id>接口隔离原则</h2>
<p>**定义：**客户端不应该依赖它不需要的接口；一个类对另一个类的依赖应该建立在最小的接口上。</p>
<p>**实现：**采用多层模块的方式，对内允许模块定义自己的子模块，对外定义统一的操作接口，最小化模块的任务。</p>
<h2 id>迪米特法则</h2>
<p>**定义：**一个对象应该对其他对象保持最少的了解。</p>
<p>**实现：**在设计检测引擎的时候，引擎只关注于其定义好的四个子模块，不关心子模块的内部实现。子模块在自己的构造函数中完整自己的初始化。</p>
<h2 id>开闭原则</h2>
<p>**定义：**一个软件实体如类、模块和函数应该对扩展开放，对修改关闭。</p>
<p>**实现：**在ROI模块中，为避免其他模块存储数据依赖ROI的问题，为ROI模块设计了存储注册机制。遵循先注册后存储的过程，避免对ROI模块的修改。</p>
<h1 id>模块设计的过程</h1>
<ol>
<li>解耦</li>
<li>定义接口，标准化代码逻辑</li>
<li>去除头文件依赖</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[前端开发知识总结]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>总结分三大部分：html、css和javascript，每部分再分成两个子部分，分别是基础知识和记忆知识。</p>
<ul>
<li>基础知识指前端开发必须会的东西，比如页面渲染方式、js基础语法等。</li>
<li>记忆知识指一些单纯背背就可以的知识，忘记的话可以查，但是免试官可能喜欢问（哭笑</li>
</ul>
<h1 id="html">Html相关</h1>
<h2 id>浏览器内核 [记忆知识]</h2>
<p>浏览器内核又可以分为渲染引擎和js引擎两部分，后来js引擎越来越独立，内核也就更倾向于指渲染引擎本身的部分。目前常见的内核引擎有Trident、Gecko、Blink、Webkit四种。</p>
<ul>
<li>
<p>Trident</p>
<ul>
<li>微软开发的内核，从IE4一直用到现在IE11。因为有过一段时间比较牛逼，拖更了很久，导致其与W3C标准脱节，加上大量BUG和安全问题都没有解决，导致现在很多用户用IE是为了下载其它浏览器。现在Win10最新的Edge浏览器已经不用这个内核，而是用自己开发的edge内核。</li>
</ul>
</li>
<li>
<p>Gecko</p>
<ul>
<li>是一个开源内核，源自于古时候与ie对抗的Netscape。目前前端开发经常使用的Firefox浏览器就使用Gecko内核。另外这个内核还兼容很多平台，各种系统都能用。</li>
</ul>
</li>
<li>
<p>Webkit</p>
<ul>
<li>苹果公司开发的内核，早起也被chrome使用。后来因为chrome火了，导致大家以为webkit是谷歌弄得，哈哈。其前身是KDE的KHTML。</li>
</ul>
</li>
<li>
<p>Blink</p>
<ul>
<li>谷歌Chrome目前使用的内核，其前身是Chromium，而Chromium的前身就是webkit。因为商业竞争等各种关系，</li></ul></li></ul>]]></description><link>https://blog.akkz.net/qian-duan-mian-shi-zong-jie/</link><guid isPermaLink="false">601558c31e72900001b6ed21</guid><category><![CDATA[笔记]]></category><category><![CDATA[web前端]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Tue, 14 Mar 2017 12:59:44 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>总结分三大部分：html、css和javascript，每部分再分成两个子部分，分别是基础知识和记忆知识。</p>
<ul>
<li>基础知识指前端开发必须会的东西，比如页面渲染方式、js基础语法等。</li>
<li>记忆知识指一些单纯背背就可以的知识，忘记的话可以查，但是免试官可能喜欢问（哭笑</li>
</ul>
<h1 id="html">Html相关</h1>
<h2 id>浏览器内核 [记忆知识]</h2>
<p>浏览器内核又可以分为渲染引擎和js引擎两部分，后来js引擎越来越独立，内核也就更倾向于指渲染引擎本身的部分。目前常见的内核引擎有Trident、Gecko、Blink、Webkit四种。</p>
<ul>
<li>
<p>Trident</p>
<ul>
<li>微软开发的内核，从IE4一直用到现在IE11。因为有过一段时间比较牛逼，拖更了很久，导致其与W3C标准脱节，加上大量BUG和安全问题都没有解决，导致现在很多用户用IE是为了下载其它浏览器。现在Win10最新的Edge浏览器已经不用这个内核，而是用自己开发的edge内核。</li>
</ul>
</li>
<li>
<p>Gecko</p>
<ul>
<li>是一个开源内核，源自于古时候与ie对抗的Netscape。目前前端开发经常使用的Firefox浏览器就使用Gecko内核。另外这个内核还兼容很多平台，各种系统都能用。</li>
</ul>
</li>
<li>
<p>Webkit</p>
<ul>
<li>苹果公司开发的内核，早起也被chrome使用。后来因为chrome火了，导致大家以为webkit是谷歌弄得，哈哈。其前身是KDE的KHTML。</li>
</ul>
</li>
<li>
<p>Blink</p>
<ul>
<li>谷歌Chrome目前使用的内核，其前身是Chromium，而Chromium的前身就是webkit。因为商业竞争等各种关系，谷歌弄出了blink与苹果分道扬镳。</li>
</ul>
</li>
</ul>
<p>参考来源 ：</p>
<p>[1] <a href="http://web.jobbole.com/84826/">主流浏览器内核介绍（前端开发值得了解的浏览器内核历史）</a></p>
<h2 id="dom">DOM操作 [基础知识]</h2>
<p>DOM的全称是Document Object Module, 文档对象模型，他是独立于语言而存在的。</p>
<ul>
<li>
<p>根据 W3C 的 HTML DOM 标准，HTML 文档中的所有内容都是节点：</p>
</li>
<li>
<p>整个文档是一个文档节点</p>
</li>
<li>
<p>每个 HTML 元素是元素节点</p>
</li>
<li>
<p>HTML 元素内的文本是文本节点</p>
</li>
<li>
<p>每个 HTML 属性是属性节点</p>
</li>
<li>
<p>注释是注释节点</p>
</li>
<li>
<p>window.documnet是浏览器为我们提供的可以操作dom的接口。</p>
</li>
<li>
<p>随着Html5标准的推广，很多大家常用的JQuery的一些方法与浏览器原生提供的方法差别不大了，可以多了解一下原生的API。</p>
</li>
</ul>
<p>参考来源 ：</p>
<p>[1] <a href="http://harttle.com/2015/10/01/javascript-dom-api.html">原生JavaScript的DOM操作汇总</a></p>
<p>[2] <a href="https://leohxj.gitbooks.io/front-end-database/html-and-css-basic/learn-dom-tree.html">理解DOM结构</a></p>
<h2 id="dom">DOM渲染方式 [基础知识]</h2>
<p>浏览器在读取Html文档后，首先会构建DOM树，随后构建渲染树，最后渲染并显示。</p>
<p><img src="http://taligarsiel.com/Projects/webkitflow.png" alt="webkit渲染html的方式"></p>
<blockquote>
<h3 id>分词算法</h3>
</blockquote>
<blockquote>
<p>算法的输出是HTML符号。算法可以用状态机来描述。 每一个状态从输入流中消费一个或多个字符，并根据它们更新下一状态。决策受当前符号状态和树的构建状态影响。这意味着同样的字符可能会产生不同的结果，取决于当前的状态。算法太复杂，我们用一个例子来看看它的原理。</p>
</blockquote>
<blockquote>
<p>基础示例，分析下面的标签:</p>
</blockquote>
<pre><code>&lt;html&gt;
	&lt;body&gt;
		Hello world
	&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<blockquote>
<p>初始状态是”Data state”，当遇到”&lt;“时状态改为“Tag open state”。吃掉”a-z”字符组成的符号后产生了”Start tag token”，状态变更为“Tag name state”。我们一直保持此状态，直到遇到”&gt;”。每个字符都被追加到新的符号名上。在我们的例子中，解出的符号就是”html”。</p>
</blockquote>
<blockquote>
<p>当碰到”&gt;”时，当前符号完成，状态改回“Data state”。”<body>”标签将会以同样的方式处理。现在”html”与”body”标签都完成了，我们回到“Data state”状态。吃掉”H”（”Hello world”第一个字母）时会产生一个字符符号，直到碰到”</body>”的”&lt;“符号，我们就完成了一个字符符号”Hello world”。</p>
</blockquote>
<blockquote>
<p>现在我们回到“Tag open state”状态。吃掉下一个输入”/”时会产生一个”end tag token”并变更为“Tag name state”状态。同样，此状态保持到我们碰到”&gt;”时。这时新标签符号完成，我们又回到“Data state”。同样””也会被这样处理。</p>
</blockquote>
<blockquote>
<p><img src="http://taligarsiel.com/Projects/image019.png" alt></p>
</blockquote>
<blockquote>
<h3 id>树的构建算法</h3>
</blockquote>
<blockquote>
<p>当解析器被创建时，文档对象也被创建了。在树的构建过程中DOM树的根节点（Documen）将被修改，元素被添加到上面去。每个分词器完成的节点都会被树构建器处理。规范中定义了每一个符号与哪个DOM对象相关。除了把元素添加到DOM树外，它还会被添加到一个开放元素堆栈。这个堆栈用于纠正嵌套错误和标签未关闭错误。这个算法也用状态机描述，它的状态叫做”insertion modes”。</p>
</blockquote>
<blockquote>
<p>让我们看看下面输入的树构建过程：</p>
</blockquote>
<pre><code>&lt;html&gt;
	&lt;body&gt;
		Hello world
	&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<blockquote>
<p>树的构建过程中，输入就是分词过程中得到的符号序列。第一个模式叫“initial mode”。接收 html 符号后会变成“before html”模式并重新处理此模式中的符号。这会创建一个HTMLHtmlElement元素并追加到根文档节点。</p>
</blockquote>
<blockquote>
<p>然后状态改变为“before head”。我们收到”body”时，会隐式创建一个HTMLHeadElement，尽管我们没有这个标签，它也会被创建并添加到树中。</p>
</blockquote>
<blockquote>
<p>现在我们进入“in head”模式，然后是“after head”，Body会被重新处理，创建HTMLBodyElement元素并插入，然后进入“in body”模式。</p>
</blockquote>
<blockquote>
<p>字符符号”Hello world”收到后会创建一个”Text”节点，所有字符都被一一追加到上面。</p>
</blockquote>
<blockquote>
<p>收到body结束标签后进入 “after body” 模式，收到html结束标签后进入“after after body”模式。所有符号处理完后将终止解析。</p>
</blockquote>
<blockquote>
<p><img src="http://taligarsiel.com/Projects/image022.gif" alt></p>
</blockquote>
<p>参考来源 ：</p>
<p>[1] <a href="http://ued.ctrip.com/blog/how-browsers-work-rendering-engine-html-parsing-series-ii.html">浏览器是怎样工作的：渲染引擎，HTML解析（连载二）</a></p>
<h1 id="css">CSS</h1>
<h2 id="csshack">CSS hack [基础知识]</h2>
<p>css hack用于处理不同浏览器css样式不兼容的问题，但这种方法并不利于代码的维护，不到万不得已不建议使用。</p>
<ul>
<li>条件注释法
<ul>
<li>微软专属hack方式，也是官方推荐的方式。</li>
</ul>
</li>
<li>类内属性前缀法
<ul>
<li>通过加一些只有部分浏览器能识别的类前缀，需要查表选择前缀。</li>
</ul>
</li>
<li>选择器前缀法
<ul>
<li>在选择器前面加前缀，与上面类似。</li>
</ul>
</li>
</ul>
<p>参考来源 ：</p>
<p>[1] <a href="http://blog.csdn.net/freshlover/article/details/12132801">史上最全的CSS hack方式一览</a></p>
<h2 id>盒模型 [基础知识]</h2>
<p>直接看图就ok啦<br>
<img src="http://www.w3school.com.cn/i/ct_css_boxmodel_example.gif" alt="盒模型"></p>
<ul>
<li>特别注意的是：ie低于版本8的浏览器的盒子模型中的width包括内边距和边框</li>
</ul>
<p>参考来源 ：</p>
<p>[1] <a href="http://www.w3school.com.cn/css/css_boxmodel.asp">CSS 框模型概述</a></p>
<h1 id="javascript">Javascript</h1>
<h2 id>数组的相关操作 [记忆知识]</h2>
<ol>
<li>concat()</li>
</ol>
<ul>
<li><code>arr.concat(arr1, arr2, a1, a2)</code></li>
<li>在arr后面添加新的元素</li>
<li>返回新的数组，不修改调用的数组</li>
</ul>
<ol start="2">
<li>join()</li>
</ol>
<ul>
<li><code>arr.join(sparate)</code></li>
<li>使用将数组拼接成字符串，用sparate连接</li>
<li>返回拼接的字符串</li>
</ul>
<ol start="3">
<li>pop()</li>
</ol>
<ul>
<li><code>arr.pop()</code></li>
<li>删除数组最后一个元素</li>
<li>修改原数组，返回删除的元素</li>
</ul>
<ol start="4">
<li>push()</li>
</ol>
<ul>
<li><code>arr.push(a1,...,ax)</code></li>
<li>在数组最后面添加元素</li>
<li>修改原数组，返回新的长度</li>
</ul>
<ol start="5">
<li>shift()</li>
</ol>
<ul>
<li><code>arr.shift()</code></li>
<li>删除数组中第一个元素</li>
<li>修改原数组，返回删除的元素</li>
</ul>
<ol start="6">
<li>unshift()</li>
</ol>
<ul>
<li><code>arr.unshift(a1,...,ax)</code></li>
<li>在数组最开始添加元素</li>
<li>修改原数组，返回新的长度</li>
</ul>
<ol start="7">
<li>reverse()</li>
</ol>
<ul>
<li><code>arr.reverse()</code></li>
<li>颠倒数组中所有的元素</li>
<li>修改原数组，返回颠倒后的原数组</li>
</ul>
<ol start="8">
<li>slice()</li>
</ol>
<ul>
<li><code>arr.slice(start, end)</code></li>
<li>提取数组中start至end的元素</li>
<li>不修改原数组，返回新提取的数组</li>
</ul>
<ol start="9">
<li>splice()</li>
</ol>
<ul>
<li><code>arr.splice(index,count,a1,...,ax)</code></li>
<li>替换数组中指定范围的元素，还可以用于删除或插入操作</li>
<li>修改原数组，返回被删除的元素</li>
</ul>
<ol start="10">
<li>sort()</li>
</ol>
<ul>
<li><code>arr.sort(compareFunction)</code></li>
<li>对指定数组进行排序，如果没有指定比较方法，则将按字母顺序对数组中的元素进行排序</li>
<li>对原数组操作，返回排序后的原数组</li>
</ul>
<ol start="11">
<li>filter()</li>
</ol>
<ul>
<li><code>arr.filter(callback)</code></li>
<li>callback : <code>function(element, index, array)</code></li>
<li>返回一个新的符合callback测试为true的结果集，该方法可以用于遍历整个arr</li>
<li>不修改原数组，返回新的数组</li>
</ul>
<ol start="12">
<li>map()</li>
</ol>
<ul>
<li><code>arr.map(processFunction)</code></li>
<li>callback : <code>function(element, index, array)</code></li>
<li>返回一个新的由callback结果构成的数组，用于处理数组中所有元素</li>
<li>不修改原数组，返回新的数组</li>
</ul>
<p>参考来源 ：</p>
<h2 id>字符串所支持的正则表达式 [基础知识]</h2>
<ol>
<li>
<p>str.search()</p>
</li>
<li>
<p>str.match()</p>
</li>
<li>
<p>str.replace()</p>
</li>
<li>
<p>str.split()</p>
</li>
</ol>
<p>[1] <a href="http://www.w3school.com.cn/jsref/jsref_obj_array.asp">JavaScript Array 对象</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Angular2 的路由总结]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Angular2的路由不像backbone是url#route这种结构，使用的是html5的pushstate方法直接从url中获得路由，这就需要进行一定配置才可以使angular2运行。</p>
<ol>
<li>base href的配置</li>
</ol>
<ul>
<li>代码：<code>&lt;base href=&quot;/&quot;&gt;</code></li>
<li>base href的配置关系到路由的有效数据的选取</li>
<li>base href同样关系到该网页的js、css等数据的获取，因此不能乱设定。</li>
</ul>
<ol start="2">
<li>后台的配置</li>
</ol>
<ul>
<li>Angular2的路由方式使得用户刷新页面时，后台默认返回404错误。</li>
<li>需要在后台配置一下，当用户访问的路径为Angular2应用的路径时，返回Angular2首页的数据。（或者只要是匹配不到的路径，直接返回Angular2首页的数据）</li>
<li>注意是后台直接返回数据即可，不是重定向。</li>
</ul>
<ol start="3">
<li>子路由的配置</li>
</ol>
<ul>
<li>Angular2的路由允许空component，一些目录可以不用配置component。</li>
<li>如果把APP的路由都放到某个子路径下面有助于简化后台重定向时的匹配复杂度。</li>
</ul>
<ol start="4">
<li>默认页面的处理</li>
</ol>
<ul>
<li>正常访问网址是默认地址是登录页面。</li>
<li>凡是带APP的子路径的地址，默认返回Angular2的数据，否则重定向到首页。</li>
</ul>
<!--kg-card-end: markdown-->]]></description><link>https://blog.akkz.net/angular2-de-lu-you-zong-jie/</link><guid isPermaLink="false">601558c31e72900001b6ed1e</guid><category><![CDATA[web前端]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Sun, 05 Feb 2017 11:35:52 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Angular2的路由不像backbone是url#route这种结构，使用的是html5的pushstate方法直接从url中获得路由，这就需要进行一定配置才可以使angular2运行。</p>
<ol>
<li>base href的配置</li>
</ol>
<ul>
<li>代码：<code>&lt;base href=&quot;/&quot;&gt;</code></li>
<li>base href的配置关系到路由的有效数据的选取</li>
<li>base href同样关系到该网页的js、css等数据的获取，因此不能乱设定。</li>
</ul>
<ol start="2">
<li>后台的配置</li>
</ol>
<ul>
<li>Angular2的路由方式使得用户刷新页面时，后台默认返回404错误。</li>
<li>需要在后台配置一下，当用户访问的路径为Angular2应用的路径时，返回Angular2首页的数据。（或者只要是匹配不到的路径，直接返回Angular2首页的数据）</li>
<li>注意是后台直接返回数据即可，不是重定向。</li>
</ul>
<ol start="3">
<li>子路由的配置</li>
</ol>
<ul>
<li>Angular2的路由允许空component，一些目录可以不用配置component。</li>
<li>如果把APP的路由都放到某个子路径下面有助于简化后台重定向时的匹配复杂度。</li>
</ul>
<ol start="4">
<li>默认页面的处理</li>
</ol>
<ul>
<li>正常访问网址是默认地址是登录页面。</li>
<li>凡是带APP的子路径的地址，默认返回Angular2的数据，否则重定向到首页。</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Mongodb 的索引管理]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>为了提高数据库的存储效率，需要为常用的检索字段添加索引，这里做一下整理：</p>
<h1 id>创建索引</h1>
<h2 id>创建普通索引</h2>
<p><code>db.collection.ensureIndex({&quot;KEY&quot;:1}) </code></p>
<p>这里就为collection中KEY字段添加了増序的索引，改成-1就是降序。</p>
<h2 id>创建唯一索引</h2>
<p><code>db.collection.ensureIndex({&quot;KEY&quot;:1},{&quot;unique&quot;:true})</code></p>
<p>这里增加了<code>{&quot;unique&quot;:true}</code>，唯一性索引和mysql中的概念相同。</p>
<h2 id>创建稀疏索引</h2>
<p><code>db.collection.ensureIndex({&quot;KEY&quot;:1},{&quot;sparse&quot;:true})</code></p>
<p>因为mongodb不像mysql，有些文档可能缺失索引的字段，稀疏索引可以保证不含该字段的文档不会被检索。</p>
<h1 id>查看索引</h1>
<p><code>db.collection.</code></p>]]></description><link>https://blog.akkz.net/mongodb-de-suo-yin-guan-li/</link><guid isPermaLink="false">601558c31e72900001b6ed1d</guid><category><![CDATA[数据库]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Tue, 31 Jan 2017 04:43:37 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>为了提高数据库的存储效率，需要为常用的检索字段添加索引，这里做一下整理：</p>
<h1 id>创建索引</h1>
<h2 id>创建普通索引</h2>
<p><code>db.collection.ensureIndex({&quot;KEY&quot;:1}) </code></p>
<p>这里就为collection中KEY字段添加了増序的索引，改成-1就是降序。</p>
<h2 id>创建唯一索引</h2>
<p><code>db.collection.ensureIndex({&quot;KEY&quot;:1},{&quot;unique&quot;:true})</code></p>
<p>这里增加了<code>{&quot;unique&quot;:true}</code>，唯一性索引和mysql中的概念相同。</p>
<h2 id>创建稀疏索引</h2>
<p><code>db.collection.ensureIndex({&quot;KEY&quot;:1},{&quot;sparse&quot;:true})</code></p>
<p>因为mongodb不像mysql，有些文档可能缺失索引的字段，稀疏索引可以保证不含该字段的文档不会被检索。</p>
<h1 id>查看索引</h1>
<p><code>db.collection.getIndexes()</code></p>
<p>可以查看collection中的所有索引。</p>
<h1 id>删除索引</h1>
<p><code>db.collection.dropIndex(&quot;KEY&quot;)</code></p>
<p>可以删除KEY索引，如果dropIndex方法不传入参数，则删除所有索引。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Mongodb 用户安全策略配置]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>在网络上运行的mongodb服务，用户配置是必不可少的，但是目前大部分配置用户角色的资料都比较旧，有些方法甚至已经被遗弃，因此这里做一下整理。</p>
<h2 id="1">1. 配置管理员</h2>
<ul>
<li>确定数据库启动时没有添加-auth参数，启动数据库</li>
<li>在admin数据库下新建管理员用户</li>
</ul>
<pre><code>use admin
db.createUser(
  {
    user: &quot;username&quot;,
    pwd: &quot;password&quot;,
    roles: [ { role: &quot;userAdminAnyDatabase&quot;, db: &quot;admin&quot; } ]
  }
)
</code></pre>
<p>这里<code>userAdminAnyDatabase</code>参数是申明用户管理员权限，也可以改成admin就拥有所有权限了。db参数不能少，否则会报错。</p>
<h2 id="2mongodb">2. 启用mongodb的认证功能</h2>
<ul>
<li>添加-auth参数并重新启动数据库</li>
<li>在所需要管理的数据库下新建管理用户</li>
</ul>
<pre><code>use database

db.createUser(
 {
   user: &quot;username&quot;,
   pwd:</code></pre>]]></description><link>https://blog.akkz.net/mongodb-yong-hu-an-quan-ce-lue-pei-zhi/</link><guid isPermaLink="false">601558c31e72900001b6ed1c</guid><category><![CDATA[服务器]]></category><category><![CDATA[数据库]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Mon, 30 Jan 2017 14:31:55 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>在网络上运行的mongodb服务，用户配置是必不可少的，但是目前大部分配置用户角色的资料都比较旧，有些方法甚至已经被遗弃，因此这里做一下整理。</p>
<h2 id="1">1. 配置管理员</h2>
<ul>
<li>确定数据库启动时没有添加-auth参数，启动数据库</li>
<li>在admin数据库下新建管理员用户</li>
</ul>
<pre><code>use admin
db.createUser(
  {
    user: &quot;username&quot;,
    pwd: &quot;password&quot;,
    roles: [ { role: &quot;userAdminAnyDatabase&quot;, db: &quot;admin&quot; } ]
  }
)
</code></pre>
<p>这里<code>userAdminAnyDatabase</code>参数是申明用户管理员权限，也可以改成admin就拥有所有权限了。db参数不能少，否则会报错。</p>
<h2 id="2mongodb">2. 启用mongodb的认证功能</h2>
<ul>
<li>添加-auth参数并重新启动数据库</li>
<li>在所需要管理的数据库下新建管理用户</li>
</ul>
<pre><code>use database

db.createUser(
 {
   user: &quot;username&quot;,
   pwd: &quot;password&quot;,
   roles: [
      { role: &quot;readWrite&quot;, db: &quot;database&quot; }
   ]
 }
)
</code></pre>
<p>完成！！</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[DSP开发技巧]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="dsp">DSP侧如何统计具体函数运行时间？</h1>
<p>TI DSPC64x+内核有一个64位的硬件定时器（Time Stamp Counter），它的频率和CPU频率一致。<br>
最简单的办法是使用TSC的低32位TSCL。注意在DM644x中，TSCH用于ARM。</p>
<pre><code>#include void main (){
…
TSCL=0;
…
t1=TSCL;
my_code_to_benchmark();
t2=TSCL;
printf(“# cycles == %d\n”, (t2-t1));
}
</code></pre>
<p>来源：<a href="http://www.ti.com.cn/general/cn/docs/gencontent.tsp?contentId=61575">http://www.ti.com.cn/general/cn/docs/gencontent.tsp?contentId=61575</a></p>
<!--kg-card-end: markdown-->]]></description><link>https://blog.akkz.net/dspkai-fa-ji-qiao/</link><guid isPermaLink="false">601558c31e72900001b6ed1b</guid><category><![CDATA[嵌入式]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Wed, 07 Dec 2016 13:41:24 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="dsp">DSP侧如何统计具体函数运行时间？</h1>
<p>TI DSPC64x+内核有一个64位的硬件定时器（Time Stamp Counter），它的频率和CPU频率一致。<br>
最简单的办法是使用TSC的低32位TSCL。注意在DM644x中，TSCH用于ARM。</p>
<pre><code>#include void main (){
…
TSCL=0;
…
t1=TSCL;
my_code_to_benchmark();
t2=TSCL;
printf(“# cycles == %d\n”, (t2-t1));
}
</code></pre>
<p>来源：<a href="http://www.ti.com.cn/general/cn/docs/gencontent.tsp?contentId=61575">http://www.ti.com.cn/general/cn/docs/gencontent.tsp?contentId=61575</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[使用Docker部署vncserver]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>有时候出门在外，需要修改一个bug却苦于没有开发环境，一个远程的开发机的重要性便凸现出来。<br>
传统的配置vncserver的方式需要安装大量的软件包，对于系统整洁强迫症来说便难以忍受。使用Docker的方式把整个环境打包，需要时启动，不需要时remove掉，不仅可以保持服务器干净整洁，还可以实现工作环境的快速迁移。</p>
<h2 id>部署流程</h2>
<ul>
<li>寻找一个基础的vncserver的docker镜像，我这里在GitHub上找到一个不错的镜像：<a href="https://github.com/queeno/docker-ubuntu-desktop">https://github.com/queeno/docker-ubuntu-desktop</a>。它配置很简单，就是基于Ubuntu:16.04，安装tightvncserver和相关的软件包，然后把xstartup配置文件和passwd密码文件复制到镜像中（默认密码是password）。</li>
</ul>
<pre><code>FROM ubuntu:16.04

ENV DEBIAN_FRONTEND noninteractive
ENV USER root

RUN apt-get update &amp;&amp; \
    apt-get install -y --no-install-recommends ubuntu-desktop &amp;&amp; \
    apt-get install</code></pre>]]></description><link>https://blog.akkz.net/shi-yong-dockerbu-shu-vncserver/</link><guid isPermaLink="false">601558c31e72900001b6ed1a</guid><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Wed, 16 Nov 2016 03:43:28 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>有时候出门在外，需要修改一个bug却苦于没有开发环境，一个远程的开发机的重要性便凸现出来。<br>
传统的配置vncserver的方式需要安装大量的软件包，对于系统整洁强迫症来说便难以忍受。使用Docker的方式把整个环境打包，需要时启动，不需要时remove掉，不仅可以保持服务器干净整洁，还可以实现工作环境的快速迁移。</p>
<h2 id>部署流程</h2>
<ul>
<li>寻找一个基础的vncserver的docker镜像，我这里在GitHub上找到一个不错的镜像：<a href="https://github.com/queeno/docker-ubuntu-desktop">https://github.com/queeno/docker-ubuntu-desktop</a>。它配置很简单，就是基于Ubuntu:16.04，安装tightvncserver和相关的软件包，然后把xstartup配置文件和passwd密码文件复制到镜像中（默认密码是password）。</li>
</ul>
<pre><code>FROM ubuntu:16.04

ENV DEBIAN_FRONTEND noninteractive
ENV USER root

RUN apt-get update &amp;&amp; \
    apt-get install -y --no-install-recommends ubuntu-desktop &amp;&amp; \
    apt-get install -y gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal &amp;&amp; \
    apt-get install -y tightvncserver &amp;&amp; \
    mkdir /root/.vnc

ADD xstartup /root/.vnc/xstartup
ADD passwd /root/.vnc/passwd

RUN chmod 600 /root/.vnc/passwd

CMD /usr/bin/vncserver :1 -geometry 1280x800 -depth 24 &amp;&amp; tail -f /root/.vnc/*:1.log

EXPOSE 5901
</code></pre>
<ul>
<li>修改软件源：
<ul>
<li>这个包使用的Ubuntu:16.04使用的是国外的软件源，导致build的速度非常慢，这里可以改成使用国内软件源的镜像，我这里做了一个</li>
</ul>
</li>
</ul>
<pre><code>FROM akkz/docker-ubuntu-chinese-resources:release-14.04
</code></pre>
<ul>
<li>增加中文的字体支持
<ul>
<li>在<code>RUN chmod 600 /root/.vnc/passwd</code>后面加上</li>
</ul>
</li>
</ul>
<pre><code>RUN apt-get install -y ttf-wqy-microhei &amp;&amp; \
    apt-get install -y ttf-wqy-zenhei &amp;&amp; \
    apt-get install -y xfonts-wqy
</code></pre>
<ul>
<li>
<p>如果有需要，加上GBK支持的命令，格式和上面相同</p>
</li>
<li>
<p>加上工作所需要的软件的安装指令，如：</p>
</li>
</ul>
<pre><code>RUN apt-get install -y firefox
</code></pre>
<ul>
<li>启动镜像</li>
</ul>
<h2 id>注意事项</h2>
<ul>
<li>有时候中文乱码可能因为字体没有装，不要陷在GBK的安装中。</li>
<li>用docker-compose可以提高部署效率</li>
<li>端口可以映射到其它端口，提高安全性</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[PhoneGap(Cordova)开发总结]]></title><description><![CDATA[<!--kg-card-begin: markdown--><ol>
<li>软件架构设计</li>
</ol>
<ul>
<li>软件架构可以借鉴MVC的方式，View层负责页面跳转和事件监听，Controller层负责业务逻辑处理，Dao层负责数据发送和接收。</li>
</ul>
<ol start="2">
<li>页面跳转/刷新时事件的注册与取消注册</li>
</ol>
<ul>
<li>大部分页面需要根据后台数据生成html，这就用到了html的模板技术。当使用类似于template7这类模板引擎时，如何管理生成页面的事件就成为了一个问题。</li>
<li>目前我探索出来的方式是，使用jQuery的on方法，把事件挂载在当前页面的根节点上，这样不管页面内容如何刷新都不会影响到事件的监听。</li>
<li>貌似一些类似于backbone的前端框架可以帮忙解决事件的监听问题。</li>
</ul>
<ol start="3">
<li>与服务端数据交互时的问题</li>
</ol>
<ul>
<li>Ajax刷新时需要给用户一个等待的反馈，请求结束后也需要给用户一个结果的反馈，由于不同模块反馈的内容不一样，因此如何实现一个公用的方案也需要考虑。</li>
<li>我的想法是，配置一个公用的存储反馈内容的json对象，调用dao层方法的时候把配置和该对象一起传进去，减少业务层逻辑的复杂程度。</li>
</ul>
<ol start="4">
<li>id、class与css选择器使用的问题</li>
</ol>
<ul>
<li>有时候为了好看，在写css选择器的时候会写上一串限制的参数，如果对于一些经常复用的class这应该是个好方法，但是我发现用着用着就把class当id用了，很多定义的class只使用了一次。我觉得以后在开发前先大致设想好自己想使用的class，提取一些公用的内容，把这种方案的特点发挥到极致。</li>
<li>对于页面中绑定的事件等操作，可以不用写上一串选择器，因为绑定是运行时实时生效，不会因为页面切换导致绑定到其它class上面去了。</li>
</ul>
<ol start="5">
<li>view层函数的结构</li>
</ol>
<ul>
<li>在写view层方法的时候，我习惯于写上init和load两个方法，其中init负责初始化事件监听，load负责加载和渲染页面，在实践后我觉得这是个非常实用的设计方案，但是目前我的代码仍然有很大的冗余，每个view都要写上init和load的调用。以后开发可以抽象出一个公用的view，然后调用loadView的方法传递一个json对象初始化view，json对象里面有init和load两个函数的定义，</li></ul>]]></description><link>https://blog.akkz.net/phonegapkai-fa-zong-jie/</link><guid isPermaLink="false">601558c31e72900001b6ed19</guid><category><![CDATA[web前端]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Wed, 09 Nov 2016 11:32:30 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><ol>
<li>软件架构设计</li>
</ol>
<ul>
<li>软件架构可以借鉴MVC的方式，View层负责页面跳转和事件监听，Controller层负责业务逻辑处理，Dao层负责数据发送和接收。</li>
</ul>
<ol start="2">
<li>页面跳转/刷新时事件的注册与取消注册</li>
</ol>
<ul>
<li>大部分页面需要根据后台数据生成html，这就用到了html的模板技术。当使用类似于template7这类模板引擎时，如何管理生成页面的事件就成为了一个问题。</li>
<li>目前我探索出来的方式是，使用jQuery的on方法，把事件挂载在当前页面的根节点上，这样不管页面内容如何刷新都不会影响到事件的监听。</li>
<li>貌似一些类似于backbone的前端框架可以帮忙解决事件的监听问题。</li>
</ul>
<ol start="3">
<li>与服务端数据交互时的问题</li>
</ol>
<ul>
<li>Ajax刷新时需要给用户一个等待的反馈，请求结束后也需要给用户一个结果的反馈，由于不同模块反馈的内容不一样，因此如何实现一个公用的方案也需要考虑。</li>
<li>我的想法是，配置一个公用的存储反馈内容的json对象，调用dao层方法的时候把配置和该对象一起传进去，减少业务层逻辑的复杂程度。</li>
</ul>
<ol start="4">
<li>id、class与css选择器使用的问题</li>
</ol>
<ul>
<li>有时候为了好看，在写css选择器的时候会写上一串限制的参数，如果对于一些经常复用的class这应该是个好方法，但是我发现用着用着就把class当id用了，很多定义的class只使用了一次。我觉得以后在开发前先大致设想好自己想使用的class，提取一些公用的内容，把这种方案的特点发挥到极致。</li>
<li>对于页面中绑定的事件等操作，可以不用写上一串选择器，因为绑定是运行时实时生效，不会因为页面切换导致绑定到其它class上面去了。</li>
</ul>
<ol start="5">
<li>view层函数的结构</li>
</ol>
<ul>
<li>在写view层方法的时候，我习惯于写上init和load两个方法，其中init负责初始化事件监听，load负责加载和渲染页面，在实践后我觉得这是个非常实用的设计方案，但是目前我的代码仍然有很大的冗余，每个view都要写上init和load的调用。以后开发可以抽象出一个公用的view，然后调用loadView的方法传递一个json对象初始化view，json对象里面有init和load两个函数的定义，而对这两个方法的调用则由公共的view完成，减少代码冗余。</li>
</ul>
<ol start="6">
<li>dao层函数的结构</li>
</ol>
<ul>
<li>在写dao层方法的时候，可以对jQuery的ajax的方法再进行一次封装，对错误的结果有个统一的处理方式。</li>
<li>在这一层的开发上，需要与后台接口协商好参数名和格式，如果出现相同参数多个名字（后台比较乱）的情况，最好还是加一层封装，预处理一下数据。假如后台返回的数据格式已经非常完善的话，那么直接回给controller层即可。</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[DM6437上行人识别程序开发总结]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>最近完成了DSP平台上行人识别程序的框架设计与实现，这里总结一下开发过程中遇到的问题及解决方案：</p>
<h2 id="1bios">1. BIOS配置文件修改生效问题</h2>
<p>CCS3.3编译程序的方式有increase build和build all两种方式，通常情况下如果只有改了某个文件，可以选择increase build来提高算法的编译速度。但是如果修改了配置文件，则一定要选择build all，否则修改无法生效。</p>
<h2 id="2">2. 周期函数、软中断的配置问题</h2>
<p>在BIOS中配置周期函数和软中断的时候，要注意中断配置的名称和它调用的方法不能同名，如果同名的话会导致配置失效。</p>
<h2 id="3">3. 不同中断函数之间变量共享方式</h2>
<p>多个中断函数需要共享某些变量时，可以使用闭包的方式，避免全局变量的使用。即将这几个函数定义在一个.c文件中，使用static修饰共享的变量。</p>
<h2 id="4">4. 模块复用性提高</h2>
<p>上面闭包的方式可以使多个软中断函数共享变量，但是这种设计会降低模块的复用程度，比如相同的检测模块调用多次完成对不同尺度下图像的检测。这时可以使用结构体存储模块的配置参数，每次调用模块中方法使将配置结构体传回，实现对模块的复用。</p>
<h2 id="5">5. 对内部函数与变量的保护</h2>
<p>为了防止外部调用不应该调用的函数，可以定义两个头文件，头文件1声明外部调用需要使用的结构体和函数，头文件2定义内部使用的函数，公开模块时只公开头文件1即可。</p>
<!--kg-card-end: markdown-->]]></description><link>https://blog.akkz.net/dm6437shang-xing-ren-shi-bie-cheng-xu-kai-fa-zong-jie/</link><guid isPermaLink="false">601558c31e72900001b6ed18</guid><category><![CDATA[嵌入式]]></category><dc:creator><![CDATA[Kevin Zhang]]></dc:creator><pubDate>Wed, 09 Nov 2016 11:07:13 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>最近完成了DSP平台上行人识别程序的框架设计与实现，这里总结一下开发过程中遇到的问题及解决方案：</p>
<h2 id="1bios">1. BIOS配置文件修改生效问题</h2>
<p>CCS3.3编译程序的方式有increase build和build all两种方式，通常情况下如果只有改了某个文件，可以选择increase build来提高算法的编译速度。但是如果修改了配置文件，则一定要选择build all，否则修改无法生效。</p>
<h2 id="2">2. 周期函数、软中断的配置问题</h2>
<p>在BIOS中配置周期函数和软中断的时候，要注意中断配置的名称和它调用的方法不能同名，如果同名的话会导致配置失效。</p>
<h2 id="3">3. 不同中断函数之间变量共享方式</h2>
<p>多个中断函数需要共享某些变量时，可以使用闭包的方式，避免全局变量的使用。即将这几个函数定义在一个.c文件中，使用static修饰共享的变量。</p>
<h2 id="4">4. 模块复用性提高</h2>
<p>上面闭包的方式可以使多个软中断函数共享变量，但是这种设计会降低模块的复用程度，比如相同的检测模块调用多次完成对不同尺度下图像的检测。这时可以使用结构体存储模块的配置参数，每次调用模块中方法使将配置结构体传回，实现对模块的复用。</p>
<h2 id="5">5. 对内部函数与变量的保护</h2>
<p>为了防止外部调用不应该调用的函数，可以定义两个头文件，头文件1声明外部调用需要使用的结构体和函数，头文件2定义内部使用的函数，公开模块时只公开头文件1即可。</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>