2020年12月30日 星期三

技術筆記:因工作需要架個簡單網站,兼回想曾在網路公司時的青春

前兩天開會時提到,配合文管需要,得有個能上傳WORD,系統自動轉換為PDF(帶浮水印)後,就立刻啟動下載程序的網路服務。聽到網路程式,大家你看看我,我看看你,都是雙手一攤,誰要我們是竹科硬體系統廠呢?但若是在我年輕時任職的網路公司,這種要求只是塊小蛋糕屑屑。所謂術業有專攻,就是這個意思吧。

既然我總是最閒的人,就接了這差事。而原本打算簡單裝個node.js模組(連結 連結)快速搞定,卻因為機器是躲在防火牆和嚴密資安監控,根本無法"安裝"軟體,只能在現有Windows Apache帶著Tomcat的架構上想辦法。只是十多年沒碰伺服器程式,進行時處處碰壁,筆記重拾記憶的雜亂過程時,兼回想過往在網際網路產業工作時的青春。

自己從學生時期就是主修資訊管理,抱著對大規模資料處理的夢想與熱情,甫畢業就加入蕃薯藤網站,也是華人最早的入口網站,幾年後再到以知識檢索見長的宇匯科技。這段期間日日夜夜接觸所及都與網際網路息息相關,且不只是我或少數公司,環顧當時Openfind、奇摩、雅虎、PCHOME等各家公司,無論是工程師或管理階層,都相信只要憑藉著技術,就能建構起偉大服務,然後就能販售產品,取得流量,處處充滿著躍躍欲試的氛圍。

但事與願違,以我自己來說,離開宇匯後進入硬體代工廠後,就再也沒碰觸過任何伺服器,而前述曾經如日中天的企業,若不是轉型為電子商務,也都消弭於市場機制中。今日與大多數人緊綁在一起的服務,無論是臉書、IG、LINE、GOOGLE各種服務,都並非由上述台灣公司演化而來,而是全由國外企業建立。

我當然不是什麼社會觀察家,但只要有眼睛,應該都能發現,與三十年前網際網路推出時狀況相比,現今世界取得資訊的管道是更為集中了。以往標榜的分散式、分權化早已消失於無形。使用者益發向少數資訊平台靠攏。而且不幸的是,這股平台洪流隊伍中,幾乎沒有任何是出自於台灣"軟體"廠商之手。

這絕對不是本土廠商犯了什麼錯誤,而是大勢所趨,但對每個曾經投入網際網路初期發展的人來說,如今軟體廠商的邊緣化,真的是僅有唏噓可以形容。無獨有偶的是,前年開始的人工智慧浪潮,似乎是前述翻版。

扯遠了,回到我那小小的轉換功能。檢視Windows上WORD轉換成PDF的方案,首推C#,但在Apache環境下,似乎只能含淚使用JAVA,連帶還得使用骨灰等級的tomcat、JSP、Servlet就覺得有些無奈。

JSP / Servlet

Apache版本是骨董等級的2.2版,設定在conf/httpd.conf,未來XXX domain服務會自動轉往tomcat服務。

<VirtualHost *:80>ServerName XXX
    ProxyPass / http://XXX:8081/
    ProxyPassReverse / http://XXX:8081/
</VirtualHost>

而Tomcat是更為久遠的6.0版(原atlassian自帶版本過於混亂,也不敢改),安裝在tool\xxxportal\xxx6.0。依序調整port  conf/server.xml  <Connector port="8081"... (原本8080已被占用,改為8081),和bin\startup.bin,在開頭加入下面兩行。若command直接執行startup.bat。

set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_11
set CATALINA_HOME=C:\目前目錄\apache-tomcat-6.0.0

在webapp\ROOT\下簡單放入個JSP,以http://127.0.0.1:8081/DateJSP.jsp,確認執行無誤後,繼續加入servlet。

對習慣使用Django或ROR等WEB應用框架的人來說,JSP實在是又土又難用,若要用MVC還得另外引入Spring Framework,IDE雖然可用ECLIPSE(連結),但最新版ECLIPSE的JAVA都飛到11版了,版號差異太大,評估後決定靜下心研究如何以command模式編譯需要的java成為servlet。

先簡單製作MyServlet.java,貼入

class MyServlet {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}
javac MyServlet.java  -> MyServlet.class -> java MyServlet (應該是省略jar部分)
改換成
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class MyServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException 
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>Hello Readers</h1>");
        out.println("</body></html>");
    }
}
javac -classpath C:\tool\XXX\apache-tomcat-6.0.0\lib\servlet-api.jar MyServlet.java  (servlet需要的內容放在classpath中)
把MyServlet.class,放在.\webapps\ROOT\WEB-INF\classes 下,修改WEB-INF\web.xml(連結)
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
重新啟動tomcat  http://127.0.0.1:8081/hello  確認JSP與Servlet連結無誤。

繼續參考(連結)完成網頁上傳檔案服務。

