2013-10-23 102 views
0

我想獲取一個OpenGL圖像並將其提供給OpenCV進行分析(作爲OpenCV算法的模擬器),但我沒有找到關於它的很多信息,我只能找到是另一種方式(在OpenGL中放置一個OpenCV圖像)。有人可以解釋如何做?OpenCV + OpenGL - 獲取OpenGL圖像作爲OpenCV攝像機

編輯:

我將模擬上的機器人的頂部上的照相機,所以我將在實時3D環境渲染和在一個Qt GUI顯示它給用戶。我會讓用戶選擇使用一個真實的攝像頭反饋或一個模擬的3D場景(隨着機器人移動而改變),並且OpenCV算法對於兩個輸入都是相同的,因此用戶可以測試他的代碼而不必使用真實的機器人始終。

+1

「OpenGL圖像」在這種情況下意味着什麼?紋理?一個場景呈現給framebuffer?一個場景呈現給一些離屏緩衝區? –

+0

@MatsPetersson我用更多的解釋更新了這個問題 – mFeinstein

+0

@MatsPetersson我猜它是「一個渲染到framebuffer的場景」選項,要更清楚。我還在深入學習OpenGL,所以我試圖找到更多關於所有必讀內容的信息,而且我找不到太多的東西......任何方向都是最受歡迎的! – mFeinstein

回答

2

您可能正在尋找功能glReadPixels。它將下載OpenGL當前顯示的任何內容到緩衝區。

unsigned char* buffer = new unsigned char[width*height*3]; 
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); 
cv::Mat image(height, width, CV_8UC3, buffer); 
cv::imshow("Show Image", image); 

對於OpenCV的你可能還需要翻轉並轉換爲BGR爲好。

編輯:由於只使用glReadPixels是不是一個非常有效的方式做到這一點,這裏是使用幀緩存和像素緩衝對象有效地傳送一些示例代碼: How to render offscreen on OpenGL?

+0

我是OpenCV的新手,是BGR特定的東西還是隻是RGB向後? – mFeinstein

+1

只需要注意,glReadPixels是使300美元的圖形卡產生5fps的極好方式,因爲每次調用glReadPixels時,圖形芯片都將不得不消耗整個工作流程。如果你聽說過CPU中的「branch mispredicts」,這是同樣的事情,但是10000倍差。 –

+0

@MatsPetersson該死的,它看起來像一個乾淨的解決方案...你有任何bettert選項,也許我可以搜索一些代碼? – mFeinstein

2

我在之前的研究項目中做過。這裏沒有太多困難。

,你所要做的主要是:

  • 使從OpenGL的讀一些預分配內存緩衝區紋理;
  • 應用一些幾何變換(翻轉X和/或Y座標)來說明OpenGL和OpenCV之間可能不同的座標系。這是一個細節,但它有助於可視化(提示:使用內含F字母的紋理快速找到需要翻轉的座標!);
  • 您可以直接在預分配的內存緩衝區周圍構建OpenCV對象,然後直接對其進行處理或將其複製到其他矩陣對象並對其進行處理。

正如在另一個答案中指出的,讀取OpenGL紋理是調用glRead()函數的一個簡單問題。 你得到的通常是3或4個通道,每個數據8位(RGB/RGBA - 每通道8位),儘管它可能取決於你實際的OpenGL上下文。

如果顏色對您很重要,您可能需要(但不是必需的)將RGB圖像數據轉換爲BGR格式(藍 - 綠 - 紅)。由於歷史原因,這是OpenCV中默認的顏色通道排序。 例如,您可以通過致電cv::cvtColor(source, dest, cv::COLOR_RGB2BGR)來完成此操作。

+0

我會嘗試一下,看看它是怎麼回事,謝謝! – mFeinstein

0

我需要爲我的研究。 我接受了littleimp的建議,但修復顏色和翻轉圖像花費寶貴的時間來弄清楚。

這就是我最終的結果。

typedef Mat Image ; 

typedef struct { 
    int width; 
    int height; 
    char* title; 
    float field_of_view_angle; 
    float z_near; 
    float z_far; 
} glutWindow; 

glutWindow win; 

Image glutTakeCVImage() { 
    // take a picture within glut and return formatted 
    // for use in openCV 
    int width = win.width; 
    int height = win.height; 
    unsigned char* buffer = new unsigned char[width*height*3]; 
    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); 
    Image img(height, width, CV_8UC3, buffer); 
    Image flipped_img; 
    flip(img,flipped_img,0); 
    Image BGR_img; 
    cvtColor(flipped_img,BGR_img, COLOR_RGB2BGR); 
    return BGR_img; 
} 

我希望有人認爲這有用。