討論區快速選單
知識庫快速選單
CSSLP認證,將資安落實在軟體開發中 網路投保旅行平安險
[ 回上頁 ] [ 討論區發言規則 ]
glut 教學 - 使用 Webcam Texture
更改我的閱讀文章字型大小
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2146 | 人氣 89850 | 評價 10080 | 評價/貼文 4.7 | 送出評價 78 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2016/12/31 下午 10:49:21
可執行的範例程式 -
http://mahty.myftp.org/glutWebcamTex/glutWebcamTest_bin.rar

glutWebcamTex DLL (with the .lib file, header file and .dll file ) -
http://mahty.myftp.org/glutWebcamTex/glutWebcamTex_lib.rar

範例程式的原碼 -
http://mahty.myftp.org/glutWebcamTex/glutWebcamTest.rar

glutWebcamTex library 的原碼 -
http://mahty.myftp.org/glutWebcamTex/glutWebcamTex.rar

(... 今天累了, 說明後補 ...)
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2146 | 人氣 89850 | 評價 10080 | 評價/貼文 4.7 | 送出評價 78 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/1/2 上午 02:31:27
先前有位網友問了一個關於 "如何擷取 Webcam 並上載到 OpenGL texture" 的問題. 這剛好是一件我想要去做很久的事, 狠心一次過把東西做到底.

先說一下為啥這是個好主意. 也許你會覺得, 把 Webcam視頻 貼上三維模型 看一陣子就厭了 用途沒多大. 不過, 這樣做的意義 不單是為了做貼圖, 更是為了 動用GPUL勁的同步運算效能 去做 Image Processing. CPU不夠快去執行的圖學演算法, 實在是多著的. 換成以GPU去執行的話, 你的電腦輕輕鬆鬆地已可效能十倍. 這也是為啥妨間的 library (如 OpenCV, Unity, Direct3D...) 也有這個功能.

@@? Arr... 既然妨間的 library 已有這種功能, 為啥還要再寫一次?? 太閒了嗎?! ^^", 這是出於效能和原碼管理的考慮. 前面說過, 這樣做是為是效能, 妨間的 library 有它們自身的市場定位考慮, 效能嘛... 一般也不會作為首要目標地為你"推到盡. 再者, 雖說妨間有 library 提供這功能, 但是, 它們同時也附帶一大堆你不需要的東西, 亂七八糟的header files; 更甚是, 就連程式的流程 也需要用家大幅改變去配合. ^^y--~cC, 單是 亂七八糟的header files一項, 我已經馬上 say no 了, 徨論影響更深的另外兩項.

嗯嗯... 好好, 這麼說, 我的包裝 又實在有多簡約呢? 這個嘛... 仔細的後面再說, 實戰使用, 除了 一個 .h檔 + 一個 .lib檔 + 一個 .dll檔 之外, 下面就是全部需要添加的原碼 (假設你本來是在用 glut 的話) ...

#include "glutWebcamTex.h"

// ..

void main( int argc, const char** argv )
{
  glutCreateWebcam(mode);
  glutFrameReadyFunc( FrameReady );
  glutWebcamLoop();

  //..

  glutMainLoop();
}

void FrameReady( double SampleTime, void *pBuffer, long BufferLen )
{
  buf0 = pBuffer;
  glutPostRedisplay();
}

void display()
{
  if( buf0 )
  {
    glBindTexture(GL_TEXTURE_2D, tex0 );
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, glutFrameWidth(), glutFrameHeight(),
    GL_BGR_EXT, GL_UNSIGNED_BYTE, buf0 );
  }

  // ...
}


