opencv 如何在C++中获得所有像素

vof42yt1  于 2022-11-24  发布在  其他
关注(0)|答案(2)|浏览(160)

在python中,我们可以使用这样的代码来获取mask下的所有像素:

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

我们得到的是一个ndarray,它包含了所有匹配条件掩码的像素。2如何用C++opencv实现同样的功能呢?
我发现copyTo可以选择指定掩码下的像素,但它只能将这些像素复制到另一个Mat,而不是python所做的。

yduiuuwa

yduiuuwa1#

C++中,这并不像预期的那样简单。该操作分解为更进一步的更小的操作。一种实现std::vector的方法是使用高于阈值的相同像素值,我使用this测试图像:

// 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 );

上面的位只是创建了一个cv::Mat,其中每个高于阈值的像素都用255的值绘制,否则用0的值绘制。它(可能)等效于mask = src_img > 50。现在,让我们用这个遮罩来遮罩原始灰度图像。考虑两个cv::Mat之间的元素乘法。一种可能的方法是:

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

现在我们有了原始的像素值,其他的都是零。这很方便,因为我们现在可以找到非零像素的位置:

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

好了,我们有一个cv::Pointstd::vector来定位每个非零像素,我们可以用这个信息来索引原始矩阵中的原始灰度像素:

// 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;
}

最后得到pixelValues,它是一个std::vector,包含了所有超过阈值的像素的列表。

hfwmuf9z

hfwmuf9z2#

为什么你讨厌写循环?
我想这是最简单的办法:

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 );
        }
    }
}

因为我收到了一个神经质的投诉,我添加了一个收集的例子。
在以下示例中,将遮罩图像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 ); }
    }
}

相关问题