javac -classpath C:\XXX\apache-tomcat-6.0.0\lib\servlet-api.jar;commons-fileupload-1.2.jar;commons-io-2.2.jar FileUploadServlet.java

編成的class放入C:\XXX...\webapps\ROOT\WEB-INF\classes\net\codejava\upload (後面這串是配合package而寫)  同時要把jar放在 C:\XXX...\webapps\ROOT\WEB-INF\lib 中,修改web.xml為

<servlet>
    <servlet-name>FileUploadServlet</servlet-name>
    <servlet-class>net.codejava.upload.FileUploadServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>FileUploadServlet</servlet-name>
    <url-pattern>/uploadFile</url-pattern>
</servlet-mapping>
把相關JSP放好,連結 http://127.0.0.1:8081/upload.jsp 上傳檔案會在.\webapps\ROOT\upload,並顯示message.jsp。

至此已經大致完成,最後探討WORD轉換為PDF方案,先測試jofficeconvert(連結),以console編譯和執行方式為

1.javac -classpath jofficeconvert.jar WordToPDF.java (程式在此,會使用lib)
2.jar -cf WordToPDF.jar WordToPDF.class (將class編入jar檔案中)
3.java -cp jofficeconvert.jar;WordToPDF.jar WordToPDF 直接執行class中function

確認無誤後,嘗試將這組程式併入前段的上傳範例 javac -classpath C:\XXX\apache-tomcat-6.0.0\lib\servlet-api.jar;commons-fileupload-1.2.jar;commons-io-2.2.jar;jofficeconvert.jar FileUploadServlet.java  將新產生的class比照上傳範例更新,測試成功。最後是修改message.jsp,上傳完畢後,servlet啟動轉換程序,並且讓瀏覽器透過JSP繼續下載已經轉換完的PDF檔案。


SPRING Framework

工作持續演進,需要個簡易佈告欄功能。參考(連結),並且開始使用spring framework,ECLIPSE和MAVEN。tomcat是單獨安裝8.5。(eclipse內部安裝似乎有副作用)

ECLIPSE位置在/home/kayjean/eclipse/jee-2020-12/eclipse,啟動,選擇window -> preference -> server -> runtime environment ...  設定兩者可以結合。未來,系統會自動包裹進入/home/kayjean/eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/tomcat1/WEB-INF/xxx 且由ECLIPSE直接 啟動該tomcat。

MAVEN

曾嘗試單獨安裝Spring和其他套件,遭遇太多困難,決定啟用MAVEN。在ECLIPSE中file->new->maven project->skip page 1 , page 2 wait 10 seconds , choose org.apache.maven.archetypes maven-archetype-webapp -> groupid(company name ex:com.altek.medical) artifact id(project name ex:portal)   至此,先測試right click project->run as->run on server -> choose server -> choose correct war set
http://localhost:8080/portal/  -> Hello World 測試成功.  (重複測試時發生error :
The superclass "javax.servlet.http.HttpServlet" was not found... 解決方式是property->project facets->runtimes-> enable server

pom file中加入下面內容
    <spring.version>4.2.0.RELEASE</spring.version>
    <jstl.version>1.2</jstl.version>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>

重新開始(clean),就會發現JSP編譯失敗。在java build path -> libraries -> add library -> server runtime -> choose tomcat 8.5,在order中選擇並且放到最上面,且enable。回到原始控制台,JSP正常,並且出現src/main/java可以加入我們的程式碼。

XML要另外加入xpath
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jaxen/jaxen -->
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.6</version>
</dependency>

Controller

Spring Framework最核心概念為MVC,程式上乃依靠bean在運作。所有瀏覽器傳送過來的URL,凡包含xxx.do,會由bean轉交給org.springframework.web.servlet.DispatcherServlet處理。DispatcherServlet規則是解析 /WEB-INF/appconfig-root.xml 的設定,如<context:component-scan base-package="com.altek.medical.board.dao.*"/> ,由目錄名稱,自動對應到需要的CLASS且開始執行。處理結果,可用下面幾種方式回傳使用者。

  • return xxx,xxx就會變成xxx.jsp
  • return "redirect:/jsps/user_login.jsp"
  • 呼叫另外controller
  • spring注射方式

JSP類會在JSP目錄中尋找配對檔案,將servlet資料與JSP頁面整合後輸出。

使用者帳密

Tomcat似乎能請瀏覽器將當時電腦的網域登錄名稱傳回伺服器(連結)。測試結果失敗,但若是要整合AD是有可能的(連結 連結 連結),取得名稱方式(連結 連結)。

2020年12月23日 星期三

手作烘焙趣

關於自製蛋糕,我可是有夢的。記得新婚不久時就心血來潮照著食譜試做海綿蛋糕,忙活了一陣,成品硬硬扁扁好像餅乾,被老婆譏笑是馬拉糕,悲憤之餘,就此再與蛋糕無緣,世界上也就少了一位烘培王啦(笑)。

時隔十數年,時間來到今年十月,因著老媽生日,突發奇想要重起爐灶完成那個小小心願。與以往不同,這時代各種蛋糕作法和教戰手冊隨手可得,家中也添購過電動打蛋機(以往失敗就是缺這個),且烘培原料行也近在咫尺(巧婦食品烘培),還增添了女兒這個小幫手。各種有利因素加持下,總算有了點成果,雖不中但也亦不遠矣。

動手做的過程中,從原料的採購、量秤,以及依步驟實現過程,無論是滿桌的瓶罐,或是用克為單位錙銖必較的心情,都讓人有回到高中時代化學實驗室的錯覺,直到成品出爐,就算是失敗品也覺得興奮,再經過逐步修正,更能滿足小小成就感。且就成果來說,相比於慢跑、爬山、看小說這些對居家生活沒什麼貢獻的活動,做蛋糕或許更能被老婆和女兒接受吧(笑)。

最近又要做蛋糕,發現事隔三個月先前記憶全部消失,趕緊翻出先前照片並筆記,若後續還有新作也能繼續累積。

海綿蛋糕

參考連結

常溫雞蛋3顆(全蛋) + 細砂糖60g 混合。

放在50度c的鍋子上方用隔水加熱的方式加熱。

下次要添購溫度計量測水溫

打蛋器以高速將蛋液打到起泡並且蓬鬆的程度,過程中,用手指不時試一下蛋液的溫度,若感覺到溫熱的程度就將鋼盆從沸水上移開,聽說這個原理是利用蒸氣加熱使得雞蛋表面張力變弱而容易起泡,所以溫度只要加溫到體溫的程度就好,太燙是會讓雞蛋凝結的。(高中化學是55度,蛋白質質變)。重複這個過程打了七分鐘,打到蛋糊蓬鬆拿起打蛋器滴落下來的蛋糊能夠有非常清楚的摺疊痕跡,也有人說是能寫完8。

低筋麵粉50g過篩(這過程有點麻煩,玉米粉10g缺)。分成三次以濾網低低過篩進蛋糊中,用刮刀混合均勻(這裡出現歧異,Carol說可以用打蛋器攪拌均勻,但又有人說這樣會造成消泡,盡量不要狂打 連結)。實作上,前兩個成品都太扁,所以最後一個在這階段混入了數克泡打粉,成品的確更高,也不確定真實原因。

無鹽奶油20g以微波融化(家中微波爐壞了改用隔水加熱),指示中提到香草精1/4茶匙(略過),從前面整鍋麵糊取出部分倒入奶油攪拌均勻,再倒回鍋中,繼續用打蛋器攪拌均勻(又是不確定部分)。


依序混入麵粉和奶油後

將蛋糊倒入已抹油且放好紙的特殊烤盤,其下方特殊設計能方便取出蛋糕本體。


放入已經預熱到170度C的烤箱中烘烤30-32分鐘至竹籤插入中心沒有沾粘即可(怪怪的,聽說到烤好前不能打開,這樣要如何插入竹籤)。

出爐後馬上倒扣在鐵網架上,指示是包覆擰乾的濕布放涼,我們則是蓋上濕的餐巾紙,放涼後撕去底部及邊緣烤焙紙(專業的會放入塑膠袋中休息一夜避免乾燥)。從照片可看到,到第三個成品時,已到可接受程度,而前面兩個既然都進了我肚子,當然也稱不上失敗歐。

由上至下,分別是第一次至第三次成品,體積明顯膨脹。

最後抹上奶油加了水果,成為老媽生日蛋糕,感謝家人抬愛,都吃得挺開心的。

動物鮮奶油打發

參考連結,買了兩盒動物性鮮奶油,每盒200g,加入細砂糖20g,就是開攪拌機狂打。第一次實驗失敗,就是所謂油水分離(這名詞很聳動),此為不可逆反應,雖說仍可用在義大利麵,仍是進了廚餘桶。

或許因為盛夏時節,造成油水分離

參考更多說明,必須在鋼盤下放置冰袋,且隨時保持低溫,終於打出如絲綢般的奶油。

所有照片都是隨便拍的,未來要補拍

未來計畫項目

巧克力(連結)

其他

夜市看到好吃甜點店(連結)

2020年12月21日 星期一

技術筆記:Micro CT 電腦斷層掃瞄系統


牙齒 Micro CT掃描成果

因工作需要,有機會於12月17日,在台達DELab 協助下(連結),利用其高端Micro CT電腦斷層掃瞄系統,掃描兩顆牙齒樣本。對工程師來說,接觸新科技總是讓人興奮不已,藉此機會紀錄CT相關概念及當天作業情形。

首先映入眼簾的是由貨櫃屋改建的行動實驗室,內有兩台最新型micro CT,桌上型μCT-100X,體積約一公尺見方箱型,以及立地形μCT-100,這台體積更大,為兩個圓筒套合在一起,造型與醫院CT神似,應該是為了後續更大型樣品預做準備。兩台掃描機體旁都另附有伺服器等級工作電腦以及台達開發的影像處理軟體進行影像處理。

靜態樣本掃描機,右測是24吋螢幕,可見得此機器之龐大
右方為活體掃描機,儼然有大型CT外型,左側為熱情的技術人員