作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2146 | 人氣 89850 | 評價 10080 | 評價/貼文 4.7 | 送出評價 78 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/1/3 上午 01:27:30
Mmm... 文字看多了, 開始暈眩了吧. 換一個看的, 上文提到有一個 可執行的範例程式 ( http://mahty.myftp.org/glutWebcamTex/glutWebcamTest_bin.rar ), rar檔入面有三個檔案, 分別是glutWebcamTest.exe, glutWebcamTex.dll 和 glut32.dll. 解壓縮之後, 就可直接執行 glutWebcamTest.exe . 一切正常的話, 就會出現一glut視窗, glut視窗會顯示 一貼了webcam視頻的長方形 沿著Y軸自轉, console視窗會報告你的webcam所有可用的輸出格式. 就如下圖...

  http://mahty.myftp.org/glutWebcamTex/screen.png

除此之外, 在 glut視窗...
  按 'p' 鍵, 就會帶出 webcam的圖像設定頁.
  按 'o' 鍵, 就會帶出 webcam的視訊格式設定頁.

圖像設定 和 視訊格式設定 也可以隨便改動. 不過, 請注意一點, 圖像設定改動 是實時的, 即 改動圖像設定 視訊會馬上有反應; 但 視訊格式設定改動, 需要先暫定視訊接收, 到 視訊格式設定頁 關了, 改動才會生效 (^^" 別慌, 那不是壞了 ).

(... 又累了, 說明再後補 ...)
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2146 | 人氣 89850 | 評價 10080 | 評價/貼文 4.7 | 送出評價 78 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/1/3 上午 01:29:06
實戰使用我寫的 Webcam library ( glutWebcamTex ), 你需要三個檔案 一個 .h檔, 一個 .lib檔 和 一個 .dll檔 ( 即上文提及的http://mahty.myftp.org/glutWebcamTex/glutWebcamTex_lib.rar ). 用法跟 glut相同, 就是把 .h檔 和 .lib檔 放在 編譯器能找到的路徑 (最直接的做法 就是都放在專案資料夾), 然在在原碼 #include .h檔. 發佈.exe時, 把 .dll檔和 .exe檔放在同一資料夾就可以. 最下面就是這 library 的 .h檔, 只有 expose 了七個函數.

glutCreateWebcam(int mode=0, int color_space = GLUTWEBCAM_CONVERT_TO_RGB24) 是 用來呼叫 DirectShow 程序, 跟系統協商好 webcam 將會如何被應用, 並準備好 width 和 height 的資料之後, 才會完結.
  - mode 是視訊格式設定, 那數值代表什麼格式, 每webcam 也不同的, 仔細資料會在 console報告. mode 0 一般就是系統的建議格式.
  - color_space 是用設定 是否強制轉換 像素資料 成RGB24,
    - GLUTWEBCAM_CONVERT_TO_RGB24 代表強制轉換,
    - GLUTWEBCAM_NO_CONVERTION 代表 不作任何修改 直接回傳webcam的輸出.
"."y--~cC , mmm, 為啥你會想要 "webcam的直接輸出" 嘛..., 雖說 本library的目標 是為了 webcam texture, 但它實在跟繪圖並無關係, 甚至, 連視窗也並沒開 亦不需要, 乾乾淨淨的. 提供 webcam的直接輸出, 乾淨到底呀.


void glutFrameReadyFunc(), 是用來註冊 callback函數, 格式如下...

  void FrameReady(double SampleTime, void *pBuffer, long BufferLen)

. 當 library 收到新的 frame, 就會呼叫這callback函數, SampleTime 是該 frame 的時間標籤, pBuffer是像素資料, BufferLen 是pBuffer的大小 (以 byte 去算). 注意!!! 注意!!! 這library在多執行緒方面下了少許功夫, 由資料擷取 到轉換, 也不會干擾到你的主程式的; 這也代表這callback 並不在你的執行緒上, 你不可以用單執行緒的思路去管理它. ^^ 不過, 主要的影響只是 你不能在這callback裡 呼叫 OpenGL函數而已, 影響不大的.


glutFrameWidth() 和 glutFrameHeight() 回傳視訊的 width 和 Height.

glutWebcamLoop() 開始擷取 webcam 視訊.

glutWebcamPropertyPage() 打開 圖像設定頁.

glutWebcamOutputPropertyPage() 打開 視訊格式設定頁.


#ifndef GLUTWEBCAMTEX_H
#define GLUTWEBCAMTEX_H

#include <windows.h>

#ifdef GLUTWEBCAMTEX_EXPORTS
#define GLUTWEBCAMTEX_API __declspec(dllexport)
#pragma message( "==============> exporting glutWebcamTex.dll" )
#else
#define GLUTWEBCAMTEX_API __declspec(dllimport)
#pragma comment(lib, "glutWebcamTex.lib")
#endif

#define GLUTWEBCAM_CONVERT_TO_RGB24 0
#define GLUTWEBCAM_NO_CONVERTION 1

extern "C" GLUTWEBCAMTEX_API void APIENTRY glutFrameReadyFunc(void (__cdecl *func)(double SampleTime, void *pBuffer, long BufferLen));
extern "C" GLUTWEBCAMTEX_API int APIENTRY glutCreateWebcam( int mode=0, int color_space = GLUTWEBCAM_CONVERT_TO_RGB24 );
extern "C" GLUTWEBCAMTEX_API int APIENTRY glutFrameWidth();
extern "C" GLUTWEBCAMTEX_API int APIENTRY glutFrameHeight();
extern "C" GLUTWEBCAMTEX_API void APIENTRY glutWebcamLoop();

extern "C" GLUTWEBCAMTEX_API void APIENTRY glutWebcamPropertyPage();
extern "C" GLUTWEBCAMTEX_API void APIENTRY glutWebcamOutputPropertyPage();

#endif
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2146 | 人氣 89850 | 評價 10080 | 評價/貼文 4.7 | 送出評價 78 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/1/3 上午 01:51:28
整個範例程式的原碼, 就是只有下面的126行.

#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>

#include "glutWebcamTex.h"

GLuint tex0;
void *buf0 = NULL;
double angle = 0;

void display();
void keyboard( unsigned char key, int x, int y );
void special( int key, int x, int y );
void FrameReady( double SampleTime, void *pBuffer, long BufferLen );

#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
#endif

void main( int argc, const char** argv )
{
  int mode = 0;
  if( argc>=2 )
    mode = atoi( argv[1] );

  glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB|GLUT_ALPHA | GLUT_DEPTH );
  glutInitWindowSize( 640, 480 );
  glutCreateWindow( "glutWebcamTest" );
  glutDisplayFunc( display );
  glutKeyboardFunc( keyboard );
  glutSpecialFunc( special );

  glutCreateWebcam(mode); // 設定 webcam
    glutFrameReadyFunc( FrameReady ); // 設定接收視訊的callback函數為 FrameReady()
    glGenTextures( 1, &tex0 );
     glBindTexture( GL_TEXTURE_2D, tex0 );
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

     // glutFrameWidth() 和 glutFrameHeight() load texture 時會需要用到的.
     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, glutFrameWidth(), glutFrameHeight(),
     0, GL_BGR_EXT, GL_UNSIGNED_BYTE, 0 );

  glutWebcamLoop(); // 開始擷取 webcam視訊

  typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int );
  PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
  wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT");
  wglSwapIntervalEXT(1);

  glutMainLoop();
}

