2010年6月13日 星期日
課程回顧
會選這堂課的主要原因是因為我之前沒有修過有關視訊的課程,所以想要嘗試看看,一開始主要是熟悉語法,CALL function感覺還滿容易的,後來到了要一個個pixel去改值的時候稍為難了一點,為了理解一個個pixel去存取花了一些時間,懂了之後就可以藉由存取pixel做到顏色辨識,利用顏色辨識就可以做到虛擬滑鼠的效果,後來又學了把不會動的背景和會動的人物相減,可以得到會動的物體,藉由取得物體的中心點就又可以做到虛擬滑鼠的效果,不需要顏色,只要會動的物體就可以做到虛擬滑鼠的效果,不像之前一樣就是一個dos視窗顯示出來顯示結果這樣,如果做錯了有了意外的效果,執行之後也覺的很好笑,上完這堂課讓我覺得自己做出來的東西能和自己互動真的滿好玩的。
2010年6月12日 星期六
HW09: X-Projection and Y-Projection
2010年5月2日 星期日
期中專題-貓抓老鼠


製作學生:495511466 郭宸雨 495511210 李俞萱
專題動機與介紹:
一開始我們想到是釣魚遊戲,利用亂數產生的魚去撈,但是我們在設計的時候發現魚只能在固定位置亂數產生,這樣跟一般的撈魚遊戲有點不合邏輯,所以才改成亂 數時間產生老鼠,然後去抓老鼠,只要有抓到老鼠就可以加分的遊戲。
使用的技術:
opencv的視訊處理功能,主要是用顏色偵測(color detection)以及虛擬滑鼠(virtual mouse)去判斷指標位置,進而去抓到老鼠
實作介紹:
利用亂數產生的圖片,當圖片被亂數產生時,就有個布林值去判斷圖片被產生了,布林值的主要目的是要當滑鼠跟圖片發生collision時,就表示抓到了老 鼠,就可以計算分數,而且可以產生抓到老鼠的音效
遭遇的困難:
圖片消失太快,導致抓不到老鼠。
一開始在跑程式的時候,是 設定老鼠出現消失,就是一個布林值而已,所以當老鼠出現後,下frame就會馬上消失,會讓看到老鼠,正要去抓的時候,老鼠就不見了,所以我們是用一個陣 列去存老鼠的狀態,當老鼠出現後,讓他增加停留的時間,延長老鼠停留的時間,這樣一來不用去改waitkey的值,也可以讓老鼠出現後比較慢的消失。
而另一個問題是貼圖的問題,一開始把logo貼上去的時候,發現有灰色的框框
,就是他不能有空白底,在這邊一開始以為是圖片格式的關係,換了好多個格式後發現無法解決,但後面仔細看了一下貼上logo的程式碼後發現,原來是因為兩層的for迴圈,把圖片每個pixel都貼上去了,於是解決的方式就是多一個判斷式:if(ptr1[3*(x)]!=100 && ptr1[3*(x)+1]!=100 &&ptr1[3*(x)+1]!=100)把灰色以外的pixel複製進視訊裡面,這樣就解決啦。遊戲介紹:
一開始的畫面,要先偵測虛擬滑鼠的顏色

實際影片
心得與展望:
這是個蠻有趣的專題,比起其他專業科目的專題,這個專題算是簡單許多,不需要用到複雜的資料結構、資料庫、或是其他難度的程式碼,但是這個專題是要結合前幾次上課的技術,在加上專題的創意,才可以完成的,所以我覺得這次的專題很有趣。在專題demo時也參觀過其他組別的遊戲,雖然都是小遊戲,不過有很多創意,這也是這次專題所要學習的。而期末專題,也希望從這個專題去做延伸...能夠寫出更完美的專題。
2010年4月3日 星期六
HW03: Pixel-Level Processing in OpenCV
Extend the HW01.cpp program to generate four videos. The first, second, and third are videos with blue, green, and red colors, respectively.

The last one is the video with a logo image at the bottom-left corner.
Extend the above program such that the logo image can be moved from left to right in the displayed window.
左邊視窗的左下角有logo他不會動,右邊的則會動

The last one is the video with a logo image at the bottom-left corner.
Extend the above program such that the logo image can be moved from left to right in the displayed window.
左邊視窗的左下角有logo他不會動,右邊的則會動
2010年3月28日 星期日
HW04: Color Detection
Extend the HW01.cpp and HW04.cpp to generate a program that can change your black hair into red hair.
偵測黑色改成紅色

偵測黑色,分成上下,改變成其他的顏色
把黑色的改變成其他顏色,分4塊

Extend the above program such that you can draw a picture using your hair in another window.
因為我的房間太暗了,很多部是黑色的地方都偵測成黑色,剛好衣服上有紅色,所以我改成偵測紅色,以下是沒有動的時候,剛好畫出一個愛心
之後小小的移動一下,愛心就變形了
過程中,我先不求畫白底,先求能夠把pixel的值改變後就殘留,不要像視訊一樣畫面不斷更新。我照了我的想法去做,把視訊圖偵測到的地方在另外一個新開的視窗上一樣的位子改變BGR,但結果還是會像視訊一樣被更新畫面,就像只是偵測出哪裡有顏色並變色一樣。
我檢查了我變色部分的code覺得沒有錯,於是我把畫白底的code插進去,並且只讓他執行一次,並調整cvWaitKey的值,把它設大,發現一開始的時候,會先出現白底,後來又變成黑底,想不通黑底到底是怎麼跑出來的,而且後來效果還是會像視訊一樣被洗掉,找不到原因,想了很久後來上網找看有沒有類似的code可以參考時發現了一句話:cvCreateImage()
創造一個全黑的基本圖片.....原來問題出在這,因為在while迴圈裡面宣告他,所以會一直不斷的出現新的黑底+被偵測出來的顏色,難怪不會殘留。所以白底的cvCreateImage()只能執行一次。
再來就是要先畫出一張白色的底,我使用的是就把每個pixel的BGR設成255,255,255而且只能畫一次(不然會被洗掉),所以我在回圈內使用了一個int當開關,當跑過一次之後他就被設成0,用if來判斷是否執行過宣告白底的frame和畫白底圖的動作
if(i==1)
{
//產生視窗
frame2 = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 3);
for (int y=0; yheight; y++)
{
uchar* ptr2=(uchar*) (frame2->imageData +y*frame2->widthStep);
for (int x=0; xwidth; x++)
{
//畫白底
ptr2[3*x]=255;
ptr2[3*x+1]=255;
ptr2[3*x+2]=255;
}
}
我要的效果有了,白底+會殘留的變色,但我發現,殘留的變色部分會一直閃爍,而且是上下對稱的閃爍法,我就猜是cvFlivp在搞怪,果然,因為我的程式架構是先把殘留部分畫好,然後再flip(因為所抓到的影像是上下顛倒的),每一秒都會flip個好幾次,當然會閃爍。於是我就把flip先砍了,然後再多創一個frame,讓他不顯示出來,並且將他上下轉正,以這個frame為準來做顏色的偵測,而不是最一開始抓到的那張圖為準(如果用最一開始的那張圖為準偵測到的會是上下顛倒)。 過程差不多是這樣完成。
顏色偵測的演算法
TH1為基準值
ptr1:取出顏色的pixel值
refBlue /refGreen/ refRed:要偵測的顏色BGR
D:(算pixel的BGR和要偵測的顏色BGR差距)^2 開根號 (就像是算2點的距離一樣)
如果 sqrt(D) < d=" (ptr1[3*x]">
偵測黑色改成紅色
偵測黑色,分成上下,改變成其他的顏色
Extend the above program such that you can draw a picture using your hair in another window.
因為我的房間太暗了,很多部是黑色的地方都偵測成黑色,剛好衣服上有紅色,所以我改成偵測紅色,以下是沒有動的時候,剛好畫出一個愛心
我檢查了我變色部分的code覺得沒有錯,於是我把畫白底的code插進去,並且只讓他執行一次,並調整cvWaitKey的值,把它設大,發現一開始的時候,會先出現白底,後來又變成黑底,想不通黑底到底是怎麼跑出來的,而且後來效果還是會像視訊一樣被洗掉,找不到原因,想了很久後來上網找看有沒有類似的code可以參考時發現了一句話:cvCreateImage()
創造一個全黑的基本圖片.....原來問題出在這,因為在while迴圈裡面宣告他,所以會一直不斷的出現新的黑底+被偵測出來的顏色,難怪不會殘留。所以白底的cvCreateImage()只能執行一次。
再來就是要先畫出一張白色的底,我使用的是就把每個pixel的BGR設成255,255,255而且只能畫一次(不然會被洗掉),所以我在回圈內使用了一個int當開關,當跑過一次之後他就被設成0,用if來判斷是否執行過宣告白底的frame和畫白底圖的動作
if(i==1)
{
//產生視窗
frame2 = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 3);
for (int y=0; y
{
uchar* ptr2=(uchar*) (frame2->imageData +y*frame2->widthStep);
for (int x=0; x
{
//畫白底
ptr2[3*x]=255;
ptr2[3*x+1]=255;
ptr2[3*x+2]=255;
}
}
我要的效果有了,白底+會殘留的變色,但我發現,殘留的變色部分會一直閃爍,而且是上下對稱的閃爍法,我就猜是cvFlivp在搞怪,果然,因為我的程式架構是先把殘留部分畫好,然後再flip(因為所抓到的影像是上下顛倒的),每一秒都會flip個好幾次,當然會閃爍。於是我就把flip先砍了,然後再多創一個frame,讓他不顯示出來,並且將他上下轉正,以這個frame為準來做顏色的偵測,而不是最一開始抓到的那張圖為準(如果用最一開始的那張圖為準偵測到的會是上下顛倒)。 過程差不多是這樣完成。
TH1為基準值
ptr1:取出顏色的pixel值
refBlue /refGreen/ refRed:要偵測的顏色BGR
D:(算pixel的BGR和要偵測的顏色BGR差距)^2 開根號 (就像是算2點的距離一樣)
如果 sqrt(D) < d=" (ptr1[3*x]">
2010年3月7日 星期日
HW02
Extend HW01.cpp to generate three videos. The first one is gray-level video. The second one is the black and white video. The third one is a video with edges only.

IplImage* pImg = NULL;
IplImage* pImg2 = NULL;
//載入圖像
pImg=cvLoadImage("fruits.jpg");
//為圖像申請空間
pImg2 = cvCreateImage(cvSize(pImg->width,pImg->height), IPL_DEPTH_8U, 3);
//要轉成黑白的照片 channel要用1
gray = cvCreateImage(cvSize(pImg->width,pImg->height), IPL_DEPTH_8U, 1);
//直接取得大小寫法
pCannyImg = cvCreateImage(cvGetSize(pImg), IPL_DEPTH_8U, 1);
IplImage 的資料結構
cvCvtColor(pImg(src), gray(des), CV_BGR2GRAY);
//cvThreshold灰階轉黑白 63 , 255為門檻值,會因bit數不同而有不同的range,如果是8 bits就是0~255
cvThreshold( gray(src), bw(des), 63, 255, CV_THRESH_BINARY );
//canny邊緣檢測
cvCanny(gray(src), pCannyImg(des), 50, 150, 3);
把作業1和2融合,這樣就可以產生一個抓到影像的視窗 跟HW1用的複製方式不同
IplImage *frame;
IplImage *frame1;
frame = cvQueryFrame(capture); //抓到的影像顯示在frame上
frame1 = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 1);

右上角為原始圖像
左上為cvThreshold( pImg, pImg2, 127, 255, CV_THRESH_BINARY );
左下為cvThreshold( gray, bw, 127, 255, CV_THRESH_BINARY );
左上是把彩色照片直接改成黑白,左下是把灰階照片改為黑白
結果就是一個依然是彩色的(顏色較深的才會變成黑色 較淺的依然還是彩色) 一個是真正黑白
How many colors in the pImg2 image?
8種 因為他是彩色圖片 有RGB3個 所以有2^3=8種組合
cvResize() //改變大小
用法是 cvResize(pImg(src), pImg2(des) ,CV_INTER_LINEAR(使用的演算法));
演算法還有以下可選擇
pImg2 = cvCreateImage(cvSize(pImg->width*3.14,pImg->height*3.14), IPL_DEPTH_8U, 3);
(Optional) Study functions of cvDilate() and cvErode().
cvDilate()
cvErode()
IplImage* pImg = NULL;
IplImage* pImg2 = NULL;
//載入圖像
pImg=cvLoadImage("fruits.jpg");
//為圖像申請空間
pImg2 = cvCreateImage(cvSize(pImg->width,pImg->height), IPL_DEPTH_8U, 3);
//要轉成黑白的照片 channel要用1
gray = cvCreateImage(cvSize(pImg->width,pImg->height), IPL_DEPTH_8U, 1);
//直接取得大小寫法
pCannyImg = cvCreateImage(cvGetSize(pImg), IPL_DEPTH_8U, 1);
IplImage 的資料結構
IplImage//cvCvtColor彩色轉灰階
|-- int nChannels; // Number of color channels (1,2,3,4) 1是黑白 3是彩色
|-- int depth; // Pixel depth in bits: U是Unsigned S是Signed 以及用幾個bit編碼
| // IPL_DEPTH_8U, IPL_DEPTH_8S,
| // IPL_DEPTH_16U,IPL_DEPTH_16S,
| // IPL_DEPTH_32S,IPL_DEPTH_32F,
| // IPL_DEPTH_64F
|-- int width; // image width in pixels
|-- int height; // image height in pixels
cvCvtColor(pImg(src), gray(des), CV_BGR2GRAY);
//cvThreshold灰階轉黑白 63 , 255為門檻值,會因bit數不同而有不同的range,如果是8 bits就是0~255
cvThreshold( gray(src), bw(des), 63, 255, CV_THRESH_BINARY );
//canny邊緣檢測
cvCanny(gray(src), pCannyImg(des), 50, 150, 3);
把作業1和2融合,這樣就可以產生一個抓到影像的視窗 跟HW1用的複製方式不同
IplImage *frame;
IplImage *frame1;
frame = cvQueryFrame(capture); //抓到的影像顯示在frame上
frame1 = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 1);
Modify the vaue of the third parameter in cvThreshold( gray, bw, 127, 255, CV_THRESH_BINARY ); such that your face becomes black.
Find the differences between cvThreshold( gray, bw, 127, 255, CV_THRESH_BINARY );
cvThreshold( pImg, pImg2, 127, 255, CV_THRESH_BINARY );右上角為原始圖像
左上為cvThreshold( pImg, pImg2, 127, 255, CV_THRESH_BINARY );
左下為cvThreshold( gray, bw, 127, 255, CV_THRESH_BINARY );
左上是把彩色照片直接改成黑白,左下是把灰階照片改為黑白
結果就是一個依然是彩色的(顏色較深的才會變成黑色 較淺的依然還是彩色) 一個是真正黑白
How many colors in the pImg2 image?
8種 因為他是彩色圖片 有RGB3個 所以有2^3=8種組合
Use cvResize() function to extend HW02.cpp such that the displayed image is enlarged by a factor of 3.14.
用法是 cvResize(pImg(src), pImg2(des) ,CV_INTER_LINEAR(使用的演算法));
演算法還有以下可選擇
- CV_INTER_NN
- CV_INTER_LINEAR -used by default
- CV_INTER_AREA -
做局部放大適用 - CV_INTER_CUBIC
pImg2 = cvCreateImage(cvSize(pImg->width*3.14,pImg->height*3.14), IPL_DEPTH_8U, 3);
(Optional) Study functions of cvDilate() and cvErode().
cvDilate()
使用任意結構元素膨脹圖像
void cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL,
int iterations=1);
- src輸入圖像.
- dst輸出圖像.
- element用於膨脹的結構元素。若為 NULL, 則使用 3×3 長方形的結構元素
- iterations膨脹的次數
cvErode()
使用任意結構元素腐蝕圖像
void cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL,
int iterations=1);
- src輸入圖像.
- dst輸出圖像.
- element用於腐蝕的結構元素。若為 NULL, 則使用 3×3 長方形的結構元素
- iterations腐蝕的次數
2010年2月28日 星期日
HW01
覺得自己不上鏡,所以還是決定讓螢幕上像就好,dev c++和opencv2.0本來以為自己要重新設定好環境,沒想到學校已經全部都設定好了,自己有在家裡稍微設定過,只是沒想到需要webcan,當時跑出來的就只是一個框,也不知道能做啥就沒繼續了 把設定過程貼在下面,做個紀錄
在Dev-C++安裝OpenCV2.0
(1)下載 OpenCV-2.0.0a-win32.exe
(2)安裝OpenCV2.0在 C:\OpenCV2.0
(3)在DEV 工具/編譯器選項/編譯器 的編譯器設定組態中新增編譯器設定(加號按鈕)並命名為"OpenCV2.0"
(4)在連結器命令列中加入以下命令(前面框號要打勾)
-llibcxcore200 -llibcv200 -llibcvaux200 -llibhighgui200 -llibml200
(5)在DEV 工具/編譯器選項/目錄/二進位檔 加入:
C:\OpenCV2.0\bin
C:\Dev-Cpp\Bin
C:\Dev-Cpp\libexec\gcc\mingw32\3.4.2
(6) 在DEV 工具/編譯器選項/目錄/函式庫 加入:
C:\OpenCV2.0\lib
C:\Dev-Cpp\lib
(7)在 DEV 工具/編譯器選項/目錄/C引入檔 加入:
C:\OpenCV2.0\include\opencv
C:\Dev-Cpp\include
(8) 在DEV 工具/編譯器選項/目錄/C++引入檔 加入:
C:\OpenCV2.0\include\opencv
C:\Dev-Cpp\lib\gcc\mingw32\3.4.2\include
C:\Dev-Cpp\include\c++\3.4.2\backward
C:\Dev-Cpp\include\c++\3.4.2\mingw32
C:\Dev-Cpp\include\c++\3.4.2
C:\Dev-Cpp\include
(9) 在C:\OpenCV2.0\include\opencv中找到cxoperations.hpp檔
(10)找到檔中第66行部分程式碼如下
#else
#include
#if __GNUC__ >= 4
(11)將它改成如下程式碼並儲存
#else
#include
#if __GNUC__ >= 4 || __MINGW32__
(12) 每次開新的專案必須在專案中選擇新建的編譯器設定(OpenCV2.0)
以上轉自 http://yester-place.blogspot.com/2008/06/dev-copencv.html
後來使用了映射的功能 故意照螢幕 螢幕內的frame又在出現照到的東西 有陷入無窮盡的感覺
CvCapture : CvCapture *capture; //產生抓影像指標 CvCapture是一個Interface的資料結構,為一個資料結構的雛形,無任何的變數型別存在
IplImage : IplImage *frame; //產生一個圖形 名frame
cvCreateCameraCapture : capture=cvCreateCameraCapture( 0 ); //視訊的視頻流分配和初始化CvCapture結構 後面的數字如果有2台攝影機可以改成1 以此類推
cvNamedWindow:cvNamedWindow("Webcam",0); //創建視窗 命名frame的title並設定是否可伸縮 0可伸縮1則否
cvQueryFrame : frame = cvQueryFrame(capture); //抓到的影像顯示在frame上
cvShowImage : cvShowImage("Webcam", frame); //把frame的影像顯示到名為Webcam的視窗上
cvWaitKey : cvWaitKey(20); //每20毫秒抓一次影像
cvReleaseCapture : cvReleaseCapture(&capture); //釋放名為(CvCapture)capture指標的記憶體空間
cvDestroyWindow : cvDestroyWindow("Webcam"); //釋放名為Webcam的記憶體空間
cvFlip : cvFlip(frame2,frame3,0);//映射效果 frame2(src) frame3(des) 0為上下相反 1為左右相反
cvCloneImage : frame1 = cvCloneImage(frame); //frame1是複製frame的影像
訂閱:
文章 (Atom)

