2017年2月26日 星期日

初試 pix2pix 失敗


昨天在 Facebook 貼了一個新的機器學習示範程式 pix2pix,只要繪畫邊緣,程式就可以將它變成手袋圖片。十分有趣。

我下載了 Tensorflow 版本,按照指示在我的 MacBook Pro 上進行組譯。等了一會出現錯誤:

可能是由於我的 MacBook Pro Late 2013 沒有適合的 GPU。不過,我在公司的 Mac mini 卻能進行組譯,它同樣是 Intel 的顯示卡,沒有 nvidia 晶片。由於只得 CPU 運算,到目前還在組譯中...希望能夠成功!

2017年2月25日 星期六

編寫同步計時器


今早出席了同事的婚禮後回家,加班了六小時去開發一個網頁項目。

這個項目只讓指定使用者登入,並會贈送一份優惠。使用者要在指定時間內使用,否則會過期作廢。畫面有計時器給大家知道還餘下多少時間。寫這個網頁的難度在於考慮到不同情況下都要還原應有的狀態。例如:
  1. 當計時器倒數到 20 分鐘時,若用戶按「刷新」鍵,數值需要繼續同步倒數,而不是重頭來過
  2. 使用者的手機跳入睡眠模式 10 分鐘後回到網頁,數值同樣需要繼續同步倒數,即是要減去 10 分鐘
  3. 使用優惠後按返回鍵,程式要知道狀況已經更新,不再顯示計時器。如此類推

就第一點,我的做法是使用 PHP 去生成 HTML 碼,並在 PHP 中計算出尚餘秒數,把數值插入 HTML 內。

至於第二點,我用 visibilityChange 事件去記錄離開瀏覽器的時間,並在返回時計算一下失去多少時間,再更新計時器。
document.addEventListener("visibilitychange", handleVisibilityChange, false);
var _lastFired = null;
function handleVisibilityChange()  {
 if (document.hidden)  {

  _lastFired = new Date().getTime();
 } else  {
  if (_lastFired != null)  {

   var currentFired = new Date().getTime();
   var different = (currentFired-_lastFired);
   var second = parseInt(different/1000);

   //  TODO: Update timer or values
  }
 }
}

最後,第三點,同樣也是在 PHP 動手腳,加入以下指令,避免緩衝:
header("Cache-Control: no-cache, must-revalidate, no-store, max-age=0");
header("Pragma: no-cache");
header("Expires: Tue, 10 Mar 1987 00:00:00 GMT");

2017年2月23日 星期四

微信伺服器認證問題


微信機械人的編程工作完成了,得由測試服轉為正式服。在微信後台輸入正式服的網址,打好了認證簽字,點下「提交」掣,出現「認證失敗」。改回測試服再試一次,卻「認證成功」。非常奇怪。

正式服使用 Udomain。試過不止一次,它的伺服器會懶醒地把數據偷偷地改了。於是我把傳入的數據記錄下來,用 Postman 模擬一下,不論是測試服還是正式服,都有相同的長度、相同的結果。只是檔頭有少許不一樣,但不會影響認證。既然 99% 一致,那麼焦點落在連線上。其中一個可能性是微信國內的伺服器連不上 Udomain。Access Log 及 Error Log 找不到認證的影子,然而程式中的活動記錄卻有寫進檔案;意味著假設不成立。於是又想,會不會是 The Great Firewall 做的好事?沒欄測試服,只欄正式服。向 Udomain 求證,他們說沒有問題。

在毫無頭緒的情況下,想到目前 HTTP 的請求會自動轉到 HTTPS 渠道,會不會這個設定有所影響呢?認證網址一直都用 HTTPS,心想 99% 不關事吧。在沒有出路的情況下唯有一試。關閉了跳轉程式,再次認證,再次「認證失敗」。隨手也試試 HTTP,今次卻成功了。雖然不清楚問題的原因,但估計是 SSL 證書,或是 VirtualHost 設定出事吧。有待研究。

2017年2月22日 星期三

用 Javascript 關閉微信內建瀏覽器


最近開發了一個簡單的 WeChat Bot。沒有甚麼功能,只在「關注」時生成一條網址;點擊網址會去到一個由 HTML 寫成的表格。填妥後會跳轉到「多謝」頁面。可是微信的檔頭出現的「返回」掣卻是返回上一頁,但我想的是「關閉」。原來微信內建的瀏覽器會自動載入自帶的 JS 功能,只要調用:
WeixinJSBridge.call('closeWindow');
就能關閉瀏覽器。另外還有其他的 WeixinJSBridge 功能,例如:
WeixinJSBridge.call('hideOptionMenu');
減少微信選單內的分享項目。即是由原來左面的選單,變成右面的選單。

2017年2月21日 星期二

初試 LUIS


上星期出席了 Microsoft Tech Submit,發現 LUIS 好像很好用,而且訓練數據不多就能順利分類,很想試試。今晚登入 LUIS 後,雖然有少許教學指引,但還是不清楚該做哪試事。

後來發現 https://www.luis.ai/Help 中有兩段 YouTube 教學,花了廿分鐘左右時間看完,才能懂得使用 LUIS 的介面。想嘗試 LUIS 的朋友一定要看。

2017年2月18日 星期六

一口好茶:工藝茶花束


內子從店裡帶回新的產品,是一枝枝獨立的工藝茶花束。跟之前情人節的花束不同,也過了情人節,正在思考要如何拍這張照片。