// 這是用來接數視訊的函數
void FrameReady( double SampleTime, void *pBuffer, long BufferLen )
{
  buf0 = pBuffer; // 記著記著像素資料的指標, 等待 display() 時上載到 texture.
  glutPostRedisplay();
}

void display()
{
  if( buf0 )
  {
    int w, h;
    glBindTexture(GL_TEXTURE_2D, tex0 );
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);

    // glTexSubImage2D() 比 glTexImage2D() 快少許的, 如果視訊解像度沒變
    // 的話, 用 glTexSubImage2D() 上載資料.
    if( w==glutFrameWidth() && h==glutFrameHeight() )
     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, glutFrameWidth(), glutFrameHeight(),
     GL_BGR_EXT, GL_UNSIGNED_BYTE, buf0 );
    else
     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, glutFrameWidth(), glutFrameHeight(), 0,
     GL_BGR_EXT, GL_UNSIGNED_BYTE, buf0 );

    buf0 = NULL; // 同一個 frame, 上載一次就夠了. 上載完之後, buf0 設 NULL, 一併用作標示 "frame已上載".
  }


  GLint viewport[4];
    glGetIntegerv( GL_VIEWPORT, viewport );

  glClearColor( .1, .2, .3, 1 );
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective( 60, double(viewport[2])/viewport[3], .1, 100 );
  glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt( 0,0,2, 0,0,0, 0,1,0 );

    glRotatef( angle, 0, 1, 0 );
    angle+=1;

    double ratio = double(glutFrameHeight())/glutFrameWidth();
    glBindTexture( GL_TEXTURE_2D, tex0 );
    glEnable( GL_TEXTURE_2D );
    glBegin( GL_QUADS );
     glTexCoord2d( 0,0 ); glVertex3f( -1, -ratio, 0 );
     glTexCoord2d( 1,0 ); glVertex3f( 1, -ratio, 0 );
     glTexCoord2d( 1,1 ); glVertex3f( 1, ratio, 0 );
     glTexCoord2d( 0,1 ); glVertex3f( -1, ratio, 0 );
    glEnd();

  glutSwapBuffers();
  glutPostRedisplay();
}

void keyboard( unsigned char key, int x, int y )
{
  switch( key )
  {
    case 'P':
    case 'p':
     glutWebcamPropertyPage(); // 打開webcam的圖像設定頁
    break;

    case 'O':
    case 'o':
     glutWebcamOutputPropertyPage(); // 打開webcam的視訊格式設定頁
    break;

    default:
    break;
  }
}

void special( int key, int x, int y )
{
  printf( "%i\n", key );
}
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2146 | 人氣 89850 | 評價 10080 | 評價/貼文 4.7 | 送出評價 78 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/1/3 上午 02:23:33
最後簡單說說這 library 的原碼吧 ( 即上文提及的 http://mahty.myftp.org/glutWebcamTex/glutWebcamTex.rar ).

原碼呢... 我是盡量克制 盡量簡約了, 但看起來還是令人十分困擾. 主要就是 DirectShow (這全球市場還是被Microsoft壟斷中的產物) 滿滿的都是反人類文化的架構. 還好的就是, 那時Microsoft的壟斷, 是真壟斷, 那時廠商們也都乖乖地 遵守那架構去編驅動程式, 然後承襲至今. 因此, 我們才可以用一個程序 讀不同生產商的webcam. Mmm... before you might get confused, 反人類文化架構 跟 共通架構, 兩者並無必然關係; 如果 DirectShow的架構 不是這麼反人類文化, 說不定能跑更遠喎.

貼出library的原碼, 本意是方便參考. 不過, 如果你是有心有力 打算試著去修改的話, 試試也無妨的, 就是別太為難自己就好了.

^o^y--cC 說明補完, 完成, 之乎者也.
 板主 : 白老鼠(Gary)
 > OpenGL - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - OpenGL - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
OpenGL
1 白老鼠(Gary) 2710 
2 CROMAYEN2000 1530 
3 aming 500 
4 東昇 380 
5 PLAYER 120 
6 富伯 110 
7 qq 100 
8 NDark 80 
9 ozzy 60 
10 simula 60 
OpenGL
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2018 程式設計俱樂部 http://www.programmer-club.com.tw/
0.03125