Home > Mobile >  Extract one colour channel from 4-dimensional cv::Mat
Extract one colour channel from 4-dimensional cv::Mat

Time:09-23

I'm working with OpenCV for a while and experiment with the DNN extension. My model has the input shape [1, 3, 224, 244] with pixel-depth uint8. So I put my m_inputImg which has 3-channels and 8 bit pixel depth in the function:

cv::dnn::blobFromImage(m_inputImg, m_inputImgTensor, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);

Now I'm interested in having a Idea how my input image "lay" inside the cv::Mat tensor. Theoretically I know how the tensor looks like, but I don't understand how OpenCV do it. So to understand this I want to extract one colour channel. I've tried this:

cv::Mat blueImg  = cv::Mat(cp->getModelConfigs().model[0].input.height,
                            cp->getModelConfigs().model[0].input.width,
                            CV_8UC3,
                            blob.ptr<uint8_t>(0, 0);

But what I get is something like that (see picture). I'm realy confused about that, can anybody help or has a good advice? Thanks

enter image description here

CodePudding user response:

cv::Size() will use the original image size. You are interpreting the data wrong. Here are 4 ways to interpret a 512x512 (cv::Size()) loaded blob-start from the lenna image:

input (512x512):

enter image description here

  1. blob-start as a 512x512 single channel image:

enter image description here

  1. blob-start as a 512x512 BGR image:

enter image description here

  1. blob-start as a 224x224 BGR image:

enter image description here

  1. blob-start as a 224x224 single channel:

enter image description here

here's the code:

int main()
{
    cv::Mat img = cv::imread("C:/data/Lenna.png"); // 8UC3
    cv::imshow("img", img);


    cv::Mat blob;
    cv::dnn::blobFromImage(img, blob, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);

    cv::Mat redImg = cv::Mat(img.rows,
        img.cols,
        CV_8UC1,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("blob 1", redImg);
    cv::imwrite("red1.jpg", redImg);

    cv::Mat redImg3C = cv::Mat(img.rows,
        img.cols,
        CV_8UC3,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("redImg3C", redImg3C);
    cv::imwrite("red3C.jpg", redImg3C);

    cv::Mat redImg224_3C = cv::Mat(224,
        224,
        CV_8UC3,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("redImg224_3C", redImg224_3C);
    cv::imwrite("redImg224_3C.jpg", redImg224_3C);

    cv::Mat redImg224_1C = cv::Mat(224,
        224,
        CV_8UC1,
        blob.ptr<uint8_t>(0, 0));

    cv::imshow("redImg224_1C", redImg224_1C);
    cv::imwrite("redImg224_1C.jpg", redImg224_1C);
    

    cv::waitKey(0);
}

Imho you have to do in your code:

cv::dnn::blobFromImage(m_inputImg, blob, 1.0, cv::Size(), cv::Scalar(), false, false, CV_8U);

cv::Mat blueImg  = cv::Mat(m_inputImg.rows,
                        m_inputImg.cols,
                        CV_8UC3,
                        blob.ptr<uint8_t>(0, 0);

OR

cv::dnn::blobFromImage(m_inputImg, blob, 1.0, cv::Size(cp->getModelConfigs().model[0].input.width , cp->getModelConfigs().model[0].input.height), cv::Scalar(), false, false, CV_8U);

cv::Mat blueImg  = cv::Mat(cp->getModelConfigs().model[0].input.height,
                        cp->getModelConfigs().model[0].input.width,
                        CV_8UC3,
                        blob.ptr<uint8_t>(0, 0);

In addition, here's the version of setting the spatial blob image size to a fixed size (e.g. the desired DNN input size):

    cv::Mat blob2;
    cv::dnn::blobFromImage(img, blob2, 1.0, cv::Size(224,224), cv::Scalar(), false, false, CV_8U);

    cv::Mat blueImg224_1C = cv::Mat(224,
        224,
        CV_8UC1,
        blob2.ptr<uint8_t>(0, 0));

    cv::imshow("blueImg224_1C", blueImg224_1C);
    cv::imwrite("blueImg224_1C.jpg", blueImg224_1C);

Giving this image: enter image description here

  • Related