异常处理 – 第六章 – C# 从入门到放弃

基本语法:

try
{
    ...
}
catch(Exception ex) when (ex.GetTypr() != typeof(System.OutOfMenoryException))
{
    ....
}

=====

数据溢出异常的处理:

checked:

int number = int.MaxValue;
checked
{
    int willThrow = number++;
    Console.WriteLine("won't run to here");
}

unchecked:

int number = int.MaxValue;
unchecked
{
    int willThrow = number++;
    Console.WriteLine("will run to here");
}

also:

try
{
    int lhs = 9876543;
    int rhs = 9876543;
    int outcome = 0;
    outcome = checked(lhs * rhs);
}
catch(OverflowException oEx)
{
    result.Text = oex.Message;
}

=====

手动抛出异常:

try
{
    throw new ArgumentOutOfRangeException("error!");
}
catch(ArgumentOutOfRangeException msg)
{
    xxx.Text = msg.Message;
}

finally的用法:

try
{
    DataConnection.Open();
    DataCommand.ExecuteReader();
    ...
    return;
}
finally
{
    DataConnection.Close();
}
//无论是否抛出异常,也无论从什么地方 return 返回,finally 语句块总是会执行,这样你有机会调用 Close 来关闭数据库连接(即使未打开或打开失败,关闭操作永远是可以执行的),以便于释放已经产生的连接,释放资源。 顺便说明,return 是可以放在 try 语句块中的。但不管在什么时机返回,在返回前,finally 将会执行。
//小结
try
{
    // 执行的代码,其中可能有异常。一旦发现异常,则立即跳到 catch 执行。否则不会执行 catch 里面的内容
}
catch
{
    // 除非 try 里面执行代码发生了异常,否则这里的代码不会执行
}
finally
{
    // 不管什么情况都会执行,包括 try catch 里面用了 return , 可以理解为只要执行了 try 或者 catch,就一定会执行 finally
}

基于socket的酷Q机器人与Minecraft消息同步功能的实现

我先放张效果图:

这张图中主要实现的功能就是消息同步,后来我又加了执行命令的功能,有兴趣的可以自己改改玩233

上图插件的介绍地址:http://mcbbs.net/thread-682777-1-1.html

项目开源地址:http://git.oschina.net/chenxuuu/Minecraft-QQGroupPlubin

gitosc的readme中我写了双方通讯的socket格式了,如下:

协议食用指南:

插件通过socket通讯,使用2333端口

客户端:minecraft插件实现

服务端:cq插件实现

===========================

通讯协议举例:

客户端与服务端每秒发送/接收一次数据