專案經理曾敏原先生解釋,桌上型與立地形原理類似,桌上型μCT-100X是以拍攝四、五公分見方靜態物體為主;更大型的樣品或活體(如老鼠),則適合備有麻醉設備和幫浦以及更多影像處理系統的立地形μCT-100。以我們提供的牙齒樣本來說,體積不大且為靜態物體,適合以μCT-100X進行掃描。

CT最重要的兩個項目,一是X光源,另外則是顯影方式。以下面這個DIY專案為例(連結 連結),X光由右下方電壓轟擊靶材產生,電子束會以角度非常小的扇形射向圖中冷凍肉雞,依材質特性,電子束會被阻擋或穿透,穿透部分擊中後方螢光感測板(phosphor screen),轉換為可見光,最後由左下方普通相機拍得這些影像,再由軟體進行重建。


類似概念套用至μCT-100X,各個元件狀況如下,X光源在右方,經過圓形過濾鏡後,射向畫面中間牙齒樣本,畫面左側為螢光感測板,若樣本體積太大,可以調整物體位置。

別擔心,這片玻璃是含鉛玻璃,可阻擋X光。由圖中牙齒大小可看出整台機器之碩大。

因為光源類似扇形,所以只要調整樣本和感測器的位置,就能拍攝出不同放大倍率和解析度的影像。有經驗的技術人員會依照樣本體積不同,選擇合適位置,達到拍攝需求。

樣品下方支架為產品配件,保麗龍僅是配合牙齒臨時製作。

校正過程除了要計算物體距離,還要考量不同物體對X光的吸收和穿透程度,例如拍攝岩石和電路板和老鼠的設定自然不同,以往這些都要依靠技術人員經驗,現有軟體已經將其數位化,並且將各種物件的屬性以屬性方式存在系統中,方便使用者挑選,大大將低操作門檻。

畫面左方可看到數種預設物品可供挑選

開始進入拍攝階段,包含各種校正與處理時間,目前每張照片時間需七至十秒,結果如下。此為一個物件在同一平面的X光照片。

初步校正後,可看到2D影像

取得平面影像僅是第一步,若要產生立體模型,概念上只要固定光源和感測器模組,讓待測物進行360度自轉,過程中同時拍攝各個角度的影像,透過3D重建理論,無論是單純的填充和消去、傅立葉轉換,或是迭代法,就可將這些影像轉換為物體內部各座標點的密度訊息。

重建概念

即使我們對相關數學方程式不熟悉,憑直覺也能推論出,物體自轉角度越精細,重建的效果會越好。目前μCT-100X是使用高精密度馬達,以每隔0.5度拍攝一組影像的方式,組合720組影像成為微米等級資訊,全程約需2小時。比較特別的是,因為是臨時搭建的貨櫃屋,過程中為避免震動改變各個元件位置,還需時刻留意避免跑跳等較大動作。

重建的第一個動作是框選合適區域,前先選擇MASK區域,減少無謂空間浪費

為了確保重建的品質和速度,硬體方面,掃描機選用工業級主機(含92M超大記憶體和高級GPU顯卡),軟體方面,台達自行研發的軟體除了能完成立體重建,更能動態瀏覽包含表面、內部切片,以及打光模式下各種顯示功能。若要輸出檔案,也能選擇TIFF或DICOM(醫學影像專用格式,一顆牙齒的DICOM約為6G)。對一般使用者來說,即使沒有上述軟體,也有其他選項(連結),例如Mango。

牙齒樣本與掃描後成果比對

由不同角度和深度觀察立體物件

對從未使用過Micro CT使用者來說,這次體驗確實能讓人感受到微米等級影像的威力,不過數百萬的售價也的確讓人為之卻步,日後若還有掃描需求,會以委託服務為主,如中研院或成大小鼠中心。畢竟這類高端研究機構,才是台達的客群。

補充資訊:

一、Micro CT與傳統CT的差異,主要是解析度,傳統CT電子束直徑較大,會產生許多扇形進而造成彼此互相干擾,降低解低度,而Micro CT發出的電子束較為集中,所以解析度會相對應提升。(連結)

二、支援活體掃描的硬體機制,下圖是活體掃描機中軌道圖,設計上可放入下圖大型管,內置老鼠活體,全程有搭配的麻醉箱、麻醉注射器等等。與桌上型不同,活體掃描時,待測物不旋轉,而是光源和感測器旋轉,機構上,高端設備是採用電刷,台達目前是採用馬達帶動。



三、支援活體掃描的軟體機制,台達已開發出解決老鼠心跳產生的上下震盪,或是掃描較長樣本時,影像接合技術。


感謝台達公司提供機會

2020年12月15日 星期二

臨老入花叢 越野跑初體驗

茶茶山徑19KM越野跑由坪林市區出發,環繞籟狸尖山後,接上台九線,進入柑腳坑後再沿北勢溪回原點,沿途有泥土路、繩索徑、密林、高聳林木、河流等自然景色,更有檳榔園、茶園、石頭屋等人文景觀,可謂豐富且多變,是理想的越野路線。

茶茶山徑,沿線茶園

最後段落北勢溪畔

由於是第一次參加,報名蠻謹慎的選擇了19KM組。活動當天雖然天公作美,終止了連續一周的陰雨,但滿地黃土都已經變成軟泥,連行走都困難,更無法跑跳。全程幾乎都是上坡當步兵,下坡太滑不敢走,柏油路散步狀況下進行,與其說越野跑,不如說是在登山或玩泥巴。

全徑滿布稀泥

同行俊男美女,但請注意我們滿是泥漿的跑鞋

裝備上,相較於一般路跑環境都較單純,越野跑為了應付多變的地形,得準備抓地力較強的跑鞋。另外,為了儲備飲水、哨子、零食等,還添購了帥帥的越野背包。

為了避免滑鐵盧,除裝備外,行前曾安排數次自我訓練,地點是在熟悉的新竹飛鳳山。起初發現只要稍稍跑一下就很累很累,難以繼續,應該是山徑上地形變化大,姿勢不能維持,連帶的速度也快快慢慢不同,一般馬拉松強調的配速、姿勢、呼吸頻率等等完全不能使用,跳跑步的技巧也很陌生。累積兩三次後,的確有進步,但仍有非常大進步空間。

補給點不多,但有啤酒就OK

回想當初報名參加越野跑時,主要是想體會在山中飛馳的感受,這次活動雖然有趣,但明顯達不到預期效果。若想要有一定野跑經驗,並且維持身體韌性,正式活動或許得考慮明年4/18內湖五指山(連結),或是6/26棲蘭50k林道(連結 已報名,期盼能住明池,看見撞到月亮的樹,三姊妹神木),或不知還有沒有的貓空越野(連結)。平時則多至飛鳳山、五峰天際線、羅山林道等鍛鍊,希望有朝一日能透過野跑,讓自己有不同的山林經驗(連結 連結)。

2020年12月14日 星期一

閱讀筆記:使女的故事 The Handmaid's Tale

仕女的故事,是愛特伍(連結)早期1985年著作,若沒意外應該也會是她傳世之作。

故事內容。不久的未來,西方文明社會出現劇烈變動,為了要對抗其他國家的侵略及環境變遷帶來的巨大災難,社會權力逐漸集中,轉變為類似拜占庭式以宗教領導的國家,也就是書中所謂基列共和國,此其中,民主與自由思想被箝制,所有的規範只有一個,就是嚴格的教義。不符合教義的思想犯會受到極大的壓迫和打擊。而教義的定義和解釋是由少數人所管控,也就是書中的大主教們。類似威權統治的描述,以下面描述最為貼切。

自由有兩種,一種是隨心所欲,另一種是無憂無慮。Freedom to and freedom from. In the days of anarchy, it was freedom to. Now you are being given freedom from.

當然,愛特伍絕不是第一位描述威權統治的作家,類似概念早已普及,尤其考量當時是後冷戰時代,對蘇聯等國家的影射作品多如過江之鯽。使女的故事能在如此眾多作品中獲得廣泛的討論,主要原因是愛特伍能跳脫僵化的論述,大膽引入"使女"這個特殊概念。所謂使女是來自聖經的隱喻,屬於特殊的族群,在當時社會中唯一的功能是生育。政府頒布一種受精儀式,強迫使女們躺在女主人的大腿間,和男主人做愛,藉著懷孕生子的能力才能活下去,文中提到,女性只是一個長了二條腿的子宮罷了。

對於將女性視為物件的延伸,是個能夠隨時替換的零件這種荒謬的假設,基列共和國大眾卻都像空氣般視而不見,默許並且容忍著。而作者對使女族群的描述越深刻,越是舉重若輕時,越會讓讀者不由自主會想探究背後的原因,最後則意識到,原來是有著許多看不見的權力和壓迫,讓人們禁聲,並且對不公不義無動於衷。也就是說,愛特伍是藉由說故事的方式,讓讀者自己動手去揭開威權統治社會謊言的面紗,進而看到那已被嚴重扭曲的外部世界。

對使女這個族群描寫的成功,當然和愛特伍長期以來注重女權在社會壓迫下的苦悶、無法自由發展有絕大關係,算是愛特伍的標記。而除了鮮明的國家認同與女性地位主題外,全書冷冽且低沉的暗色調筆法,成功塑造出,基列共和國人民生活受到層層限制的窒息感,大量對女主角遭遇生活瑣事時忽現實與忽回憶、現今與過去時間與空間上的交叉穿梭,沉靜細膩構成的真實感,都讓人流連於書中故事而無法自拔。是本值得一讀再讀的好書。

2020年12月8日 星期二

閱讀筆記:美麗性世界 The Heart Goes Last

