2012-03-29 59 views
7

拿到書「學習OpenCV的由O'Reilly不久前,從那時起我一直忙着將所有的示例代碼我看到有來自OpenCV的到JavaCV,通常後跟一點點我自己的修改也是如此。一直以來,我都試圖儘可能保持純OpenCV(C語言)代碼並避免使用Java。例如,我直接通過JavaCV中的OpenCV highgui包實現了所有的接口元素,而不是通過Java Swing。通過這樣做,我希望能夠以相對較短的順序學習OpenCV庫和一些C語言,並建立一個有用函數庫,如果我決定稍後切換到純OpenCV,我將能夠輕鬆地將其轉換爲C.轉換OpenCV的矩陣循環,從而JavaCV

無論如何,我對C小知識,並與指針打交道時,有時會遇到麻煩。書中建議下面的代碼作爲最佳由這意味着通過3信道矩陣進行迭代:

float sum(const CvMat* mat) { 
    float s = 0.0f; 
    for(int row=0; row<mat->rows; row++) { 
     const float* ptr = (const float*)(mat->data.ptr + row * mat->step); 
     for(col=0; col<mat->cols; col++) { 
      s += *ptr++; 
     } 
    } 
    return(s); 
} 

下面是該代碼所包含的說明:

當計算指針到基質,請記住,矩陣元素數據 是一個聯合。因此,當取消引用該指針時,必須指出聯合的正確的 元素才能獲得正確的指針類型。 Th en,要設置指針 ,必須使用矩陣的步驟元素。如前所述,步驟 元素以字節爲單位。爲了安全起見,最好以字節爲單位進行指針算術運算,然後將其轉換爲適當的類型,在本例中爲float。儘管CVMat結構具有與舊IplImage結構兼容的高度和寬度的概念,但我們仍然使用更新的行和列。最後,請注意,我們重新計算每行的ptr,而不是簡單地從頭開始,然後每次讀取增加指針 。釷是似乎過多,但由於數據與CvMat指針可能只是 指向一個更大的陣列內的投資回報率,也不能保證該數據將>跨行連續。

但我無法將其轉換爲JavaCV。 ptr字段(指針)似乎是一個浮動,這使我感到困惑。我認爲它實際上不是一個「指針」,而是每個像素值的添加值?或者它實際上是一個指針,它的s值是否找到給定行內所有列的總和?

無論如何,如果有人張貼我一些JavaCV代碼爲equivelent循環,我會感激。我知道還有其他方法可以訪問CvMat中的每個像素,但是AFAIK效率不高或者不準確。

+0

就我所見,從該例子可以看出,該矩陣是作爲二維灰度級浮點數據類型尋址的。所有的像素值被合計爲s,這將成爲累計亮度。 ptr實際上是一個指向任意點的數組的指針,'ptr [x]'等於'(const float *)(mat-> data.ptr + row * mat-> step)[x]; '。對於給定的像素,ptr被初始化並且遞增,所以'[x]'不是必須的,它只是簡單地用'*'解除引用,等於'[0]'。 – 2012-03-29 07:14:00

+0

@zom指針如何遞增?從我所瞭解的代碼中,指針被分配了像素的值?還是分配了像素的位置?如果是早先的情況,那麼當發生'ptr ++'操作時,分配的像素值不會增加,而不是使指針指向下一個像素?如果後面的情況,那麼何時和何地是分配給's'的像素的實際值?這麼多的問題。 – 2012-03-29 07:33:33

+0

請先閱讀本文:http://c-faq.com/ptrs/index.html – 2012-03-29 10:24:55

回答

6

您所提供的特定例子是最佳轉換爲Java作爲

float sum(CvMat mat) { 
    final int rows = mat.rows(); 
    final int cols = mat.cols(); 
    final int step = mat.step()/4; 
    FloatBuffer buf = mat.getFloatBuffer(); 
    float s = 0.0f; 
    for (int row = 0; row < rows; row++) { 
     buf.position(row * step); 
     for (int col = 0; col< cols; col++) { 
      s += buf.get(); 
     } 
    } 
    return s; 
} 
+0

謝謝山姆,很高興能從JavaCV開發者那裏得到答案!我已經解決了,但 – 2012-05-05 07:14:02

+0

好吧,太棒了!但無論如何你都應該接受答案,如果它回答你最初發布的問題是...... – 2012-05-05 09:15:07

0

這裏是一個變種我最終通過試驗&錯誤;用於迭代3通道矩陣並應用非常簡單的濾波器(我相信Samuel的示例已經很好地涵蓋了灰度值的求和)。

static IplImage setSaturate_sv(IplImage imgIn) { 
    IplImage imgOut = cvCloneImage(imgIn); 
    ByteBuffer pointer = imgOut.getByteBuffer(); 

    int height = imgIn.height(); 
    int width = imgIn.width(); 
    int widthStep = imgIn.widthStep(); 
    int nChannels = imgIn.nChannels(); 
    int rowIndex; 

    for (int row = 0; row < height; row++) { 
     rowIndex = row * widthStep; 
     for (int col = 0; col < width; col++) { 
      pointer.put((rowIndex + (col * nChannels) + 1), (byte)255); 
      pointer.put((rowIndex + (col * nChannels) + 2), (byte)255); 
      pointer.put((rowIndex + (col * nChannels) + 3), /* leave alone */); 
     } 
    } 
    return imgOut; 
}