简体   繁体   English

如何获取C++中mask中的所有像素

[英]How to get all pixels in mask in C++

In python, we can use such code to fetch all pixels under mask:在 python 中,我们可以使用这样的代码来获取 mask 下的所有像素:

src_img = cv2.imread("xxx")
mask = src_img > 50
fetch = src_img[mask]

what we get is a ndarray including all pixels matching condition mask.我们得到的是一个包含所有像素匹配条件掩码的 ndarray。 How to implement the same function using C++opencv?如何使用 C++opencv 实现相同的 function?

I've found that copyTo can select pixels under specified mask, but it can only copy those pixels to another Mat instead of what python did.我发现copyTo可以在指定掩码下复制 select 个像素,但它只能将这些像素复制到另一个Mat而不是 python 所做的。

This is not that straightforward in C++ (as expected).这在C++中并不是那么简单(正如预期的那样)。 That operation breaks down in further, smaller operations.该操作分解为更小的操作。 One way to achieve a std::vector with the same pixel values above your threshold is this, I'm using this test image:实现具有高于阈值的相同像素值的std::vector的一种方法是,我正在使用测试图像:

// Read the input image:
std::string imageName = "D://opencvImages//grayDog.png";
cv::Mat inputImage =  cv::imread( imageName );

// Convert BGR to Gray:
cv::Mat grayImage;
cv::cvtColor( inputImage, grayImage, cv::COLOR_RGB2GRAY );

cv::Mat mask;
int thresholdValue = 50;
cv::threshold( grayImage, mask, thresholdValue, 255, cv::THRESH_BINARY );

The above bit just creates a cv::Mat where each pixel above the threshold is drawn with a value of 255 , 0 otherwise.上面的位只是创建了一个cv::Mat ,其中每个高于阈值的像素都被绘制为255 ,否则为0 It is (one possible) equivalent of mask = src_img > 50 .它(一种可能)相当于mask = src_img > 50 Now, let's mask the original grayscale image with this mask.现在,让我们用这个遮罩遮盖原始灰度图像。 Think about an element-wise multiplication between the two cv::Mat s.考虑两个cv::Mat之间的逐元素乘法。 One possible way is this:一种可能的方法是这样的:

// Create grayscale mask:
cv::Mat output;
grayImage.copyTo( output, mask );

Now we have the original pixel values and everything else is zero.现在我们有了原始像素值,其他一切都为零。 Convenient, because we can find now the locations of the non-zero pixels:方便,因为我们现在可以找到非零像素的位置:

// Locate the non-zero pixel values:
std::vector< cv::Point > pixelLocations;
cv::findNonZero( output, pixelLocations );

Alright, we have a std::vector of cv::Point s that locate each non-zero pixel.好的,我们有一个cv::Pointstd::vector定位每个非零像素。 We can use this info to index the original grayscale pixels in the original matrix:我们可以使用此信息来索引原始矩阵中的原始灰度像素:

// Extract each pixel value using its location:
std::vector< int > pixelValues;
int totalPoints = (int)pixelLocations.size();

for( int i = 0; i < totalPoints; i++ ){
    // Get pixel location:
    cv::Point currentPoint = pixelLocations[i];

    // Get pixel value:
    int currentPixel = (int)grayImage.at<uchar>( currentPoint );
    pixelValues.push_back( currentPixel );

    // Print info:
    std::cout<<"i: "<<i<<" currentPoint: "<<currentPoint<<" pixelValue: "<<currentPixel<<std::endl;
}

You end up with pixelValues , which is a std::vector containing a list of all the pixels that are above your threshold.你最终得到pixelValues ,它是一个std::vector包含所有高于阈值的像素的列表。

Why do you hate writing loop?你为什么讨厌写循环?

I think this is the easiest way:我认为这是最简单的方法:

cv::Mat Img = ... //Where, this Img is 8UC1

// * In this sample, extract the pixel positions
std::vector< cv::Point > ResultData;

const unsigned char Thresh = 50;
for( int y=0; y<Img.rows; ++y )
{
    const unsigned char *p = Img.ptr<unsigned char>(y);
    for( int x=0; x<Img.cols; ++x, ++p )
    {
        if( *p > Thresh )
        {//Here, pick up this pixel's info you want.
            ResultData.emplace_back( x,y );
        }
    }
}

Because I received a nervous complaint, I add an example of collecting values .因为接到紧张的投诉,所以加了一个采集的例子。

In the following example, a mask image Mask is input to the process.在下面的示例中,掩码图像Mask被输入到流程中。

cv::Mat Img = ... //Where, this Img is 8UC1
cv::Mat Mask = ...; //Same size as Img, 8UC1

std::vector< unsigned char > ResultData;  //collect pixel values
for( int y=0; y<Img.rows; ++y )
{
    const unsigned char *p = Img.ptr<unsigned char>(y);
    const unsigned char *m = Mask.ptr<unsigned char>(y);
    for( int x=0; x<Img.cols; ++x, ++p, ++m )
    {
        if( *m ){   ResultData.push_back( *p ); }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM