how can i count all non-zero pixels within polygon area efficiently?

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&

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

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top