Install OpenCV Library for Qt Creator (update for 64bit)

Qt 是一個好用且完整的 GUI (Graphical User Interface) 開發程式,本身也提供一個 IDE (Integrated Development Environment) 『Qt Creator』來開發 C++ 專案。這裡要說明如何在 Qt Creator 上建置 OpenCV 的開發環境,讓 Qt 與 OpenCV 結合在一起。雖然 Qt 提供 Visual Studio 的 plug-in,可直接在 VC 上寫 GUI,但透過 Qt Creator 來設計 GUI 會比較快速且美觀。

大致流程可分為,1. Qt 安裝和 OpenCV 安裝;2. 用 mingw compiler 編譯 OpenCV library;3. Qt 專案上的環境設置。

1.Qt 安裝和 OpenCV 安裝

http://www.qt.io/download/ 點入 Qt download 頁面,回答一些問題及輸入基本資料後,Qt 會依據你的作業系統推薦安裝版本,只要按下 Download Now,就會開始安裝了。

2016-03-23_140954

安裝完後就可以使用 Qt Creator 來開發 C++ 專案了,但目前還無法使用 OpenCV。

2016-03-23_141158

接著到 http://opencv.org/ 安裝 OpenCV,選擇所屬的作業系統來安裝,安裝完後在 opencv 資料夾裡面會有兩個子資料夾,分別是C:\opencv\build 和 C:\opencv\sources。

2.compile OpenCV library for mingw/g++ compiler

(1) 到 https://cmake.org/download/ 下載 Cmake,且安裝至 C:\。將系統變數 Path 加入下列 Qt\bin 與 Cmake\bin 兩個路徑。(電腦>>內容>>進階系統設定>>環境變數>> path)

C:\Qt\Tools\mingw492_32\bin

C:\cmake-3.5.0-win32-x86\bin

(2) 新增資料夾 C:\opencv-mingw,開啟 cmake-gui.exe 設定 source code :C:/opencv/sources 和 build the binaries : C:\opencv-mingw。2016-03-23_142654

按下 Configure,選擇 MinGW Makefiles 與 Specify native compilers。2016-03-23_142849

選擇編譯器,到剛安裝 Qt 的資料夾裡面,找已經安裝好的 compiler mingw/g++。

2016-03-23_143359

接著就可以按下 Generate。將 WITH_QT 給打勾。打勾之後,再 Configure 一次,然後 Generate,這樣就完成了初步安裝。2016-03-23_143719

(3) 編譯 OpenCV library。打開 cmd console 到 C:\opencv-mingw,輸入 :  mingw32make。建置需要一些時間...2016-03-23_144230

完成後再輸入 : mingw32make install 2016-03-23_144605現在你已經完成 OpenCV 的建置了,可以在 Qt Creator 上 使用 OpenCV library。

3.在 Qt Creator 上新增專案

新增一個 Qt Widget Application,

2016-03-23_145305

在 pro 裡面設定 includepath 和 libraries location :

INCLUDEPATH += C:\\opencv-mingw\\install\\include
LIBS += -LC:\\opencv-mingw\\install\\x86\\mingw\\lib \
-llibopencv_core2412.dll \
-llibopencv_highgui2412.dll \
-llibopencv_imgproc2412.dll

2016-03-23_145747

接著就可以在 Qt IDE 上面寫 OpenCV 的 code 了,以下是簡單的 OpenCV image read & show 的程式。

#include "mainwindow.h"
#include <QApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>

using namespace cv;

int main(int argc, char *argv[])
 {
 //QApplication a(argc, argv);
 //MainWindow w;
 //w.show();

//return a.exec();
 Mat3b in_img;
 in_img = imread("D://6_QT//lena_std.bmp",1);
 imshow("test", in_img);
 waitKey(0);

return 0;
 }

 

2016-03-23_150556

 

 

4. For Windows 64 bit 環境

在 64 bit 安裝與上述的步驟一樣,但有些要特別注意的地方。

第一,Qt Download 並沒有提供 64bit Source,所以到以下目錄去下載,

https://sourceforge.net/projects/qt64ng/files/qt/x86-64/5.4.1/mingw-4.9/sjlj/

並且安裝至 C:\Qt,除了安裝 64bit 外,還要至 Qt 官網下載 32bit 版本,在官網點選 install online 後,選擇一個版本(這裡以 5.6版為例) 和 Tools (Qtcreator & mingw492_32),一樣安裝至 C:\Qt 資料夾內。而 OpenCV 版本的話,我下載最新版本( OpenCV3.2.0, 2017/05)。