美麗性世界,原書名The Heart Goes Last,作者瑪格麗特‧愛特伍Margaret Atwood於2017年的作品,也是我涉獵她的第三部作品。全書沿襲她一貫寫作方式,描寫新時代中,人類技術文明發展到了極高的程度,帶來了生活質量提升,同時也帶來了巨大的社會問題,就在這社會動盪交界時刻,人們被迫被給予不同身分、不同工作、而作者就特別擅長描寫面對劇變時,主人翁對生活態度的轉變和思考歷程。

愛特伍往往不是直接就切入當下的衝突,而是透過大量的回憶、和對現象絲絲入扣的白描,隨著故事進展,直到最後,讀者自會得到一個無奈且冷冽的結論,那就是在外界精密的控制下、道德的淪喪是必然,人類最終淪為了自己文明的犧牲品,成為了自己創造出來工具的工具,喪失了人所有的自由和尊嚴。

這類帶著未來感的烏托邦式小說,對美國和加拿大這類承平已久社會總有莫大吸引力,而對東亞國家來說,近百年來經歷戰爭頻仍、威權統治、戒嚴和思想控制,早已視此為常態。以這本書設定的世界觀來說,當時的環境是外部沒有工作機會,產生許多問題,主角本身是好人,僅僅是需要到一個安全的地方有個穩定工作,就會覺得正常穩定的感受安心與滿足。當個人努力無法解決,而是結構性的沉淪下,極端主義就會出現,例如書中奇特的設計制度,監獄和暴力的管理,透過限制需求,創造出了更多工作機會,吸引需要工作的人進入,達成封閉區域中的穩定狀態。

這完全就是二次世界大戰前,德國社會的翻版,當時失業人口高達六百萬人,通貨膨脹嚴重,納粹主義的作法是嚴格實行分配制度,控制並且均化所有人的薪資,概念是減少每個工人的薪水,才能聘用更多的人,只要所有人都接受了薪資減少,全國的工作職缺立即就可以大增。然後由消費人口數據精準統計出國民消費力,進而決定民生必須品的價格,使每人都可以負擔,瞬間壓制通貨膨脹,控制物價還讓全民就業。故事中的村民也是同樣想法,為了維持理想中的生活模式,代價是生活都是被配給化,且每隔一個月被迫到監獄生活,就由降低欲望和減少私有化資產讓全體都有工作。而其中正子監獄的觀念,和北京折疊類似,完全是分配化的終極表現,由早期分配土地、薪資,進一步推廣到時間和慾望的重分配。

但是不是每個人都願意接受縮減薪水吧,必然有反抗的人,所以納粹宣佈工會和工人運動屬於非法,抱怨老闆或政府的文章和言論會被壓抑,不讓民眾反抗與抱怨,不能任意辭職,因為隨便改變職業,就會影響生產的計算,抗議的話就抓去關進集中營。須建立在專制和限制自由才能保證控制薪資與國民消費力,人民是得到了職業和食物的供應,不過也失去了自由。

美麗性世界故事中,村民都是意識到自由會被限制才簽約,所以對反抗部分著墨較少,與之相比,作者更強調,【制度可以怎麼完美地掌控一個人】。在嚴密的管理機制下,為了安全,人是會自我催眠,合理化威權和暴力,並且自我調整逐步放棄自身權利且默不關心他人死活。而這又更進一步助長了體制對於反抗者管制和壓迫,如此不斷循環成為無法跳脫的大漩渦,直到內部壓力到無法承受,若不是對外侵略吸收更多人,就是自爆。

或許你會覺得怎麼會有這麼愚蠢的事情呢?願意限制自己的自由?但它真的就是這樣發生了,甚至身在其中的人還甘之如飴,小說中的看似無害的女主角為了自身安全,逐漸泯滅自我人性而無所不做就是實例,現實世界中,也處處是事例。

今日COVID-19影響下,新的國際社會和文化秩序儼然變動,類似的預言小說,除了讓我們對即將到來的社會變遷更有警惕,更提醒我們,未來面對種種試煉時,除了安全之外,還有一種選擇,叫做"自由"。

PS 學英文資訊 連結 連結

2020年12月2日 星期三

Design and fabricate 3D objects for LaserCut

女兒帶回一隻型態高雅,動感十足的金色雷射切割拼圖,若連同家中原本已有的飛龍和龍鳳,我們家都快要有奇幻動物園了。坐看這幾隻設計精美的模型,除了佩服設計者巧思外,也尋思著,這類設計是如何進行,能否由程式自動代理呢?

搜尋後發現,FlatFit(連結)就能完成類似功能,相關論文,操作範例(連結 連結),雖然沒有安裝軟體,但由範例影片即能體會其設計概念,只能說操作概念很另類,要設計出類似鳳凰骨架和造型,應不容易。

若要探究更多自動代理設計,或許可以再區分成外殼、填滿、初步分割、複雜分割四類。外殼部分有幾種方式。

  1. 軟體設計:OpenSCAD(連結 連結)。
  2. 輔助軟體CutCAD: 已有要製作版型,需要處理交接處的結合和孔洞等(連結 連結),附程式碼(連結)。
  3. 輔助軟體KYUB: 已有要製作的外型概念,以四方形的小單元不斷延長融合組合成穩定的大型立體項目(連結 連結)。
  4. 全自動軟體Explision: 將複雜表現縮減到合理可識別狀況後,就能將每一個面自動產生出來,過程中還考慮了不同面之間接合角度和接孔(連結 連結)。理論上來說,因為利用mesh控制face數量這功能,產生的結果必定為三角形,對於動物等自然物很適合,若要處理建築等人工產品則會讓人感到困惑。

