简体   繁体   English

如何有效地计算每个多边形区域内的所有非零像素?

[英]How to count all non-zero pixels within each polygon area efficiently?

I want to calculate numbers of all white pixels within every polygon area efficiently.我想有效地计算每个多边形区域内所有白色像素的数量。

Given some processes:鉴于一些过程:

// some codes for reading gray image
// cv::Mat gray = cv::imread("gray.jpg");

// given polygons
// vector< vector<cv::Point> > polygons;

cv::Mat cropped;
cv::Mat mask = cv::Mat::zeros(gray.size(), CV_8UC1);
cv::fillPoly(mask, polygons, cv::Scalar(255));
cv::bitwise_and(gray, gray, cropped, mask);

cv::Mat binary;
cv::threshold(cropped, binary, 20, 255, CV_THRESH_BINARY);

So until now, we can get a image with multiple polygon areas(say we have 3 areas) which have white( with value 255) pixels.所以到目前为止,我们可以得到一个具有多个多边形区域(假设我们有 3 个区域)的图像,这些区域具有白色(值为 255)像素。 Then after some operations we expect to get a vector like:然后经过一些操作,我们希望得到一个向量,如:

// some efficient operations
// ...

vector<int> pixelNums;

The size of pixelNums should be same with polygons which is 3 here. pixelNums 的大小应与多边形相同,此处为 3。 And if we print them we may get some outputs like(the values are basically depended on the pre-processes):如果我们打印它们,我们可能会得到一些输出(这些值基本上取决于预处理):

index: 0; value: 120
index: 1; value: 1389
index: 2; value: 0

Here is my thought.这是我的想法。 Counting every pixels within every polygon area with help of cv::countNonZero , but I need to call it within a loop which I don't think it's a efficient way, isn't it?cv::countNonZero帮助下计算每个多边形区域内的每个像素,但我需要在循环中调用它,我认为这不是一种有效的方法,不是吗?

vector<int> pixelNums;
for(auto polygon : polygons)
{
  vector< vector<cv::Point> > temp_polygons;
  temp_polygons.push_back(polygon);

  cv::Mat cropped;
  cv::Mat mask = cv::Mat::zeros(gray.size(), CV_8UC1);
  cv::fillPoly(mask, temp_polygons, cv::Scalar(255));
  cv::bitwise_and(gray, gray, cropped, mask);

  cv::Mat binary;
  cv::threshold(cropped, binary, 20, 255, CV_THRESH_BINARY);

  pixelNums.push_back(cv::countNonZero(binary));
}

If you have some better ways, please kindly answer this post.如果您有更好的方法,请回复此帖子。 Here I say better way is consuming as little time as you can just in cpu environment.在这里我说better way是在 cpu 环境中消耗尽可能少的时间。

There are some minor improvements that can be done, but all of them combined should provide a decent speedup.有一些小的改进可以做,但所有这些结合起来应该可以提供不错的加速。

  1. Compute the threshold only once只计算一次阈值
  2. Make most operations on smaller images, using the bounding box of your polygon to get the region of interest对较小的图像进行大多数操作,使用多边形的边界框来获取感兴趣的区域
  3. Avoid unneeded copies in the for loop, use const auto&避免在 for 循环中出现不需要的副本,使用const auto&

Example code:示例代码:

#include <vector>
#include <opencv2/opencv.hpp>

int main()
{
    // Your image
    cv::Mat1b gray = cv::imread("path/to/image", cv::IMREAD_GRAYSCALE);

    // Your polygons
    std::vector<std::vector<cv::Point>> polygons
    {
        { {15,120}, {45,200}, {160,160}, {140, 60} },
        { {10,10}, {15,30}, {50,25}, {40, 15} },
        // etc...
    };

    // Compute the threshold just once
    cv::Mat1b thresholded = gray > 20;

    std::vector<int> pixelNums;
    for (const auto& polygon : polygons)
    {
        // Get bbox of polygon
        cv::Rect bbox = cv::boundingRect(polygon);

        // Make a new (small) mask 
        cv::Mat1b mask(bbox.height, bbox.width, uchar(0));
        cv::fillPoly(mask, std::vector<std::vector<cv::Point>>{polygon}, cv::Scalar(255), 8, 0, -bbox.tl());

        // Get crop
        cv::Mat1b cropped = thresholded(bbox) & mask;

        // Compute the number of white pixels only on the crop
        pixelNums.push_back(cv::countNonZero(cropped));
    }

    return 0;
}

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

相关问题 如何在OpenCV中计算连续的非零像素之间的零像素? - How to count zero pixels between consecutive non-zero ones in OpenCV? OpenCV - 二进制图像中所有非零像素的位置 - OpenCV - locations of all non-zero pixels in binary image 如何清除霓虹灯中的第一条非零通道? - How to clear all but the first non-zero lane in neon? SIMD / SSE:如何检查所有矢量元素都不为零 - SIMD/SSE: How to check that all vector elements are non-zero OpenCV:查找二进制Mat图像的所有非零坐标 - OpenCV: Find all non-zero coordinates of a binary Mat image 获取密集 Eigen::Matrix 对象的所有非零值 - Get all non-zero values of a dense Eigen::Matrix object 根据另一个 Mat 的非零像素选择 cv::Mat 的一部分? - Select part of a cv::Mat based on non-zero pixels of another Mat? 如何强制编译器为未初始化的变量设置非零值? - How to force compiler to set a non-zero value to uninitialized variables? C ++:如何在非零大小的地图中初始化矢量 - C++: how to initialize vector in map with non-zero size 本征库:将SparseMatrix * Row *中的所有非零元素设置为零 - Eigen Library: Setting all Non-Zero elements in a SparseMatrix *Row* to Zero
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM