2017-07-27 57 views
3

我知道如何使用Vec3b訪問三個通道cv::Mat。但現在我有一個n頻道cv::Matn是不恆定的(使用cv::Vec<uchar, n>)。我現在如何訪問cv::Mat頻道?如何在opencv中訪問Mat的第n個通道?

+0

@DimChtz的答案是完美的,你也可以使用'.toList()'你的墊子和訪問要素。 –

+1

使用['cv :: Mat :: ptr'](http://docs.opencv.org/3.1.0/d3/d63/classcv_1_1Mat.html#a47ead5654d6577e63a3e154b57976a36)。 –

+0

@RickM。我認爲你正在和Java混合起來。 C++ API中沒有這樣的東西。你提到的答案遠非完美,因爲它要求硬編碼的通道數 - 所以它完全無法解決問題。 –

回答

2

比方說n = 10,我們想要訪問像素(i, j)4th頻道。這裏有一個簡單的例子:

typedef cv::Vec<uchar, 10> Vec10b; 

// .... 

// Create the mat 
cv::Mat_<Vec10b> some_mat; 

// Access 4th channel 
uchar value = some_mat.at<Vec10b>(i,j)(4); 

// or 
uchar value = some_mat.at<Vec10b>(i,j)[4]; 

希望這可以幫助你。注意你可以省略typedef這一行,我只是覺得這樣更容易。

+0

謝謝你的回答,但這是行不通的,因爲n沒有在編譯時定義,當我在cv :: Vec 中使用n時,它說「表達式必須有一個常數值」。 – ahamid555

+0

@ ham.a是'cv :: Vec '不會工作,AFAIK這是不可能在opencv。我相信我的回答是你得到的最好的解決方案(使用opencv)。 – DimChtz

+0

所以我認爲唯一的解決辦法是使用std :: vector 。 – ahamid555

0

爲了能夠處理任意數量的通道,您可以使用cv::Mat::ptr和一些指針算術。

例如,僅支持CV_8U數據類型將是如下一個簡單的方法:

#include <opencv2/opencv.hpp> 
#include <cstdint> 
#include <iostream> 

inline uint8_t get_value(cv::Mat const& img, int32_t row, int32_t col, int32_t channel) 
{ 
    CV_DbgAssert(channel < img.channels()); 
    uint8_t const* pixel_ptr(img.ptr(row, col)); 
    uint8_t const* value_ptr(pixel_ptr + channel); 
    return *value_ptr; 
} 

void test(uint32_t channel_count) 
{ 
    cv::Mat img(128, 128, CV_8UC(channel_count)); 
    cv::randu(img, 0, 256); 

    for (int32_t i(0); i < img.channels(); ++i) { 
     std::cout << i << ":" << get_value(img, 32, 32, i) << "\n"; 
    } 
} 

int main() 
{ 
    for (uint32_t i(1); i < 10; ++i) { 
     test(i); 
    } 

    return 0; 
}