第二,資料都安裝妥當後,接下來設定電腦環境變數,除了在 32bit 所提到的

C:\Qt\Tools\mingw492_32\bin

C:\cmake-3.5.0-win32-x86\bin

還要加入以下兩個路徑,

C:\Qt\qt-5.4.1-x64-mingw492r1-sjlj-opengl-rev1\mingw64\bin (64bit 版本)

C:\Qt\Tools\mingw492_32\i686-w64-mingw32\bin

接下來重新開機後,就可以開始上述 2. CMake 的步驟了。

第三,mingw32-make install 完畢之後,將

C:\opencv-mingw\install\x86\mingw\bin

也加入系統環境變數裡。且在 pro 裡面設定 includepath 和 libraries location 時,

LIBS 多加入 -llibopencv_imgcodecs320.dll (因為 imread 在 OpenCV3 之後被定義到 imgcodecs 裡面)。

完成以上的步驟後,一樣可以在 64bit 環境下,用 QtCreator 寫 OpenCV 。


 

reference : 

http://www.laganiere.name/opencvCookbook/chap1s1_2.shtml

https://zahidhasan.wordpress.com/2014/08/19/qt-5-3-1-64-bit-mingw-windows/

reference for 64 bit :

https://wiki.qt.io/How_to_setup_Qt_and_openCV_on_Windows

http://stackoverflow.com/questions/34497099/opencv-undefined-reference-to-imread

Changing the icon of an exe in VC2008 & Qt Creator (執行檔圖示的更改)

在程式設計完成後,執行檔(.exe) 圖示永遠都長得一樣,只是替換不同名稱而已。程式越寫越多就想要更改 .exe 的 icon 來區別不同的執行檔。

更換執行檔的圖示基本上有兩個步驟,(1) 產出想要的 .ico 圖檔(2) 在 compile 之前完成 icon 的設定

(1) 產出 .ico 圖檔

基本上我們常見的 icon 都是簡單明瞭的二維圖像,這裡推薦兩個 icon 圖集,可以從這裡面下載 .png 來做修改,或直接下載 .ico 檔。(個人比較推薦 IconArchive,這裡面的 icon 內容比較生動活潑。)

Iconfinder :: https://www.iconfinder.com/

IconArchive :: http://www.iconarchive.com/

或者如果本身有設計好的圖檔,可以透過 http://convertico.com/ 將圖檔轉成 .ico 檔。

上圖說明就是將黑蝙蝠圖檔,改成藍色蝙蝠,再轉成 .ico 檔。

 

(2) 在 compile 前完成 icon 設定

<1> in VC2008

在 project 工作列表上 >> 檢視(V) >> 資源檢視(R);

在 project 名稱上按下右鍵  >> 加入 >> 資源(R);

點選 icon。此時你已經新增 icon1.ico 到你的 project 資料夾裡面了。

接著就把我剛剛的 bat-icon-blue.ico 檔案改成 icon1.ico ,並且複製到 project 資料夾裡覆蓋掉原本的 icon1.ico 就OK了,然後再重新 compile 後,就可以看到 .exe 執行檔的 icon 被改成蝙蝠的圖示了。

<2> in Qt Creator

在 project 上按右鍵 >> 新增檔案... >> General >> Empty File >> 輸入 test.rc 檔名;

接著會在其他檔案內看到新增的檔案,接著在 test.rc 裡面編輯:

IDI_ICON1 ICON DISCARDABLE "bat-icon-blue.ico"

接著回到 .pro 檔,在

DISTFILES += \

test.rc   下加入

RC_FILE += \

test.rc

 

然後再重新 compile 後,就可以看到 qtest.exe 執行檔的 icon 也順利被更換了。

 

Photoshop CS6 掛載 CameraRAW ( 開啟 D750 NEF檔)

最近突然又對拍照重拾興趣,想衝各大攝影聖地紀錄影像,當然對影像品質也是越來越吹毛求疵。以前拍照頂多在機身上修改 RAW 檔 ─ 調調曝光補償和白平衡,之後再直接機身轉 JPG 檔輸出。但由於最近剛好在做 decode 後的 Noise Reduction,發現有損壓縮對於影像細節真的有很大的影響,Mosquito Noise & Blocking Effect 尤其嚴重,所以最近想開始在 RAW 檔上作業,而非壓成 JPG 後才開始後製。所以以下介紹如何在 Photoshop 上開啟 Nikon or Canon 的 RAW 檔。 

