What's the index type in channels of cv::Mat::at?

When I try to assign the elements in cv::Mat to a single unsigned char array one by one, the channel index does not know how to define the type and the following code does not compile with the variable k. How can I change it to assign it correctly?

/**
* @brief       OpenCV图像转一位数组
* @details     This is the detail description.
* @param[in]   srcImg 1289*720*3大小的BGR图像,uchar类型.
* @param[out]  dst 1289*720*3大小的一维数组.
* @return      返回值
*/
void convertCVToMatrix(cv::Mat &srcImg, unsigned char dst[2332800]) {
    CV_Assert(srcImg.total()==2332800 && srcImg.type() == CV_8UC3);
    size_t num = 0;
    for (int k = 0; k< srcImg.channels(); k++) {
        for (int j = 0; j < srcImg.cols; j++) {
            for (int i= 0; i < srcImg.rows; i++) {
                dst[num++] = srcImg.at<uchar>(i, j)[k];
            }
        }
   }
}

this returns a single uchar value, you cannot index that at all.

you could try with srcImg.at<Vec3b>(i, j)[k] ,
but in the end, please stop writing code like that. a simple

memcpy(dst, src.data, (1289*720*3));

should replace your whole function

OP’s code is weird. it transposes the data, like np.transpose(..., (2,1,0)). it produces separate planes, and the values are arranged column-major.

OP probably has no idea what’s going on but I think it should be pointed out.

1 Like

thanks very much,the above one-dimensional array is a column-major storage array, but a direct copy memcpy as you have provided would require some modification

void convertCVToMatrix(cv::Mat &srcImg, unsigned char dst[2332800]) {
    CV_Assert(srcImg.total()==2332800 && srcImg.type() == CV_8UC3);
    cv::Mat channels[3];
    cv::split(srcImg.t(), channels);
    size_t elems = 2332800 / srcImg.channels();
    memcpy(dst, channels[2].data, elems * sizeof(uchar));              //copy channel[2] to the red channel
    memcpy(dst + elems, channels[1].data, elems * sizeof(uchar));      // green
    memcpy(dst + 2 * elems, channels[0].data, elems * sizeof(uchar));  // blue
}

Is this the correct way to write it? @crackwitz @berak

cv::split() will separate the data into planes…

I think you can save the memcpy if you construct the three Mats in channels to be non-owning Mats directly on the destination buffer memory.

none of that takes care of row-major to column-major conversion. do you need that operation or was that just an error in your earlier code?

everyone, OpenCV included, uses row-major, i.e. elements in memory are arranged like reading text, left to right, then next row.

definitely not so. . . . .

The scenario I used was indeed coloum major and the above code passed my test later. Thanks for your advice and answers