若不只是要外殼,還要滿滿的內容物,也有辦法。

  1. 編輯軟體AutoCAD: 將3D物件簡化成理想版型,範例如下(連結)。不需要程式背景。
  2. 全自動軟體Laser Slicer: 將物件塞滿,用切片概念一片片切出並存成檔案(連結 連結)。
  3. 類似的立體地圖(連結 連結)。

在外殼和滿滿內容物間的折衷方案是OpenFold(連結),概念是以兩個座標軸,如X和Y,X和Z,Y和Z進行固定間隔的掃描取出隔板,最後產生的結果,由兩個座標面看去是密實的隔板,第三座標面看去就是類似中空的結構。猛一看的確能看出是鳳凰,但細看就會覺得過於死板和不合理,例如脖子的部分,必須配合頸部逐漸旋轉切面,這部分或許可以加入sknw功能(連結),以中軸為主,進行切片。取得中軸的方式也能參考Predicting Animation Skeletons for 3D Articulated Models via Volumetric Nets。

第四項,最複雜,也與鳳凰最接近的切割方式,可以參考論文Slices: A Shape-proxy Based on Planar Sections(連結),有C和QT的程式碼,延伸資料(連結)。另外還有一篇crdbrd:Shape Fabrication by Sliding Planar Slices(連結),作法更簡潔但沒有參考程式。

Slices論文圖片

類似雷雕作品,國內以席時斌(連結)和黃心健(連結)鋼作品為代表。除這類高端藝術品外,近年來逐漸會發現以plywood等軟性材質製作的商品,其中有些簡單的在夜市便宜賣,但也有類似鳳凰 TENONART(連結)(連結) 等有精美修飾圖紋,並刷上金漆或黑漆等高雅質感,造型包括奇幻生物Chimera(連結)作品。

2020年12月1日 星期二

Computational Brick Design

身為工程師,對於只要能手動操作的各種行為,都相信會有自動化的可能。但遇上複雜且千變萬化又總被冠上創意的美名的積木玩具(尤其指LEGO),還能夠實現自動化夢想嗎?經過探訪,發現答案是肯定也是否定。肯定是因為程式的確能自動設計出2D和3D物件,但評估其成品和創意及精美還有很大一段距離。

基礎工具:圖形化各式積木零件

自動化的首要動作是對零件的了解,透過樂高公司釋出的資料庫,我們能掌握現有零件數量已達二萬種以上,而資料庫內容包括各零件的編號、3D描述語言、顏色等資訊。

如元件 "18654.dat",可參考此處連結取得3D資料。參考ldraw python專案(連結),可用三步驟將任一元件轉變成不同視角的圖片。畫出圖形連結 連結

conda activate ldraw
from ldraw.figure import *
from ldraw.library.colours import *
from ldraw.pieces import Piece
print Piece(Black, Vector(0, 72, 0), Identity(), "4716")
python 上述程式.py > temp.ldr
ldr2pov temp.ldr temp.pov 160.0,80.0,-240.0 0,0,0 (相機角度等參數)
povray +Itemp.pov +FN16 +Otemp.png +Q6

類似產生圖片範例還有(連結)。產生出的照片可以應用在網站(如rebrick)或是編輯軟體,自己則想到可以印出成海報或T恤。

上述專案還能一次組合多個元件,透過預先了解的大小和形狀資料,決定顏色和放置位置,形成複雜物件。python example/brother.py > temp.ldr  Person是個特定的位置區,一個個放進Piece後,包進Group,再旋轉移動Group。

基礎工具:自動生成安裝說明書

以ldraw為核心的editor,可幫助組裝積木(連結) (連結),或是當做呈現動態組裝過程的產生器(連結)。結構變成可以視覺化的順序圖 連結 連結 連結

模擬2D Mosaic

輸入平面圖案,經過轉換成以pixel為單位的拼裝指示(連結)(連結)。

模擬2D Layout

Mosaic是精確模擬,但現實的模擬往往是更複雜的,如何高效及穩固方式填滿指定形狀(空間)的數學問題,基本方式是採用圖學演算法如專案2D-LEGO-GA(連結)以基因演算法為核心,conda activate study project/legoga/  執行 python run.py --types_num 3 --max_brick 7

隨機產生不同形狀數量的積木BAG,再產生約近百個族群(不同排列方式),接著透過變異過程(包括置換,增加等操作手段),以填滿個二維長方平面覆蓋率為標進行運算。最後將數值轉換為圖片顯示。

之後可以繼續測試項目如下。 1.改變平面形狀,例如中空。 2.讓袋子內容變成無限制。 3.評估分數,由覆蓋率改為使用數量。 4.套用上述拼裝過程順序。