https://helpx.adobe.com/tw/camera-raw/kb/camera-raw-plug-in-installer.html

下載Camera Raw 9.7 且安裝。基本上,版本越新,支援的機身越多。

安裝完後,至安裝資料夾內找出 Camera Raw.8bi ,若未更改安裝路徑的話會在C:\Program Files\Common Files\Adobe\Plug-Ins\CS6 資料夾裡面,

%e6%9c%aa%e5%91%bd%e5%90%8d

再至你電腦裡的 PhotoshopCS6\Plug-ins\File Formats 路徑下,將裡面的 Camera Raw.8bi 替換成剛安裝好的 Camera Raw.8bi,替換後就可以打開 Photoshop CS6,開啟你想要的 raw 檔了。若你沒有做替換動作的話,在 Photoshop 裡 說明>>關於增效模組>>Camera Raw 會有兩個... 是不能正常開啟 raw 檔,所以當你開啟 Photoshop 時,注意一下說明裡的 Camera Raw 是否只有一個。%e6%9c%aa%e5%91%bd%e5%90%8d

接著只要將你的 raw 檔拖曳到 Photoshop 裡面就可以了~~~

PS. win8 無法拖曳開啟檔案的話,

(1) 打開『執行』輸入『regedit』。

(2) 找到資料夾 : HKEY_LOCAL_MACHINE > SOFTWARE > Microsoft > Windows > CurrentVersion > Policies > System

(3) 找到『EnableLUA』,點右鍵選擇修改,將1改成0,然後再重新開機就 OK 了。

拖曳至 Photoshop,Photoshop 會自動開啟新的視窗,如下

%e6%9c%aa%e5%91%bd%e5%90%8d

而現在就可以開始後製你的 RAW 檔影像了~

自製陸龜箱-東非豹龜

在確定要養陸龜後,就決定要親手做一個木製爬蟲箱。我所有原料都是在特力屋購買的,所以成本並沒有比直接去爬蟲店買個爬蟲箱來的便宜許多,但可以照自己的喜好去設計龜箱,也算是一種體驗。由於之前也沒有木工的經驗,所以沒有特別厲害的工藝品,純粹就是一個簡單的陸龜的窩。

img_4820

木板主要是用特力屋的松木拼板(傳送門),有不同的尺寸,可以按照自己的需求去購買,而且也可以當場請員工幫你做切割(但不接受切割 30cm 以下的木板),而我當初是想做一個 100cm x 50cm x 40cm 的長方體木箱,所以木板買一買就快兩千五了,如果要省錢的話,可以去木材行買或是用常見的貨櫃木箱來做,想必能夠省下不少經費,但我懶惰,直接買現成的比較快。然後也買了鐵鎚、鐵釘、鋸子和砂紙...等工具。

licn9101

釘木板的聲音還滿大聲的,所以到附近的公園釘,不然在家裡釘木板,鄰居應該會受不了吧(事實上聲音大到我自己都受不了...)。把最大的木板鋪底,其他三面牆都訂死,留一面牆做可開關的門。

 img_4829 img_4828

在第四面上方釘上兩條高低不一的木條,木條中間留個木板的寬度,作為閘門的固定柱。

img_4830 img_4831

在木條較高的那側底部再釘個木塊,作為門擋,這樣木板才能穩固。右圖為木板門放下去的樣子。

img_4832

整體釘箱過程到此結束,上圖就是整個龜箱的外觀。由於我養的豹龜目前只有十來公分,底板100x50cm 空間還算夠,所以門外有預留一些空間,用來放置雜物。

img_4836 img_4837

釘箱完後,接下來就是將爬箱上油,這罐護木油也是在特力屋購買的,一罐四百多,可自行上特力屋官網查詢。上油的目的是為了讓木材纖維富含油脂,降低木材老化,表面龜裂,防水防霉。我上油的方式就是利用海綿沾油,塗抹在木板上,建議上個三次以上,每次間隔一個小時左右,這樣護木油才能完全被木材吸收。

img_4838上圖可以看到有上油與沒上油的差異(左邊沒上油,右邊有上油)。上完油後,將爬箱放置通風處三到五天,讓油的味道散去。至於護木油對陸龜的影響,這我當初也有想過,但護木油本身標榜是天然無毒,所以我認為對陸龜的影響應該是不大,目前飼養一個多月了,也不見我的豹龜有任何不適的情況發生。

img_48412

img_4855

目前我的豹龜算是滿適應我做的龜箱,是個愛挑食的吃貨,固定早上泡水排尿,兩至三天排便,也會到固定的地方睡覺。我的龜箱環境通風也好整理,但winter is coming,如何維持溫度與濕度是接下來要面對的難題。

 

Deinterlacing Overview

接觸 deinterlacing 也有半年之久,最近有空閒來寫一下關於 deinterlacing 的概念與精神。(其實 wiki 上面已經描述得很詳細了...但只是想用自己的經驗與觀點來介紹 deinterlacing 。)

deinterlacing,中文叫做去交錯。deinterlacing 基本概念就是將隔行掃描( interlace )的影像訊號轉換成逐行掃描( progressive ) 訊號的一種方法。在早期因為傳輸頻寬不足的情況下,使用隔行掃描能夠在相同的 frame rate 節省一半的資料量,像是北美的 NTSC 制式的電視訊號就是隔行掃描,每秒60張;歐盟的 PAL 的電視訊號是隔行掃描,每秒50張。而 CRT 電視即利用視覺暫留影響,使得 interlace video 在 CRT 顯示器上能夠正常的顯示;但現今的液晶顯示螢幕已經有夠快的速度,能即時處理逐行掃描,所以在播放 interlace video 前必須先將 video 轉換成 progressive video,影像才不會有閃爍的現象發生。然而我們常見的視頻格式縮寫 720p、480i、576i ... 前面的數字表示影片垂直解析度,後面的英文字 p 表示逐行掃描,i 表示隔行掃描。

interlace&progressive[ 隔行掃描 vs 逐行掃描]

Deinterlacing Algorithm

deinterlacing 方法基本上可粗略分為 intra-field deinterlacinginter-field deinterlacingmotion adaptive deinterlacingmotion compensated deinterlacing 這四種方法。field 的解釋如下圖,當一張影像在隔行掃描時,只會有奇數行資訊或偶數行資訊,這一半的資訊量我們稱作場 (field),消失的另一半(灰色區域)就是靠 deinterlacing 方法內插出來的。

interlace&progressive2

intra-field deinterlacing 方法是最省硬體資源的方式,就從單一 field 裡面的資料訊息做內插,可用 line repetition、linear interpolation,或其他內插演算法來實現,但這種做法得到的畫面品質較差,畫面中有細橫線時,容易有閃爍的現象發生。

inter-field deinterlacing 方法,則是參考前後不同 fields 的訊息來做內插(需要有 DRAM 來存 frame buffer),這方法在靜態區域會有很好的影像品質,但當畫面移動或有移動物體存在時,會有鋸齒或橫紋的現象發生( feathering effect, combing effect, zipper ... paper 上常見到的說法)。

interlace&progressive3[右邊為 inter-field deinterlacing 的結果。]

motion adaptive deinterlacing 則是綜合 intra-field 與 inter-field 的優點來實現的演算法,利用 field 之間的像素差來判斷動態區域與靜態區域,動態區域用 intra-field deinterlacing,靜態區域使用 inter-field deinterlacing。此方式是目前 deinterlacing 最為廣泛的做法,因為在硬體資源可接受範圍下能做到不錯的效果。因為使用廣泛,所以演算法要一較高下,除了在 motion detection 要做得好之外,intra-field deinterlacing 也是一大重點。

motion compensated deinterlacing 利用動態補償方式來做,需要大量運算每個 block 的 motion vector 來估測每個像素的移動向量,此作法會有非常好的影像品質,但所需要硬體資源非常可觀。就我所知,除了在 encoder 或 frame rate transfer 上會用 MEMC (motion estimation and motion compensation) 外,其他 image processing 不會這麼下重本。

Future Work

除了上述基本的 deinterlacing 方法外,在實際應用上還會遇到許許多多的問題,像是 interlaced video 被標示為 progressive video,或 video 是 32 pulldown 的情況,又或者畫面中有固定速度移動的物體(如新聞跑馬燈)...在這些雜七雜八的問題出現下,如何設計演算法讓畫面能有最好的品質呈現,這就是 deinterlacing algorithm 能夠繼續發展的原因,但在 .265 HEVC encoder 不再支援 interlacing video 的情況下,deinterlacing 也將會漸漸式微。

 