之前設計了 23 張海報,都是有大量的後期製作,如:退地、調節光暗、變色、加背景、加效果...等處理。今次想回歸基本,用照片表達情感。我覺得花束由少女把持的感覺最為溫馨,於是找來長女扮演模特兒。以往習慣連拍數張,避免手震或不對稱問題;今次卻隨意拍了一張。在家中拍的相片,出來的效果十分好。在構圖上,我認為花要突出,模特兒要不露臉,以免搶去主體的焦點。所以用了長鏡把背景打矇。女兒找來的外套顏色剛好能襯托出藍色的花束。多個巧合匯聚成這張作品,我自己也很喜歡。

2017年2月11日 星期六

微信 JS-SDK 需要 ICP 牌照


微信 WeChat 是對話機械人的先驅,比起 Facebook 及其他的 ChatBot 早了幾年上市。其實除了能在 WeChat 中開發 ChatBot 外,還能在網頁上用上 JS-SDK 來偵測在 WeChat 內的使用活動。在慕課網找到「PHP 微信公眾平台開發高級篇—微信 JS-SDK」這個免費課程講解了相關的技術。可是,要用 WeChat 的 JS-SDK,需要得到 ICP 牌照,否則 Javascript 程序無法順利執行。又沒有得嘗試...。

2017年2月10日 星期五

初試 Microsoft Azure Machine Learning Studio


三個星期前,拿到了 Microsoft Azure Machine Learning Studio 帳號,可以試試 Microsoft 的人工智能有多強。我第一時間想到利用它來預測股票走勢,而當中一個部份可以給用戶載入自編的 Python 程序。於是我問 Microsoft 負責人關於這個平台能否讀進第三方的 Python Package 呢?他說:「沒問題」。於是我便嘗試相關的方法。


看過文件,知道把 Python package 當成 dataset 檔案上傳到 Azure Storage 後,便能在 Machine Learning Studio 內的程序中調用。我依著指示進行,可是卻出現導入問題。想想可能是因為 yahoo_finance 這個 package 中有兩個 .py 檔,而文件範例只有一個;於是手動把它變成一個獨立檔案,然後上傳,然後再次失敗。後來向負責人查證,發現 Machine Learning Studio 是不支援的,只好放棄這個部份,繼續嘗試其他的功能...。

2017年2月9日 星期四

加入微信測試帳號


要測試寫好的 WeChat Bot,可以把 WeChat 帳號加入成為測試帳號。

登入「微信公眾平台」後選「開發者工具」,在右面頁面選「公眾平台測試帳號」後方的「進入」。再用想加入測試帳號的 WeChat 掃瞄畫面上的二維碼,點「關注」。該 WeChat 帳號便能成為測試帳號,從而測試 WeChat Bot 的功能。

2017年2月8日 星期三

認證微信機械人伺服器


要開發 WeChat Bot,需要有微信公眾帳號。就像建立 Facebook Messenger Bot 一樣,在平台內建立應用程式,得到 App ID 及 App Secret;拿著這兩串數值換來兩小時期限的 Access Token;往後的 API 都是用 Access Token 來執行。

每個應用程式都需要一個伺服器用來接收由客戶發出的訊息;就像 Webhook 的方法差不多。所以,第一步得對伺服器做認證工作。根據上圖的要求去做認證。如果運算結果符合時,傳回 echostr 代表。以下是我的認證程式:
<?php
//----------------------------------------------------------------------------------------
//  WeChat Open Platform Test
//  API Token Checking Program
//----------------------------------------------------------------------------------------
//  Platform: Linux + Apache + PHP
//  Written by Pacess HO
//  Copyright 2017 Pacess Studio.  All rights reserved.
//----------------------------------------------------------------------------------------

header("Access-Control-Allow-Origin: https://home.pacess.com");
header("Access-Control-Allow-Methods: POST");

header("Content-type: text/plain");
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Tue, 10 Mar 1987 00:00:00 GMT");

date_default_timezone_set("Asia/Hong_Kong");
mb_internal_encoding("UTF-8");
ini_set("memory_limit", "-1");
set_time_limit(0);

//----------------------------------------------------------------------------------------
//  Defines
define("TOKEN", "sita-chan");

//----------------------------------------------------------------------------------------
//  * Order is important
require("./libraries/wechatAPI.php");

//========================================================================================
//  Main Program
$_interfaceType = php_sapi_name();

//  apache2handler = Browser
//  cli = Terminal
if ($_interfaceType == "cli")  {
   echo("Please run this program with browser...");
   exit(0);
}

//----------------------------------------------------------------------------------------
$wechatAPI = new wechatAPI();
$wechatAPI->valid();
echo("Sorry, validation failed...");

?>
index.php

<?php
//----------------------------------------------------------------------------------------
//  WeChat Open Platform Test
//  WeChat API Test Object
//----------------------------------------------------------------------------------------
//  Platform: Linux + Apache + PHP
//  Written by Pacess HO
//  Copyright 2017 Pacess Studio.  All rights reserved.
//----------------------------------------------------------------------------------------

//========================================================================================
//  Main Program
class wechatAPI  {
      
   //----------------------------------------------------------------------------------------
   private function checkSignature()  {
      if (!defined("TOKEN"))  {throw new Exception('TOKEN is not defined!');}
      
      $signature = $_GET["signature"];
      $timestamp = $_GET["timestamp"];
      $nonce = $_GET["nonce"];
      $token = TOKEN;

      $parameterArray = array($token, $timestamp, $nonce);

      //  Use SORT_STRING rule
      sort($parameterArray, SORT_STRING);
      $string = implode($parameterArray);
      $sha1 = sha1($string);
      
      return ($sha1 == $signature);
   }

   //----------------------------------------------------------------------------------------
   public function valid()  {
      $echoStr = $_GET["echostr"];
      if ($this->checkSignature())  {echo($echoStr);  exit;}
   }
}
?>
wechatAPI.php

認證成功後,便可以正式編寫 WeChat 機械人的程式。