類似專案(連結)(連結)論文(連結)。而這是3D版本的連結 連結 。

除基本圖形演算法外,近來更加入人工智慧(連結),例如TilinGNN(連結),嘗試以幾個基本形狀填滿各種不同形狀。程式 conda activate tilin /project/TilinGNN,python Tiling-GUI.py 。概念是,先產生所有形狀組合,隨機產生形狀讓系統學習最適合排列方式。

1. Change to drawing mode by Key M
2. Draw the shape that you like
3. Transform by the shapes (Z/X, -/=, UP/DOWN/LEFT/RIGHT) or edit the shapes in Edit mode
4. Crop superset by Key E
5. Solve the problem by Key S (with number of trials)


模擬3D Shape

簡單說就是用積木逐漸填滿3D物體,填的越像越好,範例Automatic Generation of Constructable Brick Sculptures(連結 連結),有C語言版本(連結),以及Python簡化版本(連結)。

論文圖片

程式legobuild  python main.py,還在摸索中。資料格式為xxx.csv,有3D空間中每個點的位置和顏色。作法上是以Z為平面,由底開始,逐層挑選需要積木,並且在鋪設時考慮其上層結構與目前這層關係是否合理,若有需要則建構出輔助積木,並且考慮穩定性(另外一篇可考慮穩定性議題 連結),如圖片中身體部份就不只是單獨顆粒,而是交叉放置,最後完成全部物件。GAN程式(連結)。

其他參考資料如bricker,這似乎是Add-On程式(連結 連結),使用說明(連結 連結)。還有一類可手動操作軟體(連結)。

從擬真的角度來說,即使完成這個部分,也會因為使用的積木都是方形,使得造型過分簡單。雖然有素人童趣,但從專業角度來說,還是太粗糙,解決方式是加入更多不同零件,例如Automatic Generation of Vivid LEGO Architectural Sculptures( 連結 )就加入圓弧和三角等造型,並且用類神經網路來優化。但當元件項目達到數十上百種時,基本演算法或許就無法處理,得用CNN(或YOLO)等比對概念來選擇。可能的作法會是。決定要模擬的3D物件以及縮放的比例。將物件縮放到最終尺寸。用不同大小和位置,框選物件上的一個區域,再以CNN的方式選擇合適項目。

拼裝3D Technic Sketch

前述是外表的模擬,但要如何模擬sketch架構呢?Computational LEGO Technic Design(連結)影片(連結),即利用Technic元件完成這個目標。

論文圖片

首先牠假設已有一組已經事先定義好的零件資料表,並且輸入要完成的線條結構圖。填滿的過程先執行sketch coverage,過程中除考慮不同零件如何連結,更有最優化的機制。我很喜歡這幾個人的補充(連結)。例如This would be a great tool for prototyping and for non-AFOL makers who are trying to build simple models from their imagination. I can also see this being helpful for people who are new to Technic, have difficulty with spatial reasoning, or have physical disabilities that prevent them from building things by themselves. This could be a nice tool for educators, too.

而實際運作上,很好奇這系統如何處理斜線?以及互動過程中Guide Graph會動態調整嗎?檢查結構是否穩固則可參考(連結)。

千呼萬喚始出來,相關程式碼連結。介紹連結

自動轉化3D物件生成Sketch

上面專案的sketch是靠軟體手繪而成,難度太高。而現成資料庫中,幾乎都是只有外型,並沒有Sketch,順便列出物件資料庫資訊(連結 連結 連結)。

是否能直接由3D物件產生出Sketch呢?這方面的研究有兩類,第一類是尋找內部"骨架",而不是架構,例如Predicting Animation Skeletons for 3D Articulated Models via Volumetric Nets(連結),程式位置(連結)。概念可參考(連結)。

第二種是我較感興以簡化物體外型擷取出物件"架構"為主,如Learning Shape Abstractions by Assembling Volumetric Primitives(連結),訓練資料來自ShapeNet資料庫,取得物件第一階段造型,結果如下圖。程式 project/PyTorch/shape,待瞭解。值得一提是作者的人工智慧template可參考(連結)。

論文圖片

以此為基礎,北京清華後續研究加入多層次概念,Learning Adaptive Hierarchical Cuboid Abstractions of 3D Shape Collections(連結),技術上使用oct-tree,與前者相比,產生了第二層細節,視覺上更為完備,作者也認為可繼續加入更深層次。程式 conda activate shape  project/tensorflow_gpu/shape1 執行 python training_script.py --category airplane

論文圖片

未來應用,或許是先下載3D資料庫,由上述內容繪出架構,再由上節程式製作出以科技件為主的安裝說明書。系統則透過瀏覽或搜尋方式,讓使用者挑選項目後可自行拼裝。

其中搜尋部份,或許可採用素描搜尋(連結 連結),資料庫為普林斯頓3D資料庫,以類似手寫辨識方式,或機器學習方式(連結),找到最接近項目。參考範例(連結) (連結)。