reference :

http://www.vlsi.uwindsor.ca/presentations/elham_seminar1.pdf

https://zh.wikipedia.org/wiki/%E5%8E%BB%E4%BA%A4%E9%8C%AF

 

C/C++ Q&A

1. typedef 與 #define 差異?

typedef 是用來定義一個新的資料型態名稱,而 #define 是定義巨集,但編譯器只是用來取代。

ex.

typedef char char_1; // 定義一個新的資料型態名稱,從此多了一個型態。

#define char_2 char; //定義了一個 char 型態,往後遇到 char_2 型態的變數都認為是 char。

2. *& reference to pointer 用意

#include <iostream>
char *str1 = "Hello";
char *str2 = "World";
char *ptr = str1;
char *&rptr = str1;
rptr = str2;
std::cout << ptr << str1 << std::endl;

上面程式會輸出 "Hello World",因為 rptr 是一個 char 指標的『參考』(rptr 是 str1 的參考)。

Sphere Mapping in OpenGL (L12)

2016-03-10_135900

Sphere Environment Mapping 是個可以創造出反射環境的金屬幾何體或者是反射屏幕內容到二次曲面上。雖然本篇介紹的方法不是真正的將屏幕裡的內容,確切的反射到幾何體正確位置上面,但 Sphere Mapping 是個快速製造出反射圖形的一種方法。

在了解本篇內容前,請先參考 Quadrics in OpenGL (L9) ,裡面介紹了 Quadric 的繪製方法。至於本篇主旨雖然是說球形映射,但其實也可以用在任何二次曲面上或方體上面。首先,要創造出如金屬般的反射效果,要先從 Photoshop 製造出一個球形曲面,即是利用 Photoshop 裡面的濾鏡 >> 扭曲 >> 魚眼效果,得到一張球形曲面影像,取代用魚眼鏡頭拍攝。(PS. 在 OpenGL 裡面的 texture image size 盡量都改成 2 的冪次方,這樣 rendering 效果會比較好。)

castle

castle_fisheye

[ 背景影像;球形扭曲影像。]

所以首先將上面兩張圖 load 到 texture[6] 陣列裡面,而每張影像有三種不同的 texture filter,code 如下。

void myopenGL::loadGLTexture()
{
	//@ texture 1
	string in_file = "D:\\4_OpenGL\\castle_fisheye.bmp";
	QImage img[2], GL_img[2];
	if(!img[0].load(in_file.c_str()))
	{
		qWarning("Could not read the image file.");
		QImage dummy(512, 512, QImage::Format_RGB32);
		dummy.fill(Qt::green);
		img[0] = dummy;
	}
	GL_img[0] = QGLWidget::convertToGLFormat( img[0] ); // convert QImage to GLformat
	//@ texture 2
	string in_file2 = "D:\\4_OpenGL\\castle.bmp";
	if(!img[1].load(in_file2.c_str()))
	{
		qWarning("Could not read the image file.");
		QImage dummy(512, 512, QImage::Format_RGB32);
		dummy.fill(Qt::green);
		img[1] = dummy;
	}
	GL_img[1] = QGLWidget::convertToGLFormat( img[1] ); // convert QImage to GLformat

	glGenTextures(6, &amp;amp;amp;amp;amp;amp;texture[0]);	// create three texture for two images

	for(int loop = 0; loop &amp;amp;amp;amp;amp;lt; 2; loop++)
	{
		//@ nearesr filtered texture
		glBindTexture(GL_TEXTURE_2D, texture[loop]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, GL_img[loop].width(), GL_img[loop].height(), 0,
					GL_RGBA, GL_UNSIGNED_BYTE, GL_img[loop].bits());
		//@ linear filtered texture
		glBindTexture(GL_TEXTURE_2D, texture[loop+2]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, GL_img[loop].width(), GL_img[loop].height(), 0,
					GL_RGBA, GL_UNSIGNED_BYTE, GL_img[loop].bits());
		//@ MipMapped texture
		glBindTexture(GL_TEXTURE_2D, texture[loop+4]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, GL_img[loop].width(), GL_img[loop].height(),
						GL_RGBA, GL_UNSIGNED_BYTE, GL_img[loop].bits());
	}

}