客户端→服务端(minecraft插件→cq插件)发送字符串举例:xxxxxxxx]][[ccccc]][[dawdasdasdasdasd]][[asadsdasdasd

分割符号为“]][[”(如果这一秒内有多条消息的话会这样)

服务端→客户端(cq插件→minecraft插件)发送字符串举例:|||||xxxxxxxx|||||command>ccccc|||||<player>dawdasdasdasdasd

分割符号为“|||||”(如果这一秒内有多条消息的话会这样),当分割开后,字符串中包含“<”符号的,将直接在服务器全局发送;字符串中包含“command>”符号且不包含“<”符号的,将作为命令发送到控制台,其他数据将舍弃(如xxxxxxxx那一个字符串)。

我就稍微再贴一下两边的核心代码吧。

java端:

java这个语言我是没接触过的,所以代码基本都是请教的Balrogs_xt大佬(博客地址:http://www.acgxt.com/),还有万能的百度

java端实现的功能是socket的客户端、并且作为minecraft插件输出和执行各种数据,代码不长,我就全部贴在这里了:

package com.sweetcreeper.qqplugin;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;

public class Qqplugin extends JavaPlugin implements Listener
{
	public String player="none233";
	public String msg="none233";
	
	@Override//重写父类的方法
	public void onEnable()
	{
		getLogger().info("QQGroupMessagePlugin is started successfully!");
		//注册监听
		Bukkit.getPluginManager().registerEvents(this,this);
		
		new BukkitRunnable(){     
		    int s = 0;//设置定10秒后执行某段代码
		    @Override    
		    public void run(){
		    	if(s>=60)
		    	{
		    		Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "tm abc 发钱啦!");
		    		Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "eco give * 1");
		    		s=0;
		    	}
		    	else
		    	{
		    		s++;
		    	}
		        //s--;//迭代递减,我看官方的教程是没这个的,我没试过,你也可以删除试试
		        //if(s==0){
		            //这个写10秒后执行的代码(假如定义的定时器每次是1秒)
		        //    cancel();//cancel用来取消定时器
		        //}else{
		            //这里可以写每次触发定时器执行的代码
		            try 
		            {
		                //1.创建客户端Socket,指定服务器地址和端口
		                Socket socket=new Socket("localhost", 2333);
		                //2.获取输出流,向服务器端发送信息
		                OutputStream os=socket.getOutputStream();//字节输出流
		                PrintWriter pw=new PrintWriter(os);//将输出流包装为打印流
		                if(player!="none233")
		                {
		                	pw.write(msg);
		                	player="none233";
		                }
		                else
		                {
		                	pw.write("getmsg");
		                }
		                pw.flush();
		                socket.shutdownOutput();//关闭输出流
		                //3.获取输入流,并读取服务器端的响应信息
		                InputStream is=socket.getInputStream();
		                BufferedReader br=new BufferedReader(new InputStreamReader(is));
		                String info=null;
		                info=br.readLine();
		                String[] sourceStrArray=info.split("\\|\\|\\|\\|\\|");
		                for(int i=0;i<sourceStrArray.length;i++)
		                {
		                	if(sourceStrArray[i].indexOf("<")!=-1)
		                	{
		                		Bukkit.broadcastMessage(sourceStrArray[i]);
		                	}
		                	else if(sourceStrArray[i].indexOf("command>")!=-1)
		                	{
		                		Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), sourceStrArray[i].replace("command>", ""));
		                		if(player!="none233")
		                		{
		                			msg+="]][[<提示>"+sourceStrArray[i].replace("command>", "")+"已执行";
		                		}
		                		else
		                		{
		                			player="ok";
		                			msg="<提示>"+sourceStrArray[i].replace("command>", "")+"已执行";
		                		}
		                	}
		                }
		                //Bukkit.broadcastMessage("debug:"+info);
		                //4.关闭资源
		                br.close();
		                is.close();
		                pw.close();
		                os.close();
		                socket.close();
		            } catch (UnknownHostException e) {
		                //e.printStackTrace();
		            } catch (IOException e) {
		                //e.printStackTrace();
		            }
		        //}
		    } 
		}.runTaskTimer(this, 0L, 20L);//参数是,主类、延迟、多少秒运行一次,比如5秒那就是5*20L
	}
	@Override
	public void onDisable()
	{
		getLogger().info("QQGroupMessagePlugin is stoped successfully!");
	}
	
	@EventHandler
	public void onPlayerSay(AsyncPlayerChatEvent event)
	{
		if(player!="none233")
		{
			msg+="]][[<"+event.getPlayer().getName()+">"+event.getMessage();
			//player="ok";
		}
		else
		{
			player="ok";
			msg="<"+event.getPlayer().getName()+">"+event.getMessage();
		}
		//Bukkit.broadcastMessage("player:"+event.getPlayer().getName()+",msg:"+event.getMessage());
	}
	
	@EventHandler
	public void onPlayerJoin(PlayerJoinEvent event)
	{
		if(player!="none233")
		{
			msg+="]][[<消息>"+event.getPlayer().getName()+"上线了";
		}
		else
		{
			player="ok";
			msg="<消息>"+event.getPlayer().getName()+"上线了";
		}
	}
	
	@EventHandler
	public void onPlayerQuit(PlayerQuitEvent event)
	{
		if(player!="none233")
		{
			msg+="]][[<消息>"+event.getPlayer().getName()+"掉线了";
		}
		else
		{
			player="ok";
			msg="<消息>"+event.getPlayer().getName()+"掉线了";
		}
	}
}

基本的思路就是前面写的那个格式:“xxxxxxxx]][[ccccc]][[dawdasdasdasdasd]][[asadsdasdasd”

C#端:

c#端作为酷q插件,在socket通讯中作为服务端

我把网上找来的socket代码稍作修改:

/// <summary>
/// 监听客户端连接
/// </summary>
private static void ListenClientConnect()
{
    while (true)
    {
        Socket clientSocket = serverSocket.Accept();
        //clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello\r\n"));
        Socket myClientSocket = (Socket)clientSocket;
        int receiveNumber;
        receiveNumber = myClientSocket.Receive(result);
        //Console.WriteLine("接收客户端 {0} 消息{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.UTF8.GetString(result, 0, receiveNumber));
        string replay = Encoding.UTF8.GetString(result, 0, receiveNumber);
        if (replay.IndexOf("<") != -1)
        {
            if (replay.IndexOf("]][[") != -1)
            {
                try
                {
                    string[] str2;
                    str2 = replay.Split(new string[] { "]][[" }, StringSplitOptions.None);
                    foreach (string i in str2)
                    {
                        CQ.SendGroupMessage(GroupSet, i);
                    }
                }
                catch { }
            }
            else
            {
                CQ.SendGroupMessage(GroupSet, replay);
            }
        }
        clientSocket.Send(Encoding.UTF8.GetBytes("ok233"));
        clientSocket.Send(Encoding.UTF8.GetBytes(mcmsg));
        mcmsg = "";
        myClientSocket.Shutdown(SocketShutdown.Both);
        myClientSocket.Close();
    }
}

上面那段作为多线程部分后台死循环运行。

然后定义几个全局变量:

private static byte[] result = new byte[4096];
private static int myProt = 2333;   // 端口  
static Socket serverSocket;

在插件初始化时,打开该线程:

IPAddress ip = IPAddress.Parse("127.0.0.1");
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(ip, myProt));  // 绑定 IP 地址:端口
serverSocket.Listen(10);    // 设定最多 10 个排队连接请求
// 通过 Clientsoket 发送数据
Thread myThread = new Thread(ListenClientConnect);
myThread.Start();

最后只是消息处理问题了,只要让结果消息+="|||||"和别的东西就可以了。

注意的地方:

如果普通消息中你没有强制插入"<"符号,可能后导致命令输入漏洞,所以我从c#到java输出的普通聊天记录的格式是[群消息]<玩家id>消息内容

其他:没东西啦

399元斐讯K2免费路由器刷breed教程及华硕老毛子固件包

前天买了个免费路由器(http://item.jd.com/2615810.html

这个免费的套路其实就是:拿399投资到金融平台一个月,送你台路由器

不要白不要,我就入手了一台

网上传言说是路由器有后门,然后我尝试刷第三方固件,毕竟第三方固件功能比官方多多了(我其实就是要ss)

于是我开始了尝试。。。

固件版本V22.4.6.xx(后面的我忘了。。。

网上教程(点我去看那个教程)需要把版本刷到V22.4.2.9

然而。。路由器提示:“版本错误,升级失败!”

好吧,怪我买的晚,路由器早tm把这个洞补上了。。

然后我尝试着刷breed。。。

噫居然可以!

工具下载:http://pan.baidu.com/s/1hs7gctu 密码:nk39

所有工具都在这里面啦,接下来可以放心断网看本教程

你需要:一根网线

准备工作:

首先禁用你所有网卡,除了有线连接的网卡

然后你就会发现:你断网啦~

接着我们把电脑的网线连上路由器的任意一个“LAN”口

拿出我们的工具:斐讯K2刷机工具\路由器刷breed Web助手通用版v3.0\路由器刷breed Web助手通用版v3.0.exe

右击以管理员身份运行

然后,除了用户名和密码(第一次通电开机没改过密码的除外),其他设置请完全按照我给出的执行

(仅限固件版本V22.4.6.xx的路由器,如果版本较低,你可以试试直接刷入V22.4.2.9固件,不确定的话你可以两个都试试,试试又不会怀孕)

接着,点击“开始刷机”,耐心等等就行了

等到显示要你等待两分钟再重启路由器的时候(就是软件一动不动的时候),就可以关掉路由器了

接着把路由器断电,按住复位键再通电,保持十秒再松手

等待一会儿,再打开电脑浏览器“192.168.1.1”

如果成功的话,我们可以看到breed的后台界面~

我们选“固件更新”,更新刷入固件

在固件包中我们选择“斐讯K2刷机工具\华硕固件\2016 10 11 RT AC54U GPIO 1 PSG1208 64M 3.4.3.9 099.trx”

刷入之后路由器重启

华硕固件管理地址:192.168.123.1 密码:admin 密码:admin

华硕固件默认无线密码:1234567890 SSID:PDCN

教程完毕啦~~

下面给大家看看我刷好的路由器后台:

记校园网代理中转网站的搭建过程

学校的教务系统从16年开始便只能用校内网或者是宿舍的移动网打开登陆,去年的时候我用树莓搭建了一个中转(毕竟树莓闲置着的,另外科创连的是校内网)

当时采用的是nginx+Glype当作服务端,采用的是花生壳提供的内网穿透服务,不过说实话花生壳提供的免费服务确实不咋地,后来我用了natapp.cn提供的ngrok内网转发,五块钱一个月那个。现在采用的是ngrok.cc提供的免费ngrok服务,网站总体所需流量不大,所以用这个的话效果也还可以。

下面我简单讲一下搭建的流程吧,主要就是两点:搭建nginx+php和运行ngrok服务

我在这里用的是树莓派2B,系统镜像是2015-01-31-raspbian

首先把所有该初始化的东西搞完,我们就可以开始装nginx+php了

首先安装nginx:

sudo apt-get install nginx

启动nginx:

sudo /etc/init.d/nginx start

接下来修改配置文件:

sudo nano /etc/nginx/sites-available/default

在“listen 80”那个大括号里,把“index index.html index.htm”后面加上“index.php”:

listen 80;
root /usr/share/nginx/www;
index index.html index.htm index.php;

然后找到php那一段,改成下面这样:

location ~ .php$ {
 fastcgi_pass unix:/var/run/php5-fpm.sock;
 fastcgi_index index.php;
 include fastcgi_params;
}

改完配置文件之后,保存关闭

安装php和必要组件:

sudo apt-get install php5-fpm php5-sqlite

重启nginx:

sudo /etc/init.d/nginx reload

到这里的话,nginx服务器搭建过程基本上都是抄的“树莓派开发系列教程7——树莓派做web服务器(nginx、Apache)”这篇文章里的东西,但是到后面你会发现Glype无法运行,原因其实就是php里的curl组件没装上,所以我们还需要执行以下命令:

sudo apt-get install php5-curl

你要是不嫌麻烦可以把所有需要的组件都装上:

apt-get install php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl

至此,nginx+php服务器搭建完毕,接下来只要把Glype扔到/usr/share/nginx/www里就能正常运行了,当然我改了好多东西

接下来解决外网访问的问题,我就解释一下ngrok的用法

其实用法很简单(如果你不想自己搭建服务器的话)

用ngrok.cc提供的服务举例:

首先到后台开通一个隧道,隧道协议选择“http”、本地端口写你前面设置的端口(前面配置文件里写的是80)“127.0.0.1:80”其他的按照自己的需求来写就行

然后下载官网提供的软件,树莓的话要选linux arm版,

下载之后先给777权限:

sudo chmod 777 xxxx#文件名

然后按教程运行就行了:

./sunny clientid xxxxxxxxxxxxxx

这样的话其实整个代理已经搭建完了,但是有一个重要的问题没有解决:这个服务一但遇到了停电或者是网络不稳定的情况之后,必须手动重启才可以,这样的话就会变得相当棘手。想象一下,你寒假回家了,但是服务器挂了,你找谁给你开启服务啊

所以我加了两个自动检测的脚本

一个是一分钟运行一次的“autorun.sh”,可以保证ngrok服务一直处于开启状态:

#!/bin/sh
ps -fe|grep sunny |grep -v grep
if [ $? -ne 0 ]
then
echo "start process....."
screen -dm nohup sudo /home/pi/sunny clientid xxxxxxxxxxxxxxxx &
else
echo "runing....."
fi

另一个是十分钟运行一次的“check.sh”,用于保证网站可访问,当打不开时会自动重启软件:

#!/bin/sh
result=`curl http://wfkj.papapoi.com/check.php -s`
if [ $result == "ok" ];then
echo "ok"
else
sudo killall sunny
screen -dm nohup sudo /home/pi/sunny clientid xxxxxxxxxxxxxxxx &
fi

最后打开定时任务列表:

crontab -e

加上这俩货:

* * * * * /home/pi/autorun.sh &
*/10 * * * * sudo sh /home/pi/check.sh &

大功告成!

最后把做好的网址发在这里:http://wfkj.papapoi.com/

从此,随时随地都可以让大家感受到挂科的喜悦了(雾

至今有效的从百度云高速下载可行的办法

教程之前先看看效果:

速度是很快的2333

下面准备工具,我们需要:

能装Greasemonkey或者Tampermonkey拓展的浏览器

一个百度云账号

IDM

首先安装Tampermonkey,这里我用的是chrome所以直接搜索拓展装上即可:

拓展地址:https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?utm_source=chrome-app-launcher-info-dialog

需翻墙打开,国产浏览器请自行到应用商店搜索,edge浏览器请到windows应用商店搜,firefox请搜索“Greasemonkey”这个应用

装完长这样:

然后打开https://greasyfork.org/zh-CN/scripts/23635-百度网盘直接下载助手,点击“安装此脚本”

浏览器部分准备结束。

接下来下载一个IDM

IDM请自行在网上搜索,我在这里不提供下载地址,百度IDM能有一大把

打开IDM之后,点击菜单栏“下载”-“选项”,选择“连接”选项卡,把“默认最大连接数”改成32,点确定:

(这里的32个线程看自己的需求来修改,我是开的最大的)

然后回到百度云,点一个文件来测试下,选中一个文件,然后:

其实别的可能也能用,没测试,你们自己可以试试

在弹出的链接里随便复制一个链接,扔到IDM里面

教程完毕

附:安卓手机可行的方法(仅能提速到大约800k/s)

安装ES文件管理器(推荐pro版,建议去酷安下载)、ADM

在ES里添加百度网盘,添加后打开,长按你要下载的文件,选“打开为”,选“视频”,点“ADM”

然后ADM设置里吧线程数拉到最大就行了,下载途中千万记得不要关闭ES和ADM

微软虚拟学院MVA字幕及视频获取方法

微软虚拟学院上面有许多视频,而且见解都十分独特

但是哈,它加载速度慢、只能在线看、字幕特别小、反正各种坑。。

离线下载的视频又没字幕。。。怎么办咧?

看到了一篇文章:微软虚拟学院 MVA 字幕获取方法

然而。。。。没卵用。。网站改版了。。

最后经过我的研究。。。找出了可行的办法

下面以这个链接举例:https://mva.microsoft.com/zh-cn/training-courses/-c-8295

首先打开你的IE11(其他版本不敢保证可行,可以尝试chrome,但是我的会崩溃):

打开首页后,右击空白处–审查元素:

选择“网络”选项卡:

接着打开你要下载的网址,选择你要下载的那个视频:

把“网络”选项卡拉到最下面,从下往上找,找到“video_cc.xml?v=xxxxxxxxx”这一项,右击复制URL:

在新标签打开,按住ctrl+s保存,字幕下载完毕:

然后用网页上自带的那个“下载”按钮下载视频就好(你也可以从“网络”选项卡里找到URL然后扔到qq旋风里下233)

接下来处理xml字幕为ass格式。

下载SubtitleEdit:(百度云传不上,所以大家自己必应找吧)

打开软件,从菜单选择“File-Open”打开下载的xml字幕:

从菜单选择“File-Save As”另存为ass字幕:

然后,一般视频文件名和ass字幕文件名相同的话,就会自动加载(或者自己用小丸工具箱/格式工厂把字幕嵌到视频里):

这样,就下载好了一个带字幕的视频(还有一大堆自己慢慢下载去吧2333

树莓派驱动12464OLED播放Bad Apple

效果查看:

屏幕驱动安装见 http://www.chenxublog.com/2016/08/20/raspi-12864-spi-oled.html

本视频程序下载:https://pan.baidu.com/s/1miMfwM0 密码: f3kx

制作流程:视频经过FFmpeg转换为每帧图片→通过signpics处理为128×64分辨率的图片→转为png→通过pngtopnm命令转为ppm序列图片→程序调用显示

附赠一个可以提高姿势水平的视频程序:

点我预览效果

程序下载:http://chenxublog.ctfile.com/fs/pHJ158469949

用一个小脚本在win/*nix上一键下载bing每日壁纸

昨天在逛zhiyb的github(http://zhiyb.github.io/)的时候。。。点到了他的OneDrive里看了看,结果发现了一个好像很有用的小脚本:

bing.sh

#!/bin/bash -e
url="http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=10"
data="$(curl -so - "$url")"
num="$(echo "$data" | jq -r ".images | length")"
mkdir -p images
cd images
for ((i = 0; i < $num; i++)); do
imgdata="$(echo "$data" | jq -r ".images[$i]")"
url="$(echo "$imgdata" | jq -r ".url")"
[ "${url:0:4}" != "http" ] && url="http://www.bing.com/$url"
echo "$url"
base="$(basename "$url")"
base="${base%%_*}.${base##*.}"
[ -s "$base" ] && continue
curl -o "$base" "$url"
mkdir -p json
echo "$imgdata" > json/"$base.json"
done

然而跑了跑好像少了什么组件,没跑成。。

所以我用powershell改写了一个(毕竟咱用的是windows

花了一点时间就写好了。(才发现powershell简直神器啊

bing.ps1

#by chenxublog.com
mkdir images
cd images
mkdir jsons
cd jsons
$url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=10"
$time = Get-Date
$data = Invoke-WebRequest $url
$data.Content | Out-File $time.DayOfYear
$decode = ConvertFrom-Json($data)
cd ..
$range = 1..8
$count = $range.Count
for($i=0; $i -lt $count; $i++)
{
    $temp = $decode.images.Get($i)
    Invoke-WebRequest $temp.url -OutFile ($temp.hsh + ".jpg")
}

把上面的文件保存为bing.ps1就好啦→_→ 

右击,运行!

啪!

啪啪啪!

这样每天就可以收到八张好看的壁纸啦~~

2017.3.5补充:

必应json改规则了,代码更新~~~

#by chenxublog.com
$x = Split-Path -Parent $MyInvocation.MyCommand.Definition
cd $x
mkdir images
cd images
mkdir jsons
cd jsons
$url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=10"
$time = Get-Date
$data = Invoke-WebRequest $url
$data.Content | Out-File $time.DayOfYear
$decode = ConvertFrom-Json($data)
cd ..
$range = 1..8
$count = $range.Count
for($i=0; $i -lt $count; $i++)
{
    $temp = $decode.images.Get($i)
    $urlsplit = -Join("http://www.bing.com",$temp.url)
    echo $urlsplit
    Invoke-WebRequest $urlsplit -OutFile ($temp.hsh + ".jpg")
}
echo ok!
pause

应该正常了吧。。

利用neural-style生成和目标图像风格一致的图片(win10一周年更新版可用)

几天前在知乎发现了个问题很有趣:如何评价德国计算机神经网络科学家发表的这篇可以让电脑模仿任何画家的风格作画的论文?

里面附带了一张图:点击查看~(点击后拉到最下面可以放大)

然后我在问题里发现有人已经集成好了,发到了github上面:

https://github.com/jcjohnson/neural-style

怀着不嫌麻烦的精神,为了满足自己的好奇心,开始了这几天的折腾

先是看到这货不支持windows,于是我找到了几个Python版本。。。然而。。也没法运行在windows上。。

后来我想到了,win10一周年更新版好像自带了一个Ubuntu子系统来着(微软大法好

下面讲讲怎么运行这玩意

0x00、打开linux的bash命令行:

你可以:

  1. 直接在linux系统里跑(直接跳过这一段

  2. 在win10一周年更新版中运行(仅限专业版,家庭版貌似没有这个功能)之前疏忽,其实是有的)

开启win10bash方法:

  1. 右击开始菜单-控制面板

  2. 点击“程序”那一栏下面的“卸载程序”

  3. 点击左边栏的“启用或关闭windows功能”

  4. 拉到最下面,选上“适用于linux的windows子系统”(如果没有这一项,说明你的系统不是win10专业版或没进行上一周年更新升级)

5.重启之后,按win+r(windows徽标键+R键)呼出运行窗口,输入“cmd”,然后回车。

这时可能要设置密码和用户名,自己设置吧。

最后在输入框内输入“bash”,并且回车,即可开启bash。

0x01、将源换为国内源:

首先取得root权限,这样方便,如果不想这样的话,可能会权限不足,只要命令前面加一句“sudo”即可:

sudo su
#然后输入密码回车

为了下载软件快点,所以把源还为国内的

输入指令:

sudo vi /etc/apt/sources.list

按一下“INSERT”键,删掉原有的所有文字,换上你要用的源,具体的列表可以见此(点击查看),由于我在学校,所以用的是中国科学技术大学更新服务器的源,如下:

deb http://debian.ustc.edu.cn/ubuntu/ trusty main multiverse restricted universe
deb http://debian.ustc.edu.cn/ubuntu/ trusty-backports main multiverse restricted universe
deb http://debian.ustc.edu.cn/ubuntu/ trusty-proposed main multiverse restricted universe
deb http://debian.ustc.edu.cn/ubuntu/ trusty-security main multiverse restricted universe
deb http://debian.ustc.edu.cn/ubuntu/ trusty-updates main multiverse restricted universe
deb-src http://debian.ustc.edu.cn/ubuntu/ trusty main multiverse restricted universe
deb-src http://debian.ustc.edu.cn/ubuntu/ trusty-backports main multiverse restricted universe
deb-src http://debian.ustc.edu.cn/ubuntu/ trusty-proposed main multiverse restricted universe
deb-src http://debian.ustc.edu.cn/ubuntu/ trusty-security main multiverse restricted universe
deb-src http://debian.ustc.edu.cn/ubuntu/ trusty-updates main multiverse restricted universe

复制之后按右键即可粘贴,输入完毕后按“ESC”然后输入“:wq”回车即可保存。

0x02、安装torch7运行库:

依次运行如下命令:

cd ~/
curl -s https://raw.githubusercontent.com/torch/ezinstall/master/install-deps | bash
git clone https://github.com/torch/distro.git ~/torch --recursive
cd ~/torch; ./install.sh

下载过程可能较长,可以喝杯茶冷精一下Σヽ(゚Д ゚; )ノ

然后一小时过去了

设置环境变量,运行如下命令:

source ~/.bashrc

0x03、安装loadcaffe运行库:

输入命令安装必要的包:

sudo apt-get install libprotobuf-dev protobuf-compiler

由于更换了国内源,速度应该是很快的,如果速度只有一秒十几k,请更换源再试

输入指令安装loadcaffe:

luarocks install loadcaffe

这个下载过程也可能较长,可以再喝杯茶冷精一下Σヽ(゚Д ゚; )ノ

然后又一个小时过去了

0x04、下载最后的大boss:

依次运行命令:

cd /mnt/e/test/    # 这里指“E:\test”文件夹,根据自己的需要改吧
git clone https://github.com/jcjohnson/neural-style.git
#上面从github下载比较慢的可以试试我fork到国内的源:
#https://git.oschina.net/chenxuuu/neural-styleneural-style.git
cd neural-style

这个下载过程也可能较长,可以再再喝杯茶冷精一下Σヽ(゚Д ゚; )ノ

然后又一个小时过去了

运行如下命令下载最后需要的大头。几百M,很大,我是直接用qq旋风下载的然后复制进去的2333

sh models/download_models.sh

这个下载过程也可能较长,可以再再再再再再喝杯茶冷精一下Σヽ(゚Д ゚; )ノ

然后又一天过去了

做完这些事之后运行下面的命令测试一下能不能运行:

th neural_style.lua -gpu -1 -print_iter 1

如果显示如下图所示的东西就说明可以运行:

0x05、来运行吧!:

先切换到软件文件夹下(自己看着改吧!路径不一定和我的一样)

cd /mnt/e/test/neural-style

把图片也扔到这个文件夹下面~(必须jpg格式)

运行命令!(CPU燃烧吧!)

th neural_style.lua -style_image the_scream.jpg -content_image in.jpg -gpu -1
#命令解释:th neural_style.lua -style_image 风格图片 -content_image 想处理的图片 -gpu -1 ←win10自带的不支持cuda,所以就让CPU累着吧2333

生成结果很好啊:

选择的图:

风格图:

生成结果:

另外生成的时候会每运行10%放出一张预览图,下面的就是:

最后,小彩蛋:

树莓派驱动SPI接口的12864OLED屏

昨天玩了玩18b20,然后今天想起来还有两块从车上扣下来的12864小OLED屏,所以准备研究下

然后发现这个库依旧依旧有人写好了23333

(怪不得树莓那么多人玩)

以下教程不完全参考自(毕竟理论和实际会有出入233):http://www.dfrobot.com.cn/community/thread-13396-1-1.html

先看看效果图:

这个功能和某宝上的“CPU Info”差不多啊。。。(黑粗翔

下面开始教程:

0x00、硬件连接√:

照例,贴一张树莓的针脚分布图:

按照下面的来对应连接:

GND 任意一个0v
VCC 任意一个5v/3.3v
D0(SCLK) 23号物理接口
D1(MOSI) 19号物理接口
RST 11号物理接口
DC(数据与命令选择) 13号物理接口
CS(SPI 片选) 24号物理接口

最好整齐的连上,下图是错误的示范:

请大家不要连的像我的一样这么杂乱(笑

0x01、启动SPI服务

在树莓开机后输入命令:

sudo raspi-config

选“Advanced Options”这一项,找到“SPI”和“I2C”,开启就好。

然后重启树莓派:

sudo reboot

重启后运行指令:

cd /dev
ls -al

如果你看到了这两项,就说明刚才的设置成功了:

0x02、安装SPI屏幕的库:

先安装必要组件:

sudo apt-get update
sudo apt-get install build-essential python-dev python-pip
sudo pip install RPi.GPIO
sudo apt-get install python-imaging python-smbus
sudo apt-get install git

然后,将SPI屏驱动函数的库下载下来:

cd ~
git clone https://git.oschina.net/chenxuuu/Adafruit_Python_SSD1306.git
#这里我换成了国内源,为的是速度快一些,原地址:https://github.com/adafruit/Adafruit_Python_SSD1306.git

安装Python的SPI驱动模块:

cd Adafruit_Python_SSD1306
sudo python setup.py install

0x03、测试程序:

测试Python代码如下:

#!/usr/bin/python/
# coding: utf-8
import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
import Image
import ImageDraw
import ImageFont

# Raspberry Pi pin configuration:
RST = 17
# Note the following are only used with SPI:
DC = 27
SPI_PORT = 0
SPI_DEVICE = 0

# 128x64 display with hardware SPI:
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))

# Initialize library.
disp.begin()

# Clear display.
disp.clear()
disp.display()

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = disp.width
height = disp.height
image = Image.new('1', (width, height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a black filled box to clear the image.
draw.rectangle((0,0,width,height), outline=0, fill=0)

# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
padding = 1
top = padding
x = padding
# Load default font.
font = ImageFont.load_default()

# Alternatively load a TTF font.
# Some other nice fonts to try: http://www.dafont.com/bitmap.php
#font = ImageFont.truetype('Minecraftia.ttf', 8)

# Write two lines of text.
draw.text((x, top), 'This is first line', font=font, fill=255)
draw.text((x, top+10), 'This is second line', font=font, fill=255)
draw.text((x, top+20), 'This is third line', font=font, fill=255)
draw.text((x, top+30), 'This is fourth line', font=font, fill=255)
draw.text((x, top+40), 'This is fifth line', font=font, fill=255)
draw.text((x, top+50), 'This is last line', font=font, fill=255)

# Display image.
disp.image(image)
disp.display()

至于我用的代码,我也给大家贴出来:

#!/usr/bin/python/
# coding: utf-8
import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
import Image
import ImageDraw
import ImageFont

import socket
import fcntl
import struct
def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])
	

while True:

	# 打开温度传感器文件
	tfile = open("/sys/bus/w1/devices/28-0115a83f87ff/w1_slave")
	# 读取文件所有内容
	text = tfile.read()
	# 关闭文件
	tfile.close()
	# 用换行符分割字符串成数组,并取第二行
	secondline = text.split("\n")[1]
	# 用空格分割字符串成数组,并取最后一个,即 t=23000
	temperaturedata = secondline.split(" ")[9]
	# 取 t = 后面的数值,并转换为浮点型
	temperature = float(temperaturedata[2:])
	# 转换单位为摄氏度
	temperature = temperature / 1000

	# Raspberry Pi pin configuration:
	RST = 17
	# Note the following are only used with SPI:
	DC = 27
	SPI_PORT = 0
	SPI_DEVICE = 0

	# 128x64 display with hardware SPI:
	disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))

	# Initialize library.
	disp.begin()

	# Clear display.
	disp.clear()
	disp.display()

	# Create blank image for drawing.
	# Make sure to create image with mode '1' for 1-bit color.
	width = disp.width
	height = disp.height
	image = Image.new('1', (width, height))

	# Get drawing object to draw on image.
	draw = ImageDraw.Draw(image)

	# Draw a black filled box to clear the image.
	draw.rectangle((0,0,width,height), outline=0, fill=0)

	# Draw some shapes.
	# First define some constants to allow easy resizing of shapes.
	padding = 1
	top = padding
	x = padding
	# Load default font.
	font = ImageFont.load_default()

	# Alternatively load a TTF font.
	# Some other nice fonts to try: http://www.dafont.com/bitmap.php
	#font = ImageFont.truetype('Minecraftia.ttf', 8)

	# Write two lines of text.
	draw.text((x, top), "Chenxu's Raspebrry Pi", font=font, fill=255)
	draw.text((x, top+10), time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())), font=font, fill=255)
	draw.text((x, top+20), 'The temperature:' + str(temperature), font=font, fill=255)
	draw.text((x, top+30), "Pi's ip:", font=font, fill=255)
	draw.text((x, top+40), 'eth  ip:'+ get_ip_address('eth0'), font=font, fill=255)
	draw.text((x, top+50), 'wlan ip:'+ get_ip_address('lo'), font=font, fill=255)

	# Display image.
	disp.image(image)
	disp.display()
	time.sleep(5)

教程完毕√

更新:

加了个显示内存占用的功能,代码如下

#!/usr/bin/python/
# coding: utf-8
from __future__ import print_function
from collections import OrderedDict

import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
import Image
import ImageDraw
import ImageFont

import socket
import fcntl
import struct
def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])
	
def meminfo():
    meminfo = OrderedDict()
    with open('/proc/meminfo') as f:
        for line in f:
            meminfo[line.split(':')[0]] = line.split(':')[1].strip()
    return (format(meminfo['MemFree']) + '/' + format(meminfo['MemTotal']))

while True:
	
	# 打开温度传感器文件
	tfile = open("/sys/bus/w1/devices/28-0115a83f87ff/w1_slave")
	# 读取文件所有内容
	text = tfile.read()
	# 关闭文件
	tfile.close()
	# 用换行符分割字符串成数组,并取第二行
	secondline = text.split("\n")[1]
	# 用空格分割字符串成数组,并取最后一个,即 t=23000
	temperaturedata = secondline.split(" ")[9]
	# 取 t = 后面的数值,并转换为浮点型
	temperature = float(temperaturedata[2:])
	# 转换单位为摄氏度
	temperature = temperature / 1000

	# Raspberry Pi pin configuration:
	RST = 17
	# Note the following are only used with SPI:
	DC = 27
	SPI_PORT = 0
	SPI_DEVICE = 0

	# 128x64 display with hardware SPI:
	disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000))

	# Initialize library.
	disp.begin()

	# Clear display.
	disp.clear()
	disp.display()

	# Create blank image for drawing.
	# Make sure to create image with mode '1' for 1-bit color.
	width = disp.width
	height = disp.height
	image = Image.new('1', (width, height))

	# Get drawing object to draw on image.
	draw = ImageDraw.Draw(image)

	# Draw a black filled box to clear the image.
	draw.rectangle((0,0,width,height), outline=0, fill=0)

	# Draw some shapes.
	# First define some constants to allow easy resizing of shapes.
	padding = 1
	top = padding
	x = padding
	# Load default font.
	font = ImageFont.load_default()

	# Alternatively load a TTF font.
	# Some other nice fonts to try: http://www.dafont.com/bitmap.php
	#font = ImageFont.truetype('Minecraftia.ttf', 8)

	# Write two lines of text.
	draw.text((x, top), "Chenxu's Raspebrry Pi", font=font, fill=255)
	draw.text((x, top+10), time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())), font=font, fill=255)
	draw.text((x, top+20), 'The temperature:' + str(temperature), font=font, fill=255)
	draw.text((x, top+30), meminfo(), font=font, fill=255)
	draw.text((x, top+40), 'eth  ip:'+ get_ip_address('eth0'), font=font, fill=255)
	draw.text((x, top+50), 'wlan ip:'+ get_ip_address('lo'), font=font, fill=255)

	# Display image.
	disp.image(image)
	disp.display()
	time.sleep(5)