joeforker
joeforker

Reputation: 41747

Is there an OpenCV function to copy all pixels under a mask into an array?

I would like to find the median color in a masked area in OpevCV. Does OpenCV have a function that takes an image and a mask, and puts only the pixels from the image where mask != 0 into an array or Mat?

Upvotes: 2

Views: 1020

Answers (3)

MaciekS
MaciekS

Reputation: 451

Post is quite old now, but - as there is still no function available in OpenCV - I implemented it for my app. Maybe will be useful for anyone...

cv::Mat extractMaskedData(cv::Mat data, cv::Mat mask)
{
    CV_Assert(mask.size()==data.size());
    CV_Assert(mask.type()==CV_8UC1);

    const bool isContinuous = data.isContinuous() && mask.isContinuous();
    const int nRows = isContinuous ? 1 : data.rows;
    const int nCols = isContinuous ? data.rows * data.cols : data.cols;

    const size_t pixelBitsize = data.channels() * (data.depth() < 2 ? 1 : data.depth() < 4 ? 2 : data.depth() < 6 ? 4 : 8);

    cv::Mat extractedData(0, 1, data.type());

    uint8_t* m;
    uint8_t* d;
    for (size_t i = 0; i < nRows; ++i) {
        m = mask.ptr<uint8_t>(i);
        d = data.ptr(i);
        for (size_t j = 0; j < nCols; ++j) {
            if(m[j]) {
                const cv::Mat pixelData(1, 1, data.type(), d + j * pixelBitsize);
                extractedData.push_back(pixelData);
            }
        }
    }

    return extractedData;
}

It returns cv::Mat(1,n,data.type()) where n is the number of non-zero elements in mask.

May be optimised by using image-type-specific d pointer (e.g. cv::Vec3f for CV_32FC3 instead of generic uint8_t* d together with const cv::Mat pixelData(1, 1, data.type(), d + j * pixelBitsize);.

Upvotes: 1

Bahramdun Adil
Bahramdun Adil

Reputation: 6079

You should use the following function of the Mat class to copy all the pixels into another Mat by using Mask:

Mat rst;
img.copyTo(rst, mask);

Upvotes: 1

shortcipher3
shortcipher3

Reputation: 1380

I don't know of any OpenCV function that creates a vector from masked values, I have written my own function to do that in the past, which you could do.

Alternatively you could calculate the histogram and find the median off of that, if your data is uint8.

Upvotes: 1

Related Questions