接著,這裡是本篇 sphere mapping 的重點,我們透過 glTexGeni 來產生紋理,而紋理座標(S, T, R, Q)相應著物體座標(x, y, z, w),所以如果今天用的是一維紋理( 1D ) 則只需要定義 S 座標,而 2D texture 則是定義 S 和 T 座標。

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP) 透過 glTexGeni 來定義 S 軸(水平軸) 的紋理特性。

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP) 則是定義 T 軸(垂直軸)的紋理特性。

在 glTexGeni 裡第三個參數是用來決定紋理的行為模式,除了 GL_SPHERE_MAP 外,還有 GL_OBJECT_LINEARGL_EYE_LINEARGL_SPHERE_MAPGL_REFLECTION_MAPGL_NORMAL_MAP

GL_OBJECT_LINEAR : 物體模式,紋理會隨著物體轉動而轉動。

GL_EYE_LINEAR : 視覺模式,紋理不會隨著物體轉動,始終保持原樣。

GL_SPHERE_MAP : 環境紋理(球體貼圖),具有反射效果。

GL_REFLECTION_MAP : 環境紋理(反射紋理),也具有反射效果。

GL_NORMAL_MAP : 用於立方體貼圖。

所以要在 initializeGL() 裡面定義紋理的行為模式。

	//@ sphere mapping
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);

最後,在 painGL() 裡面將 GL_TEXTURE_GEN_SGL_TEXTURE_GEN_T 啟動後,即可看到 sphere mapping 的效果了,painGL() 裡面我透過 quadratic_object 來變化不同的二次曲面,這部分在 lesson 9 有詳細的說明了,這裡就不再敘述。後面就是把背景圖也給畫出來而已。

void myopenGL::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();		
	glTranslatef(0.0f, 0.0f, -10.0f);	
	//@ sphere mapping
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	glBindTexture(GL_TEXTURE_2D, texture[4]);
	glPushMatrix();
	glRotatef(rota_x, 1.0f, 0.0f, 0.0f);
	glRotatef(rota_y, 0.0f, 1.0f, 0.0f);
	glRotatef(rota_z, 0.0f, 0.0f, 1.0f);

	if(quadratic_object &amp;amp;gt; 3)
		quadratic_object = 0;

	switch(quadratic_object)
	{
	case 0:
		drawCube();
		break;
	case 1:
		glTranslatef(0.0f, 0.0f, -1.5f);
		gluCylinder(quadratic, 1.0f, 1.0f, 3.0f, 32, 32);
		break;
	case 2:
		gluSphere(quadratic, 1.3f, 32, 32);
		break;
	case 3:
		glTranslatef(0.0f, 0.0f, -1.5f);
		gluCylinder(quadratic, 1.0f, 0.0f, 3.0f, 32, 32);
		break;
	}
	glPopMatrix();
	glDisable(GL_TEXTURE_GEN_S);
	glDisable(GL_TEXTURE_GEN_T);
	//@ print the background
	glBindTexture(GL_TEXTURE_2D, texture[5]);
	glPushMatrix();
	glTranslatef(0.0f, 0.0f, -24.0f);
	glBegin(GL_QUADS);
	glNormal3f(0.0f, 0.0f, 1.0f);
	glTexCoord2f(0.0f, 0.0f); glVertex3f(-13.3f, -10.0f, 10.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f( 13.3f, -10.0f, 10.0f);
	glTexCoord2f(1.0f, 1.0f); glVertex3f( 13.3f,  10.0f, 10.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex3f(-13.3f,  10.0f, 10.0f);
	glEnd();

	glPopMatrix();
}

 

執行結果:

2016-03-10_135153[球型反射曲面。]

2016-03-10_135249[錐形反射曲面。]

 

 


reference : 

http://nehe.gamedev.net/tutorial/sphere_mapping_quadrics_in_opengl/15005/

http://tiankefeng0520.iteye.com/blog/2007939

 

了解Gamma Correction

Gamma 在數位影像系統裡面是個重要的議題,但卻很少提到。Gamma 定義了像素的數值與真實的亮度值之間的關係。如果沒有 gamma 存在,我們將無法感知畫面較暗的訊息,而相關的 gamma 非線性運算可稱為 Gamma CorrectionGamma Encoding 或是 Gamma Compression

● Gamma 存在到底有甚麼用呢?

1.我們人眼對光的敏感度是非線性的,但相機卻是線性的。

數位相機上的感光元件,感測到的光亮度是線性關係( 以8 bits depth 為例,表示像素128是255的一半亮度);但人類的眼睛感知上卻不是如此簡單,當我們需要感知255一半的亮度時,卻只要像素約50就夠了,所以人眼對於光的感知能力是非線性的。2016-02-24_171725< 相機擷取到50%強度的亮度。>

2016-02-24_171744

<人眼感測到50%強度的亮度。>

所以跟相機相比,我們人眼對於暗部的感知能力比亮部還要來的敏銳。那跟本篇要說的 Gamma 有甚麼關係呢?因為數位相機的『線性關係』與人類眼睛的『非線性關係』溝不上邊,因此 Gamma 是將數位相機的線性關係轉換成非線性關係,這個步驟就叫做 Gamma Correction 或是 Gamma Encoded。

2. Gamma encoded 在儲存的過程中被實現。

在任何數位圖檔( ex JPEG,除了 RAW檔案外;video files 也是一樣,ex MPEG )儲存的 binary data 都會明確的經過 Gamma encoded,而不是線性的像素值,Gamma encoded 使影像畫素重新分布為我們人眼較能感知的分布,以下圖 5bit depth 為例,經由 Gamma Encoded 後,灰階分布較為一致。

2016-02-24_173344

< 線性 Encoded 與 Gamma Encoded 比較>

● Gamma 工作流程

Gamma 的非線性關係除了與人眼感知有關係之外,還跟 monitor 特性有關。早期 CRT (Cathode ray tube) 螢幕由於輸出電流與輸入的電壓不成線性關係(以8bit depth為例,如果要輸出白色(255)的一半亮度,像素值要為178左右,而非128),所以影像在儲存時要做 Gamma Correction,然後在 display 端才能正確地顯示數值。

I\propto V_{s}^{\gamma }

\gamma 影響亮度與電壓之間的關係,在 CRT 時代 \gamma 範圍在 2.35~2.55 之間;但現在 LCD 螢幕或電視所校正的 \gamma 範圍在 1.8~2.2 之間。Windows 的電腦 image encoding gamma 是 1/2.2,而 decoding gamma 是 2.2;反之 Apple Mac 裡預設的 encoding gamma 是 1/1.8,而 decoding gamma 是 1.8。但是現在的螢幕可調性很高,gamma value 是可以自行校正的。

2016-02-24_180000

上圖說明了原本是線性的 RAW image 經過了 Image File GammaDisplay Gamma 後,所得到的 System Gamma 會還原成線性分布。

1.Image File Gamma

2016-02-24_181027

上圖左邊是 RAW 影像,他的 image gamma 是 1.0,左邊的 encoding gamma 為 1/2.2,在大部分的影像檔案裡所用的 encoding gamma 都為 1/2.2 (只要是使用 sRGB 和 Adobe RGB color space)。

2.Display Gamma

display gamma 是可以掌控的,我們可以藉由 monitor calibration 去校正我們想要的對比程度。下圖可以看到透過不同 display gamma 值的調整,可以得到不一樣的影像結果。

2016-02-24_182616

CRT Monitors 由於自己電壓電流不成正比的特性,有著像 gamma 2.5 的 Display Gamma,幾乎是我們人眼感測能力的反轉換,所以只要透過製造商做些微的調整就可以達到 Display Gamma 2.2 的結果了。

LCD Monitors 本身液晶明亮度與輸入像素大小成正比,所以需要經過特殊的 gamma look-up table 去做校正,來逼近 Display Gamma 2.2 的效果。

 

 


reference :

http://www.cambridgeincolour.com/tutorials/gamma-correction.htm

https://en.wikipedia.org/wiki/Gamma_correction

 

在 Visual Studio 2008 下 Compile C Program

最近由於要執行別人的 C model,才發現 Visual Studio 2008 支持的 C 語言規範只到 C89 (是最早的 C 語言規範,在90年由美國國家表準協會(ANSI)推出 ANSI 版本,所以也稱做 C90)。然而 C89 coding 方式繁瑣且不直觀,所有的變數宣告都要在函式執行之前,簡單來說就是所有變數都要宣告在頂端就對了。

所以要讓 C model 可以執行,有以下的解決方法,

  1. 最直覺也最簡單的方式,將 C code 全部轉成 .cpp 的格式,利用 VC 裡面的 C++ compiler 來執行。(但這個方法會存在些差異)
  2. IDE 用 VC 或 eclipse,然後 compiler 用 MinGW (MinGW 支援 C99)。
  3. 升級到VC2013,VC2013 裡的 C++ compiler 支援 C99 的變數宣告方式。

 


 

reference :

http://stackoverflow.com/questions/13308944/how-to-simulate-c99-in-visual-studio-for-variables-declaration

http://jashliao.pixnet.net/blog/post/167143629

自製魚菜共生系統( Aquaponic System)

魚菜共生系統這篇裡面有提到如何利用氮循環來達到『養魚不換水,種菜不施肥』的共生環境。早在去年我和我爸就成功的完成這項系統(只是拖到現在才寫... 有點給他太懶惰了...)。那基本上就如上面影片所示,最上層就『植栽床』,裡面放滿了礫石或發泡煉石,為消化菌的培養床,用來分解魚的排泄物(氨,阿摩尼亞),轉化成植物的肥料。IMG_2646

在植栽床裡面就利用寶特瓶製造出水壓差,利用虹吸管將含有硝酸鹽養分的水給排放到水栽槽去。

IMG_2639 IMG_2640

最下層就是養殖槽,裡面可以養魚養蝦養烏龜,裡面放置一個小型抽水馬達,將含有動物排泄物的水上抽至植栽床裡面,給消化菌做分解,之後回流回養殖槽的水就是被植物過濾過的乾淨水源了。所以整體而言,只要定時餵魚吃飼料,就可以不費吹灰之力得到新鮮的蔬菜與肥美的魚肉。

IMG_2642

 


在完成魚菜共生系統後,我和我爸也試種試養了好幾個禮拜,發現有兩個大問題,第一就是水會慢慢地減少,由於我們種植的地方是戶外,所以在整個系統裡面的水容易蒸發掉,所以水會漸漸減少;第二,寶特瓶做的虹吸系統,時間久了會失效 (虹吸原理是利用瓶內與瓶外的壓力差,將植栽槽的水抽排至下層水栽槽) 但時間久了寶特瓶瓶內與瓶外的壓力差變小,以致無法有效地將植栽槽裡的水抽乾,所以無法有效地將含有養分的水排至水栽槽給水耕植物做吸收。後來由於外務繁忙,就沒有再針對這個系統作改良,所以後來就不了了之了...但製作這個系統也是一種經驗,透過實作對於魚菜共生系統有更一步的了解。

 


水耕蔬菜真的好嗎?近年來水耕栽植日漸盛行,一堆科技業者紛紛投入水耕栽植的設備開發,主打著水耕植物無農藥與重金屬殘留,且植物葉大肥美,不須洗滌,可直接生吃。水耕植物在植物工廠內,吸收人類調配出來的黃金比例培養液,在合適的溫濕度下成長,每日的光合作用時間,由LED決定,在這種重重把關的環境下生長,的確能長得又快又漂亮,但一離開栽植環境,水耕植物沒幾個小時就垂頭喪氣,容易枯萎,猶如溫室裡的花朵,落不經風,經不起考驗。反觀土耕植物,土壤裡有微生物幫忙分解肥料,以利植物吸收,在外風吹日曬,在比較艱困環境下成長的植物較為茁壯且具生命力,在室溫下,土耕植物比水耕植物更不容易枯萎,且研究顯示土耕植物裡的礦物質含量與種類都比水耕植物來的多,但受到人類的農藥與化學肥料的毒害下,使土耕植物內的農藥殘留與重金屬含量都比水耕植物來的高。因此,水耕好還是土耕好?其實各有優缺。近年來台灣一直推廣有機種植,堅持使用有機肥料,無農藥,若所有植物蔬菜能在這樣的環境土壤下生活,那才是最好的來源。

水耕植物有它存在的利基點,基本上不受天災影響,能夠穩定市場供需,且在工廠內生長,在單位面積的生產量來說,遠比土耕植物來的多許多,有利於解決未來人類人口暴增所面臨到的糧食危機。但業者不斷的大肆宣揚水耕植物的好及鼓勵民眾在自家大量種植,不外乎就是要大賺水耕器材與設備的錢,這種短視近利的作法並無法永續,應該多多提倡有機種植,多愛護我們的地球與土壤,讓植物蔬果生長在健康的土壤上,因為蔬果本是給人下肚的食物,不應該都是由工廠生產出來的產品,但現實與理想永遠都背道而馳,地球上不受汙染的土地只會越來越少...